Started to merge @ZobyTwo cmake branch
This commit is contained in:
326
thirdparty/SDL/src/SDL.c
vendored
Normal file
326
thirdparty/SDL/src/SDL.c
vendored
Normal file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Initialization code for SDL */
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_revision.h"
|
||||
#include "SDL_fatal.h"
|
||||
#include "SDL_assert_c.h"
|
||||
#include "haptic/SDL_haptic_c.h"
|
||||
#include "joystick/SDL_joystick_c.h"
|
||||
|
||||
/* Initialization/Cleanup routines */
|
||||
#if !SDL_TIMERS_DISABLED
|
||||
extern void SDL_StartTicks(void);
|
||||
extern int SDL_TimerInit(void);
|
||||
extern void SDL_TimerQuit(void);
|
||||
#endif
|
||||
#if defined(__WIN32__)
|
||||
extern int SDL_HelperWindowCreate(void);
|
||||
extern int SDL_HelperWindowDestroy(void);
|
||||
#endif
|
||||
|
||||
|
||||
/* The initialized subsystems */
|
||||
static Uint32 SDL_initialized = 0;
|
||||
static Uint32 ticks_started = 0;
|
||||
|
||||
|
||||
int
|
||||
SDL_InitSubSystem(Uint32 flags)
|
||||
{
|
||||
#if !SDL_VIDEO_DISABLED
|
||||
/* Initialize the video/event subsystem */
|
||||
if ((flags & SDL_INIT_VIDEO) && !(SDL_initialized & SDL_INIT_VIDEO)) {
|
||||
if (SDL_VideoInit(NULL) < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_initialized |= SDL_INIT_VIDEO;
|
||||
}
|
||||
#else
|
||||
if (flags & SDL_INIT_VIDEO) {
|
||||
SDL_SetError("SDL not built with video support");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_AUDIO_DISABLED
|
||||
/* Initialize the audio subsystem */
|
||||
if ((flags & SDL_INIT_AUDIO) && !(SDL_initialized & SDL_INIT_AUDIO)) {
|
||||
if (SDL_AudioInit(NULL) < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_initialized |= SDL_INIT_AUDIO;
|
||||
}
|
||||
#else
|
||||
if (flags & SDL_INIT_AUDIO) {
|
||||
SDL_SetError("SDL not built with audio support");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_TIMERS_DISABLED
|
||||
/* Initialize the timer subsystem */
|
||||
if (!ticks_started) {
|
||||
SDL_StartTicks();
|
||||
ticks_started = 1;
|
||||
}
|
||||
if ((flags & SDL_INIT_TIMER) && !(SDL_initialized & SDL_INIT_TIMER)) {
|
||||
if (SDL_TimerInit() < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_initialized |= SDL_INIT_TIMER;
|
||||
}
|
||||
#else
|
||||
if (flags & SDL_INIT_TIMER) {
|
||||
SDL_SetError("SDL not built with timer support");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
/* Initialize the joystick subsystem */
|
||||
if ((flags & SDL_INIT_JOYSTICK) && !(SDL_initialized & SDL_INIT_JOYSTICK)) {
|
||||
if (SDL_JoystickInit() < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_initialized |= SDL_INIT_JOYSTICK;
|
||||
}
|
||||
#else
|
||||
if (flags & SDL_INIT_JOYSTICK) {
|
||||
SDL_SetError("SDL not built with joystick support");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !SDL_HAPTIC_DISABLED
|
||||
/* Initialize the haptic subsystem */
|
||||
if ((flags & SDL_INIT_HAPTIC) && !(SDL_initialized & SDL_INIT_HAPTIC)) {
|
||||
if (SDL_HapticInit() < 0) {
|
||||
return (-1);
|
||||
}
|
||||
SDL_initialized |= SDL_INIT_HAPTIC;
|
||||
}
|
||||
#else
|
||||
if (flags & SDL_INIT_HAPTIC) {
|
||||
SDL_SetError("SDL not built with haptic (force feedback) support");
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_Init(Uint32 flags)
|
||||
{
|
||||
if (SDL_AssertionsInit() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Clear the error message */
|
||||
SDL_ClearError();
|
||||
|
||||
#if defined(__WIN32__)
|
||||
if (SDL_HelperWindowCreate() < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the desired subsystems */
|
||||
if (SDL_InitSubSystem(flags) < 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Everything is initialized */
|
||||
if (!(flags & SDL_INIT_NOPARACHUTE)) {
|
||||
SDL_InstallParachute();
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_QuitSubSystem(Uint32 flags)
|
||||
{
|
||||
/* Shut down requested initialized subsystems */
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
if ((flags & SDL_initialized & SDL_INIT_JOYSTICK)) {
|
||||
SDL_JoystickQuit();
|
||||
SDL_initialized &= ~SDL_INIT_JOYSTICK;
|
||||
}
|
||||
#endif
|
||||
#if !SDL_HAPTIC_DISABLED
|
||||
if ((flags & SDL_initialized & SDL_INIT_HAPTIC)) {
|
||||
SDL_HapticQuit();
|
||||
SDL_initialized &= ~SDL_INIT_HAPTIC;
|
||||
}
|
||||
#endif
|
||||
#if !SDL_TIMERS_DISABLED
|
||||
if ((flags & SDL_initialized & SDL_INIT_TIMER)) {
|
||||
SDL_TimerQuit();
|
||||
SDL_initialized &= ~SDL_INIT_TIMER;
|
||||
}
|
||||
#endif
|
||||
#if !SDL_AUDIO_DISABLED
|
||||
if ((flags & SDL_initialized & SDL_INIT_AUDIO)) {
|
||||
SDL_AudioQuit();
|
||||
SDL_initialized &= ~SDL_INIT_AUDIO;
|
||||
}
|
||||
#endif
|
||||
#if !SDL_VIDEO_DISABLED
|
||||
if ((flags & SDL_initialized & SDL_INIT_VIDEO)) {
|
||||
SDL_VideoQuit();
|
||||
SDL_initialized &= ~SDL_INIT_VIDEO;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_WasInit(Uint32 flags)
|
||||
{
|
||||
if (!flags) {
|
||||
flags = SDL_INIT_EVERYTHING;
|
||||
}
|
||||
return (SDL_initialized & flags);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Quit(void)
|
||||
{
|
||||
/* Quit all subsystems */
|
||||
#if defined(__WIN32__)
|
||||
SDL_HelperWindowDestroy();
|
||||
#endif
|
||||
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
||||
|
||||
/* Uninstall any parachute signal handlers */
|
||||
SDL_UninstallParachute();
|
||||
|
||||
SDL_ClearHints();
|
||||
SDL_AssertionsQuit();
|
||||
SDL_LogResetPriorities();
|
||||
}
|
||||
|
||||
/* Get the library version number */
|
||||
void
|
||||
SDL_GetVersion(SDL_version * ver)
|
||||
{
|
||||
SDL_VERSION(ver);
|
||||
}
|
||||
|
||||
/* Get the library source revision */
|
||||
const char *
|
||||
SDL_GetRevision(void)
|
||||
{
|
||||
return SDL_REVISION;
|
||||
}
|
||||
|
||||
/* Get the library source revision number */
|
||||
int
|
||||
SDL_GetRevisionNumber(void)
|
||||
{
|
||||
return SDL_REVISION_NUMBER;
|
||||
}
|
||||
|
||||
/* Get the name of the platform */
|
||||
const char *
|
||||
SDL_GetPlatform()
|
||||
{
|
||||
#if __AIX__
|
||||
return "AIX";
|
||||
#elif __HAIKU__
|
||||
/* Haiku must appear here before BeOS, since it also defines __BEOS__ */
|
||||
return "Haiku";
|
||||
#elif __BEOS__
|
||||
return "BeOS";
|
||||
#elif __BSDI__
|
||||
return "BSDI";
|
||||
#elif __DREAMCAST__
|
||||
return "Dreamcast";
|
||||
#elif __FREEBSD__
|
||||
return "FreeBSD";
|
||||
#elif __HPUX__
|
||||
return "HP-UX";
|
||||
#elif __IRIX__
|
||||
return "Irix";
|
||||
#elif __LINUX__
|
||||
return "Linux";
|
||||
#elif __MINT__
|
||||
return "Atari MiNT";
|
||||
#elif __MACOS__
|
||||
return "MacOS Classic";
|
||||
#elif __MACOSX__
|
||||
return "Mac OS X";
|
||||
#elif __NETBSD__
|
||||
return "NetBSD";
|
||||
#elif __NDS__
|
||||
return "Nintendo DS";
|
||||
#elif __OPENBSD__
|
||||
return "OpenBSD";
|
||||
#elif __OS2__
|
||||
return "OS/2";
|
||||
#elif __OSF__
|
||||
return "OSF/1";
|
||||
#elif __QNXNTO__
|
||||
return "QNX Neutrino";
|
||||
#elif __RISCOS__
|
||||
return "RISC OS";
|
||||
#elif __SOLARIS__
|
||||
return "Solaris";
|
||||
#elif __WIN32__
|
||||
#ifdef _WIN32_WCE
|
||||
return "Windows CE";
|
||||
#else
|
||||
return "Windows";
|
||||
#endif
|
||||
#elif __IPHONEOS__
|
||||
return "iPhone OS";
|
||||
#else
|
||||
return "Unknown (see SDL_platform.h)";
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
#if !defined(HAVE_LIBC) || (defined(__WATCOMC__) && defined(BUILD_DLL))
|
||||
/* Need to include DllMain() on Watcom C for some reason.. */
|
||||
#include "core/windows/SDL_windows.h"
|
||||
|
||||
BOOL APIENTRY
|
||||
_DllMainCRTStartup(HANDLE hModule,
|
||||
DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* building DLL with Watcom C */
|
||||
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
487
thirdparty/SDL/src/SDL_assert.c
vendored
Normal file
487
thirdparty/SDL/src/SDL_assert.c
vendored
Normal file
@@ -0,0 +1,487 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.h"
|
||||
#include "SDL_atomic.h"
|
||||
#include "SDL_assert.h"
|
||||
#include "SDL_assert_c.h"
|
||||
#include "video/SDL_sysvideo.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "core/windows/SDL_windows.h"
|
||||
|
||||
#ifndef WS_OVERLAPPEDWINDOW
|
||||
#define WS_OVERLAPPEDWINDOW 0
|
||||
#endif
|
||||
#else /* fprintf, _exit(), etc. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata);
|
||||
|
||||
/*
|
||||
* We keep all triggered assertions in a singly-linked list so we can
|
||||
* generate a report later.
|
||||
*/
|
||||
static SDL_assert_data assertion_list_terminator = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
static SDL_assert_data *triggered_assertions = &assertion_list_terminator;
|
||||
|
||||
static SDL_mutex *assertion_mutex = NULL;
|
||||
static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion;
|
||||
static void *assertion_userdata = NULL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
static void
|
||||
debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
|
||||
#endif
|
||||
|
||||
static void
|
||||
debug_print(const char *fmt, ...)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
/* Format into a buffer for OutputDebugStringA(). */
|
||||
char buf[1024];
|
||||
char *startptr;
|
||||
char *ptr;
|
||||
LPTSTR tstr;
|
||||
int len;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
len = (int) SDL_vsnprintf(buf, sizeof (buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Visual C's vsnprintf() may not null-terminate the buffer. */
|
||||
if ((len >= sizeof (buf)) || (len < 0)) {
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
}
|
||||
|
||||
/* Write it, sorting out the Unix newlines... */
|
||||
startptr = buf;
|
||||
for (ptr = startptr; *ptr; ptr++) {
|
||||
if (*ptr == '\n') {
|
||||
*ptr = '\0';
|
||||
tstr = WIN_UTF8ToString(startptr);
|
||||
OutputDebugString(tstr);
|
||||
SDL_free(tstr);
|
||||
OutputDebugString(TEXT("\r\n"));
|
||||
startptr = ptr+1;
|
||||
}
|
||||
}
|
||||
|
||||
/* catch that last piece if it didn't have a newline... */
|
||||
if (startptr != ptr) {
|
||||
tstr = WIN_UTF8ToString(startptr);
|
||||
OutputDebugString(tstr);
|
||||
SDL_free(tstr);
|
||||
}
|
||||
#else
|
||||
/* Unix has it easy. Just dump it to stderr. */
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __WIN32__
|
||||
static SDL_assert_state SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
|
||||
static const SDL_assert_data *SDL_Windows_AssertData = NULL;
|
||||
|
||||
static LRESULT CALLBACK
|
||||
SDL_Assertion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_CREATE:
|
||||
{
|
||||
/* !!! FIXME: all this code stinks. */
|
||||
const SDL_assert_data *data = SDL_Windows_AssertData;
|
||||
char buf[1024];
|
||||
LPTSTR tstr;
|
||||
const int w = 100;
|
||||
const int h = 25;
|
||||
const int gap = 10;
|
||||
int x = gap;
|
||||
int y = 50;
|
||||
int len;
|
||||
int i;
|
||||
static const struct {
|
||||
LPCTSTR name;
|
||||
SDL_assert_state state;
|
||||
} buttons[] = {
|
||||
{TEXT("Abort"), SDL_ASSERTION_ABORT },
|
||||
{TEXT("Break"), SDL_ASSERTION_BREAK },
|
||||
{TEXT("Retry"), SDL_ASSERTION_RETRY },
|
||||
{TEXT("Ignore"), SDL_ASSERTION_IGNORE },
|
||||
{TEXT("Always Ignore"), SDL_ASSERTION_ALWAYS_IGNORE },
|
||||
};
|
||||
|
||||
len = (int) SDL_snprintf(buf, sizeof (buf),
|
||||
"Assertion failure at %s (%s:%d), triggered %u time%s:\r\n '%s'",
|
||||
data->function, data->filename, data->linenum,
|
||||
data->trigger_count, (data->trigger_count == 1) ? "" : "s",
|
||||
data->condition);
|
||||
if ((len < 0) || (len >= sizeof (buf))) {
|
||||
buf[sizeof (buf) - 1] = '\0';
|
||||
}
|
||||
|
||||
tstr = WIN_UTF8ToString(buf);
|
||||
CreateWindow(TEXT("STATIC"), tstr,
|
||||
WS_VISIBLE | WS_CHILD | SS_LEFT,
|
||||
x, y, 550, 100,
|
||||
hwnd, (HMENU) 1, NULL, NULL);
|
||||
SDL_free(tstr);
|
||||
y += 110;
|
||||
|
||||
for (i = 0; i < (sizeof (buttons) / sizeof (buttons[0])); i++) {
|
||||
CreateWindow(TEXT("BUTTON"), buttons[i].name,
|
||||
WS_VISIBLE | WS_CHILD,
|
||||
x, y, w, h,
|
||||
hwnd, (HMENU) buttons[i].state, NULL, NULL);
|
||||
x += w + gap;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
SDL_Windows_AssertChoice = ((SDL_assert_state) (LOWORD(wParam)));
|
||||
SDL_Windows_AssertData = NULL;
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
SDL_Windows_AssertData = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion_windows(const SDL_assert_data *data)
|
||||
{
|
||||
HINSTANCE hInstance = 0; /* !!! FIXME? */
|
||||
HWND hwnd;
|
||||
MSG msg;
|
||||
WNDCLASS wc = {0};
|
||||
|
||||
SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT;
|
||||
SDL_Windows_AssertData = data;
|
||||
|
||||
wc.lpszClassName = TEXT("SDL_assert");
|
||||
wc.hInstance = hInstance ;
|
||||
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
||||
wc.lpfnWndProc = SDL_Assertion_WndProc;
|
||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||
|
||||
RegisterClass(&wc);
|
||||
hwnd = CreateWindow(wc.lpszClassName, TEXT("SDL assertion failure"),
|
||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
150, 150, 570, 260, 0, 0, hInstance, 0);
|
||||
|
||||
while (GetMessage(&msg, NULL, 0, 0) && (SDL_Windows_AssertData != NULL)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
UnregisterClass(wc.lpszClassName, hInstance);
|
||||
return SDL_Windows_AssertChoice;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void SDL_AddAssertionToReport(SDL_assert_data *data)
|
||||
{
|
||||
/* (data) is always a static struct defined with the assert macros, so
|
||||
we don't have to worry about copying or allocating them. */
|
||||
if (data->next == NULL) { /* not yet added? */
|
||||
data->next = triggered_assertions;
|
||||
triggered_assertions = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SDL_GenerateAssertionReport(void)
|
||||
{
|
||||
const SDL_assert_data *item;
|
||||
|
||||
/* only do this if the app hasn't assigned an assertion handler. */
|
||||
if (assertion_handler != SDL_PromptAssertion)
|
||||
return;
|
||||
|
||||
item = SDL_GetAssertionReport();
|
||||
if (item->condition)
|
||||
{
|
||||
debug_print("\n\nSDL assertion report.\n");
|
||||
debug_print("All SDL assertions between last init/quit:\n\n");
|
||||
|
||||
while (item->condition) {
|
||||
debug_print(
|
||||
"'%s'\n"
|
||||
" * %s (%s:%d)\n"
|
||||
" * triggered %u time%s.\n"
|
||||
" * always ignore: %s.\n",
|
||||
item->condition, item->function, item->filename,
|
||||
item->linenum, item->trigger_count,
|
||||
(item->trigger_count == 1) ? "" : "s",
|
||||
item->always_ignore ? "yes" : "no");
|
||||
item = item->next;
|
||||
}
|
||||
debug_print("\n");
|
||||
|
||||
SDL_ResetAssertionReport();
|
||||
}
|
||||
}
|
||||
|
||||
static void SDL_ExitProcess(int exitcode)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
ExitProcess(42);
|
||||
#else
|
||||
_exit(42);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SDL_AbortAssertion(void)
|
||||
{
|
||||
SDL_Quit();
|
||||
SDL_ExitProcess(42);
|
||||
}
|
||||
|
||||
|
||||
static SDL_assert_state
|
||||
SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
|
||||
{
|
||||
const char *envr;
|
||||
SDL_assert_state state = SDL_ASSERTION_ABORT;
|
||||
SDL_Window *window;
|
||||
|
||||
(void) userdata; /* unused in default handler. */
|
||||
|
||||
debug_print("\n\n"
|
||||
"Assertion failure at %s (%s:%d), triggered %u time%s:\n"
|
||||
" '%s'\n"
|
||||
"\n",
|
||||
data->function, data->filename, data->linenum,
|
||||
data->trigger_count, (data->trigger_count == 1) ? "" : "s",
|
||||
data->condition);
|
||||
|
||||
/* let env. variable override, so unit tests won't block in a GUI. */
|
||||
envr = SDL_getenv("SDL_ASSERT");
|
||||
if (envr != NULL) {
|
||||
if (SDL_strcmp(envr, "abort") == 0) {
|
||||
return SDL_ASSERTION_ABORT;
|
||||
} else if (SDL_strcmp(envr, "break") == 0) {
|
||||
return SDL_ASSERTION_BREAK;
|
||||
} else if (SDL_strcmp(envr, "retry") == 0) {
|
||||
return SDL_ASSERTION_RETRY;
|
||||
} else if (SDL_strcmp(envr, "ignore") == 0) {
|
||||
return SDL_ASSERTION_IGNORE;
|
||||
} else if (SDL_strcmp(envr, "always_ignore") == 0) {
|
||||
return SDL_ASSERTION_ALWAYS_IGNORE;
|
||||
} else {
|
||||
return SDL_ASSERTION_ABORT; /* oh well. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Leave fullscreen mode, if possible (scary!) */
|
||||
window = SDL_GetFocusWindow();
|
||||
if (window) {
|
||||
if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
|
||||
SDL_MinimizeWindow(window);
|
||||
} else {
|
||||
/* !!! FIXME: ungrab the input if we're not fullscreen? */
|
||||
/* No need to mess with the window */
|
||||
window = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* platform-specific UI... */
|
||||
|
||||
#ifdef __WIN32__
|
||||
state = SDL_PromptAssertion_windows(data);
|
||||
|
||||
#elif __MACOSX__
|
||||
/* This has to be done in an Objective-C (*.m) file, so we call out. */
|
||||
extern SDL_assert_state SDL_PromptAssertion_cocoa(const SDL_assert_data *);
|
||||
state = SDL_PromptAssertion_cocoa(data);
|
||||
|
||||
#else
|
||||
/* this is a little hacky. */
|
||||
for ( ; ; ) {
|
||||
char buf[32];
|
||||
fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
|
||||
fflush(stderr);
|
||||
if (fgets(buf, sizeof (buf), stdin) == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SDL_strcmp(buf, "a") == 0) {
|
||||
state = SDL_ASSERTION_ABORT;
|
||||
break;
|
||||
} else if (SDL_strcmp(envr, "b") == 0) {
|
||||
state = SDL_ASSERTION_BREAK;
|
||||
break;
|
||||
} else if (SDL_strcmp(envr, "r") == 0) {
|
||||
state = SDL_ASSERTION_RETRY;
|
||||
break;
|
||||
} else if (SDL_strcmp(envr, "i") == 0) {
|
||||
state = SDL_ASSERTION_IGNORE;
|
||||
break;
|
||||
} else if (SDL_strcmp(envr, "A") == 0) {
|
||||
state = SDL_ASSERTION_ALWAYS_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Re-enter fullscreen mode */
|
||||
if (window) {
|
||||
SDL_RestoreWindow(window);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
SDL_assert_state
|
||||
SDL_ReportAssertion(SDL_assert_data *data, const char *func, const char *file,
|
||||
int line)
|
||||
{
|
||||
static int assertion_running = 0;
|
||||
static SDL_SpinLock spinlock = 0;
|
||||
SDL_assert_state state = SDL_ASSERTION_IGNORE;
|
||||
|
||||
SDL_AtomicLock(&spinlock);
|
||||
if (assertion_mutex == NULL) { /* never called SDL_Init()? */
|
||||
assertion_mutex = SDL_CreateMutex();
|
||||
if (assertion_mutex == NULL) {
|
||||
SDL_AtomicUnlock(&spinlock);
|
||||
return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&spinlock);
|
||||
|
||||
if (SDL_LockMutex(assertion_mutex) < 0) {
|
||||
return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
|
||||
}
|
||||
|
||||
/* doing this because Visual C is upset over assigning in the macro. */
|
||||
if (data->trigger_count == 0) {
|
||||
data->function = func;
|
||||
data->filename = file;
|
||||
data->linenum = line;
|
||||
}
|
||||
|
||||
SDL_AddAssertionToReport(data);
|
||||
|
||||
data->trigger_count++;
|
||||
|
||||
assertion_running++;
|
||||
if (assertion_running > 1) { /* assert during assert! Abort. */
|
||||
if (assertion_running == 2) {
|
||||
SDL_AbortAssertion();
|
||||
} else if (assertion_running == 3) { /* Abort asserted! */
|
||||
SDL_ExitProcess(42);
|
||||
} else {
|
||||
while (1) { /* do nothing but spin; what else can you do?! */ }
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->always_ignore) {
|
||||
state = assertion_handler(data, assertion_userdata);
|
||||
}
|
||||
|
||||
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;
|
||||
break;
|
||||
|
||||
case SDL_ASSERTION_IGNORE:
|
||||
case SDL_ASSERTION_RETRY:
|
||||
case SDL_ASSERTION_BREAK:
|
||||
break; /* macro handles these. */
|
||||
}
|
||||
|
||||
assertion_running--;
|
||||
SDL_UnlockMutex(assertion_mutex);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
int SDL_AssertionsInit(void)
|
||||
{
|
||||
/* this is a no-op at the moment. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_AssertionsQuit(void)
|
||||
{
|
||||
SDL_GenerateAssertionReport();
|
||||
if (assertion_mutex != NULL) {
|
||||
SDL_DestroyMutex(assertion_mutex);
|
||||
assertion_mutex = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata)
|
||||
{
|
||||
if (handler != NULL) {
|
||||
assertion_handler = handler;
|
||||
assertion_userdata = userdata;
|
||||
} else {
|
||||
assertion_handler = SDL_PromptAssertion;
|
||||
assertion_userdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const SDL_assert_data *SDL_GetAssertionReport(void)
|
||||
{
|
||||
return triggered_assertions;
|
||||
}
|
||||
|
||||
void SDL_ResetAssertionReport(void)
|
||||
{
|
||||
SDL_assert_data *item = triggered_assertions;
|
||||
SDL_assert_data *next = NULL;
|
||||
for (item = triggered_assertions; item->condition; item = next) {
|
||||
next = (SDL_assert_data *) item->next;
|
||||
item->always_ignore = SDL_FALSE;
|
||||
item->trigger_count = 0;
|
||||
item->next = NULL;
|
||||
}
|
||||
|
||||
triggered_assertions = &assertion_list_terminator;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
25
thirdparty/SDL/src/SDL_assert_c.h
vendored
Normal file
25
thirdparty/SDL/src/SDL_assert_c.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
extern int SDL_AssertionsInit(void);
|
||||
extern void SDL_AssertionsQuit(void);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
1815
thirdparty/SDL/src/SDL_compat.c
vendored
Normal file
1815
thirdparty/SDL/src/SDL_compat.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
258
thirdparty/SDL/src/SDL_error.c
vendored
Normal file
258
thirdparty/SDL/src/SDL_error.c
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Simple error handling in SDL */
|
||||
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_error_c.h"
|
||||
|
||||
|
||||
/* Routine to get the thread-specific error variable */
|
||||
#if SDL_THREADS_DISABLED
|
||||
/* The default (non-thread-safe) global error variable */
|
||||
static SDL_error SDL_global_error;
|
||||
#define SDL_GetErrBuf() (&SDL_global_error)
|
||||
#else
|
||||
extern SDL_error *SDL_GetErrBuf(void);
|
||||
#endif /* SDL_THREADS_DISABLED */
|
||||
|
||||
#define SDL_ERRBUFIZE 1024
|
||||
|
||||
/* Private functions */
|
||||
|
||||
static const char *
|
||||
SDL_LookupString(const char *key)
|
||||
{
|
||||
/* FIXME: Add code to lookup key in language string hash-table */
|
||||
return key;
|
||||
}
|
||||
|
||||
/* Public functions */
|
||||
|
||||
void
|
||||
SDL_SetError(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
SDL_error *error;
|
||||
|
||||
/* Copy in the key, mark error as valid */
|
||||
error = SDL_GetErrBuf();
|
||||
error->error = 1;
|
||||
SDL_strlcpy((char *) error->key, fmt, sizeof(error->key));
|
||||
|
||||
va_start(ap, fmt);
|
||||
error->argc = 0;
|
||||
while (*fmt) {
|
||||
if (*fmt++ == '%') {
|
||||
while (*fmt == '.' || (*fmt >= '0' && *fmt <= '9')) {
|
||||
++fmt;
|
||||
}
|
||||
switch (*fmt++) {
|
||||
case 0: /* Malformed format string.. */
|
||||
--fmt;
|
||||
break;
|
||||
case 'c':
|
||||
case 'i':
|
||||
case 'd':
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
error->args[error->argc++].value_i = va_arg(ap, int);
|
||||
break;
|
||||
case 'f':
|
||||
error->args[error->argc++].value_f = va_arg(ap, double);
|
||||
break;
|
||||
case 'p':
|
||||
error->args[error->argc++].value_ptr = va_arg(ap, void *);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
int i = error->argc;
|
||||
const char *str = va_arg(ap, const char *);
|
||||
if (str == NULL)
|
||||
str = "(null)";
|
||||
SDL_strlcpy((char *) error->args[i].buf, str,
|
||||
ERR_MAX_STRLEN);
|
||||
error->argc++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (error->argc >= ERR_MAX_ARGS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* If we are in debug mode, print out an error message */
|
||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s", SDL_GetError());
|
||||
}
|
||||
|
||||
/* This function has a bit more overhead than most error functions
|
||||
so that it supports internationalization and thread-safe errors.
|
||||
*/
|
||||
static char *
|
||||
SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
|
||||
{
|
||||
SDL_error *error;
|
||||
|
||||
/* Clear the error string */
|
||||
*errstr = '\0';
|
||||
--maxlen;
|
||||
|
||||
/* Get the thread-safe error, and print it out */
|
||||
error = SDL_GetErrBuf();
|
||||
if (error->error) {
|
||||
const char *fmt;
|
||||
char *msg = errstr;
|
||||
int len;
|
||||
int argi;
|
||||
|
||||
fmt = SDL_LookupString(error->key);
|
||||
argi = 0;
|
||||
while (*fmt && (maxlen > 0)) {
|
||||
if (*fmt == '%') {
|
||||
char tmp[32], *spot = tmp;
|
||||
*spot++ = *fmt++;
|
||||
while ((*fmt == '.' || (*fmt >= '0' && *fmt <= '9'))
|
||||
&& spot < (tmp + SDL_arraysize(tmp) - 2)) {
|
||||
*spot++ = *fmt++;
|
||||
}
|
||||
*spot++ = *fmt++;
|
||||
*spot++ = '\0';
|
||||
switch (spot[-2]) {
|
||||
case '%':
|
||||
*msg++ = '%';
|
||||
maxlen -= 1;
|
||||
break;
|
||||
case 'c':
|
||||
case 'i':
|
||||
case 'd':
|
||||
case 'u':
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'X':
|
||||
len =
|
||||
SDL_snprintf(msg, maxlen, tmp,
|
||||
error->args[argi++].value_i);
|
||||
msg += len;
|
||||
maxlen -= len;
|
||||
break;
|
||||
case 'f':
|
||||
len =
|
||||
SDL_snprintf(msg, maxlen, tmp,
|
||||
error->args[argi++].value_f);
|
||||
msg += len;
|
||||
maxlen -= len;
|
||||
break;
|
||||
case 'p':
|
||||
len =
|
||||
SDL_snprintf(msg, maxlen, tmp,
|
||||
error->args[argi++].value_ptr);
|
||||
msg += len;
|
||||
maxlen -= len;
|
||||
break;
|
||||
case 's':
|
||||
len =
|
||||
SDL_snprintf(msg, maxlen, tmp,
|
||||
SDL_LookupString(error->args[argi++].
|
||||
buf));
|
||||
msg += len;
|
||||
maxlen -= len;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*msg++ = *fmt++;
|
||||
maxlen -= 1;
|
||||
}
|
||||
}
|
||||
*msg = 0; /* NULL terminate the string */
|
||||
}
|
||||
return (errstr);
|
||||
}
|
||||
|
||||
/* Available for backwards compatibility */
|
||||
const char *
|
||||
SDL_GetError(void)
|
||||
{
|
||||
static char errmsg[SDL_ERRBUFIZE];
|
||||
|
||||
return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_ClearError(void)
|
||||
{
|
||||
SDL_error *error;
|
||||
|
||||
error = SDL_GetErrBuf();
|
||||
error->error = 0;
|
||||
}
|
||||
|
||||
/* Very common errors go here */
|
||||
void
|
||||
SDL_Error(SDL_errorcode code)
|
||||
{
|
||||
switch (code) {
|
||||
case SDL_ENOMEM:
|
||||
SDL_SetError("Out of memory");
|
||||
break;
|
||||
case SDL_EFREAD:
|
||||
SDL_SetError("Error reading from datastream");
|
||||
break;
|
||||
case SDL_EFWRITE:
|
||||
SDL_SetError("Error writing to datastream");
|
||||
break;
|
||||
case SDL_EFSEEK:
|
||||
SDL_SetError("Error seeking in datastream");
|
||||
break;
|
||||
case SDL_UNSUPPORTED:
|
||||
SDL_SetError("That operation is not supported");
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unknown SDL error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_ERROR
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char buffer[BUFSIZ + 1];
|
||||
|
||||
SDL_SetError("Hi there!");
|
||||
printf("Error 1: %s\n", SDL_GetError());
|
||||
SDL_ClearError();
|
||||
SDL_memset(buffer, '1', BUFSIZ);
|
||||
buffer[BUFSIZ] = 0;
|
||||
SDL_SetError("This is the error: %s (%f)", buffer, 1.0);
|
||||
printf("Error 2: %s\n", SDL_GetError());
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
61
thirdparty/SDL/src/SDL_error_c.h
vendored
Normal file
61
thirdparty/SDL/src/SDL_error_c.h
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This file defines a structure that carries language-independent
|
||||
error messages
|
||||
*/
|
||||
|
||||
#ifndef _SDL_error_c_h
|
||||
#define _SDL_error_c_h
|
||||
|
||||
#define ERR_MAX_STRLEN 128
|
||||
#define ERR_MAX_ARGS 5
|
||||
|
||||
typedef struct SDL_error
|
||||
{
|
||||
/* This is a numeric value corresponding to the current error */
|
||||
int error;
|
||||
|
||||
/* This is a key used to index into a language hashtable containing
|
||||
internationalized versions of the SDL error messages. If the key
|
||||
is not in the hashtable, or no hashtable is available, the key is
|
||||
used directly as an error message format string.
|
||||
*/
|
||||
char key[ERR_MAX_STRLEN];
|
||||
|
||||
/* These are the arguments for the error functions */
|
||||
int argc;
|
||||
union
|
||||
{
|
||||
void *value_ptr;
|
||||
#if 0 /* What is a character anyway? (UNICODE issues) */
|
||||
unsigned char value_c;
|
||||
#endif
|
||||
int value_i;
|
||||
double value_f;
|
||||
char buf[ERR_MAX_STRLEN];
|
||||
} args[ERR_MAX_ARGS];
|
||||
} SDL_error;
|
||||
|
||||
#endif /* _SDL_error_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
139
thirdparty/SDL/src/SDL_fatal.c
vendored
Normal file
139
thirdparty/SDL/src/SDL_fatal.c
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General fatal signal handling code for SDL */
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_fatal.h"
|
||||
|
||||
/* This installs some signal handlers for the more common fatal signals,
|
||||
so that if the programmer is lazy, the app doesn't die so horribly if
|
||||
the program crashes.
|
||||
*/
|
||||
|
||||
static void
|
||||
SDL_Parachute(int sig)
|
||||
{
|
||||
signal(sig, SIG_DFL);
|
||||
SDL_Quit();
|
||||
raise(sig);
|
||||
}
|
||||
|
||||
static const int SDL_fatal_signals[] = {
|
||||
SIGSEGV,
|
||||
#ifdef SIGBUS
|
||||
SIGBUS,
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
SIGFPE,
|
||||
#endif
|
||||
#ifdef SIGQUIT
|
||||
SIGQUIT,
|
||||
#endif
|
||||
0
|
||||
};
|
||||
|
||||
void
|
||||
SDL_InstallParachute(void)
|
||||
{
|
||||
/* Set a handler for any fatal signal not already handled */
|
||||
int i;
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction action;
|
||||
|
||||
for (i = 0; SDL_fatal_signals[i]; ++i) {
|
||||
sigaction(SDL_fatal_signals[i], NULL, &action);
|
||||
if (action.sa_handler == SIG_DFL) {
|
||||
action.sa_handler = SDL_Parachute;
|
||||
sigaction(SDL_fatal_signals[i], &action, NULL);
|
||||
}
|
||||
}
|
||||
#ifdef SIGALRM
|
||||
/* Set SIGALRM to be ignored -- necessary on Solaris */
|
||||
sigaction(SIGALRM, NULL, &action);
|
||||
if (action.sa_handler == SIG_DFL) {
|
||||
action.sa_handler = SIG_IGN;
|
||||
sigaction(SIGALRM, &action, NULL);
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
void (*ohandler) (int);
|
||||
|
||||
for (i = 0; SDL_fatal_signals[i]; ++i) {
|
||||
ohandler = signal(SDL_fatal_signals[i], SDL_Parachute);
|
||||
if (ohandler != SIG_DFL) {
|
||||
signal(SDL_fatal_signals[i], ohandler);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SIGACTION */
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UninstallParachute(void)
|
||||
{
|
||||
/* Remove a handler for any fatal signal handled */
|
||||
int i;
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction action;
|
||||
|
||||
for (i = 0; SDL_fatal_signals[i]; ++i) {
|
||||
sigaction(SDL_fatal_signals[i], NULL, &action);
|
||||
if (action.sa_handler == SDL_Parachute) {
|
||||
action.sa_handler = SIG_DFL;
|
||||
sigaction(SDL_fatal_signals[i], &action, NULL);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void (*ohandler) (int);
|
||||
|
||||
for (i = 0; SDL_fatal_signals[i]; ++i) {
|
||||
ohandler = signal(SDL_fatal_signals[i], SIG_DFL);
|
||||
if (ohandler != SDL_Parachute) {
|
||||
signal(SDL_fatal_signals[i], ohandler);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SIGACTION */
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* No signals on this platform, nothing to do.. */
|
||||
|
||||
void
|
||||
SDL_InstallParachute(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UninstallParachute(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SIGNAL_H */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
27
thirdparty/SDL/src/SDL_fatal.h
vendored
Normal file
27
thirdparty/SDL/src/SDL_fatal.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General fatal signal handling code for SDL */
|
||||
|
||||
extern void SDL_InstallParachute(void);
|
||||
extern void SDL_UninstallParachute(void);
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
121
thirdparty/SDL/src/SDL_hints.c
vendored
Normal file
121
thirdparty/SDL/src/SDL_hints.c
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_hints.h"
|
||||
|
||||
|
||||
/* Assuming there aren't many hints set and they aren't being queried in
|
||||
critical performance paths, we'll just use a linked list here.
|
||||
*/
|
||||
typedef struct SDL_Hint {
|
||||
char *name;
|
||||
char *value;
|
||||
SDL_HintPriority priority;
|
||||
struct SDL_Hint *next;
|
||||
} SDL_Hint;
|
||||
|
||||
static SDL_Hint *SDL_hints;
|
||||
|
||||
|
||||
SDL_bool
|
||||
SDL_SetHintWithPriority(const char *name, const char *value,
|
||||
SDL_HintPriority priority)
|
||||
{
|
||||
const char *env;
|
||||
SDL_Hint *prev, *hint;
|
||||
|
||||
if (!name || !value) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
env = SDL_getenv(name);
|
||||
if (env && priority < SDL_HINT_OVERRIDE) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
for (hint = SDL_hints; hint; prev = hint, hint = hint->next) {
|
||||
if (SDL_strcmp(name, hint->name) == 0) {
|
||||
if (priority < hint->priority) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
if (SDL_strcmp(hint->value, value) != 0) {
|
||||
SDL_free(hint->value);
|
||||
hint->value = SDL_strdup(value);
|
||||
}
|
||||
hint->priority = priority;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Couldn't find the hint, add a new one */
|
||||
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
|
||||
if (!hint) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
hint->name = SDL_strdup(name);
|
||||
hint->value = SDL_strdup(value);
|
||||
hint->priority = priority;
|
||||
hint->next = SDL_hints;
|
||||
SDL_hints = hint;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_SetHint(const char *name, const char *value)
|
||||
{
|
||||
return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL);
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_GetHint(const char *name)
|
||||
{
|
||||
const char *env;
|
||||
SDL_Hint *hint;
|
||||
|
||||
env = SDL_getenv(name);
|
||||
for (hint = SDL_hints; hint; hint = hint->next) {
|
||||
if (SDL_strcmp(name, hint->name) == 0) {
|
||||
if (!env || hint->priority == SDL_HINT_OVERRIDE) {
|
||||
return hint->value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
void SDL_ClearHints(void)
|
||||
{
|
||||
SDL_Hint *hint;
|
||||
|
||||
while (SDL_hints) {
|
||||
hint = SDL_hints;
|
||||
SDL_hints = hint->next;
|
||||
|
||||
SDL_free(hint->name);
|
||||
SDL_free(hint->value);
|
||||
SDL_free(hint);
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
329
thirdparty/SDL/src/SDL_log.c
vendored
Normal file
329
thirdparty/SDL/src/SDL_log.c
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Simple log messages in SDL */
|
||||
|
||||
#include "SDL_log.h"
|
||||
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__)
|
||||
#include "core/windows/SDL_windows.h"
|
||||
#elif defined(__ANDROID__)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL
|
||||
#define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO
|
||||
|
||||
typedef struct SDL_LogLevel
|
||||
{
|
||||
int category;
|
||||
SDL_LogPriority priority;
|
||||
struct SDL_LogLevel *next;
|
||||
} SDL_LogLevel;
|
||||
|
||||
/* The default log output function */
|
||||
static void SDL_LogOutput(void *userdata,
|
||||
int category, SDL_LogPriority priority,
|
||||
const char *message);
|
||||
|
||||
static SDL_LogLevel *SDL_loglevels;
|
||||
static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
|
||||
static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY;
|
||||
static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput;
|
||||
static void *SDL_log_userdata = NULL;
|
||||
|
||||
static const char *SDL_priority_prefixes[SDL_NUM_LOG_PRIORITIES] = {
|
||||
NULL,
|
||||
"VERBOSE",
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"WARN",
|
||||
"ERROR",
|
||||
"CRITICAL"
|
||||
};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
|
||||
"APP",
|
||||
"ERROR",
|
||||
"SYSTEM",
|
||||
"AUDIO",
|
||||
"VIDEO",
|
||||
"RENDER",
|
||||
"INPUT"
|
||||
};
|
||||
|
||||
static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
|
||||
ANDROID_LOG_VERBOSE,
|
||||
ANDROID_LOG_DEBUG,
|
||||
ANDROID_LOG_INFO,
|
||||
ANDROID_LOG_WARN,
|
||||
ANDROID_LOG_ERROR,
|
||||
ANDROID_LOG_FATAL
|
||||
};
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
|
||||
void
|
||||
SDL_LogSetAllPriority(SDL_LogPriority priority)
|
||||
{
|
||||
SDL_LogLevel *entry;
|
||||
|
||||
for (entry = SDL_loglevels; entry; entry = entry->next) {
|
||||
entry->priority = priority;
|
||||
}
|
||||
SDL_application_priority = SDL_default_priority = priority;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogSetPriority(int category, SDL_LogPriority priority)
|
||||
{
|
||||
SDL_LogLevel *entry;
|
||||
|
||||
for (entry = SDL_loglevels; entry; entry = entry->next) {
|
||||
if (entry->category == category) {
|
||||
entry->priority = priority;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a new entry */
|
||||
entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry));
|
||||
if (entry) {
|
||||
entry->category = category;
|
||||
entry->priority = priority;
|
||||
entry->next = SDL_loglevels;
|
||||
SDL_loglevels = entry;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_LogPriority
|
||||
SDL_LogGetPriority(int category)
|
||||
{
|
||||
SDL_LogLevel *entry;
|
||||
|
||||
for (entry = SDL_loglevels; entry; entry = entry->next) {
|
||||
if (entry->category == category) {
|
||||
return entry->priority;
|
||||
}
|
||||
}
|
||||
|
||||
if (category == SDL_LOG_CATEGORY_APPLICATION) {
|
||||
return SDL_application_priority;
|
||||
} else {
|
||||
return SDL_default_priority;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogResetPriorities(void)
|
||||
{
|
||||
SDL_LogLevel *entry;
|
||||
|
||||
while (SDL_loglevels) {
|
||||
entry = SDL_loglevels;
|
||||
SDL_loglevels = entry->next;
|
||||
SDL_free(entry);
|
||||
}
|
||||
|
||||
SDL_application_priority = DEFAULT_APPLICATION_PRIORITY;
|
||||
SDL_default_priority = DEFAULT_PRIORITY;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogVerbose(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_VERBOSE, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogDebug(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_DEBUG, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogInfo(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_INFO, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogWarn(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_WARN, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogError(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_ERROR, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogCritical(int category, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, SDL_LOG_PRIORITY_CRITICAL, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogMessage(int category, SDL_LogPriority priority, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
SDL_LogMessageV(category, priority, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
static const char *
|
||||
GetCategoryPrefix(int category)
|
||||
{
|
||||
if (category < SDL_LOG_CATEGORY_RESERVED1) {
|
||||
return SDL_category_prefixes[category];
|
||||
}
|
||||
if (category < SDL_LOG_CATEGORY_CUSTOM) {
|
||||
return "RESERVED";
|
||||
}
|
||||
return "CUSTOM";
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
void
|
||||
SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list ap)
|
||||
{
|
||||
char *message;
|
||||
|
||||
/* Nothing to do if we don't have an output function */
|
||||
if (!SDL_log_function) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we don't exceed array bounds */
|
||||
if (priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if we want to do anything with this message */
|
||||
if (priority < SDL_LogGetPriority(category)) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
|
||||
if (!message) {
|
||||
return;
|
||||
}
|
||||
SDL_vsnprintf(message, SDL_MAX_LOG_MESSAGE, fmt, ap);
|
||||
SDL_log_function(SDL_log_userdata, category, priority, message);
|
||||
SDL_stack_free(message);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
|
||||
const char *message)
|
||||
{
|
||||
#if defined(__WIN32__)
|
||||
/* Way too many allocations here, urgh */
|
||||
{
|
||||
char *output;
|
||||
size_t length;
|
||||
LPTSTR tstr;
|
||||
|
||||
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1;
|
||||
output = SDL_stack_alloc(char, length);
|
||||
SDL_snprintf(output, length, "%s: %s", SDL_priority_prefixes[priority], message);
|
||||
tstr = WIN_UTF8ToString(output);
|
||||
OutputDebugString(tstr);
|
||||
SDL_free(tstr);
|
||||
SDL_stack_free(output);
|
||||
}
|
||||
#elif defined(__ANDROID__)
|
||||
{
|
||||
char tag[32];
|
||||
|
||||
SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category));
|
||||
__android_log_write(SDL_android_priority[priority], tag, message);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_STDIO_H
|
||||
fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata)
|
||||
{
|
||||
if (callback) {
|
||||
*callback = SDL_log_function;
|
||||
}
|
||||
if (userdata) {
|
||||
*userdata = SDL_log_userdata;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata)
|
||||
{
|
||||
SDL_log_function = callback;
|
||||
SDL_log_userdata = userdata;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
102
thirdparty/SDL/src/atomic/SDL_atomic.c
vendored
Normal file
102
thirdparty/SDL/src/atomic/SDL_atomic.c
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_stdinc.h"
|
||||
|
||||
#include "SDL_atomic.h"
|
||||
|
||||
/* Note that we undefine the atomic operations here, in case they are
|
||||
defined as compiler intrinsics while building SDL but the library user
|
||||
doesn't have that compiler. That way we always have a working set of
|
||||
atomic operations built into the library.
|
||||
*/
|
||||
|
||||
/*
|
||||
If any of the operations are not provided then we must emulate some
|
||||
of them. That means we need a nice implementation of spin locks
|
||||
that avoids the "one big lock" problem. We use a vector of spin
|
||||
locks and pick which one to use based on the address of the operand
|
||||
of the function.
|
||||
|
||||
To generate the index of the lock we first shift by 3 bits to get
|
||||
rid on the zero bits that result from 32 and 64 bit allignment of
|
||||
data. We then mask off all but 5 bits and use those 5 bits as an
|
||||
index into the table.
|
||||
|
||||
Picking the lock this way insures that accesses to the same data at
|
||||
the same time will go to the same lock. OTOH, accesses to different
|
||||
data have only a 1/32 chance of hitting the same lock. That should
|
||||
pretty much eliminate the chances of several atomic operations on
|
||||
different data from waiting on the same "big lock". If it isn't
|
||||
then the table of locks can be expanded to a new size so long as
|
||||
the new size is a power of two.
|
||||
|
||||
Contributed by Bob Pendleton, bob@pendleton.com
|
||||
*/
|
||||
|
||||
static SDL_SpinLock locks[32];
|
||||
|
||||
static __inline__ void
|
||||
enterLock(void *a)
|
||||
{
|
||||
uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
|
||||
|
||||
SDL_AtomicLock(&locks[index]);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
leaveLock(void *a)
|
||||
{
|
||||
uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
|
||||
|
||||
SDL_AtomicUnlock(&locks[index]);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicCAS_(SDL_atomic_t *a, int oldval, int newval)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
enterLock(a);
|
||||
if (a->value == oldval) {
|
||||
a->value = newval;
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
leaveLock(a);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_AtomicCASPtr_(void **a, void *oldval, void *newval)
|
||||
{
|
||||
SDL_bool retval = SDL_FALSE;
|
||||
|
||||
enterLock(a);
|
||||
if (*a == oldval) {
|
||||
*a = newval;
|
||||
retval = SDL_TRUE;
|
||||
}
|
||||
leaveLock(a);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
110
thirdparty/SDL/src/atomic/SDL_spinlock.c
vendored
Normal file
110
thirdparty/SDL/src/atomic/SDL_spinlock.c
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_stdinc.h"
|
||||
|
||||
#include "SDL_atomic.h"
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_timer.h"
|
||||
|
||||
/* Don't do the check for Visual Studio 2005, it's safe here */
|
||||
#ifdef __WIN32__
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
/* This function is where all the magic happens... */
|
||||
SDL_bool
|
||||
SDL_AtomicTryLock(SDL_SpinLock *lock)
|
||||
{
|
||||
#if SDL_ATOMIC_DISABLED
|
||||
/* Terrible terrible damage */
|
||||
static SDL_mutex *_spinlock_mutex;
|
||||
|
||||
if (!_spinlock_mutex) {
|
||||
/* Race condition on first lock... */
|
||||
_spinlock_mutex = SDL_CreateMutex();
|
||||
}
|
||||
SDL_mutexP(_spinlock_mutex);
|
||||
if (*lock == 0) {
|
||||
*lock = 1;
|
||||
SDL_mutexV(_spinlock_mutex);
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
SDL_mutexV(_spinlock_mutex);
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
SDL_COMPILE_TIME_ASSERT(locksize, sizeof(*lock) == sizeof(long));
|
||||
return (InterlockedExchange((long*)lock, 1) == 0);
|
||||
|
||||
#elif defined(__MACOSX__)
|
||||
return OSAtomicCompareAndSwap32Barrier(0, 1, lock);
|
||||
|
||||
#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
|
||||
return (__sync_lock_test_and_set(lock, 1) == 0);
|
||||
|
||||
#elif defined(__GNUC__) && defined(__arm__) && \
|
||||
(defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || \
|
||||
defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5TE__))
|
||||
int result;
|
||||
__asm__ __volatile__ (
|
||||
"swp %0, %1, [%2]\n"
|
||||
: "=&r,&r" (result) : "r,0" (1), "r,r" (lock) : "memory");
|
||||
return (result == 0);
|
||||
|
||||
#elif defined(__GNUC__) && defined(__arm__)
|
||||
int result;
|
||||
__asm__ __volatile__ (
|
||||
"ldrex %0, [%2]\nteq %0, #0\nstrexeq %0, %1, [%2]"
|
||||
: "=&r" (result) : "r" (1), "r" (lock) : "cc", "memory");
|
||||
return (result == 0);
|
||||
|
||||
#else
|
||||
/* Need CPU instructions for spinlock here! */
|
||||
__need_spinlock_implementation__
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicLock(SDL_SpinLock *lock)
|
||||
{
|
||||
/* FIXME: Should we have an eventual timeout? */
|
||||
while (!SDL_AtomicTryLock(lock)) {
|
||||
SDL_Delay(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_AtomicUnlock(SDL_SpinLock *lock)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
_ReadWriteBarrier();
|
||||
*lock = 0;
|
||||
|
||||
#elif HAVE_GCC_ATOMICS || HAVE_GCC_SYNC_LOCK_TEST_AND_SET
|
||||
__sync_lock_release(lock);
|
||||
|
||||
#else
|
||||
*lock = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
1210
thirdparty/SDL/src/audio/SDL_audio.c
vendored
Normal file
1210
thirdparty/SDL/src/audio/SDL_audio.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
55
thirdparty/SDL/src/audio/SDL_audio_c.h
vendored
Normal file
55
thirdparty/SDL/src/audio/SDL_audio_c.h
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Functions and variables exported from SDL_audio.c for SDL_sysaudio.c */
|
||||
|
||||
/* Functions to get a list of "close" audio formats */
|
||||
extern SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format);
|
||||
extern SDL_AudioFormat SDL_NextAudioFormat(void);
|
||||
|
||||
/* Function to calculate the size and silence for a SDL_AudioSpec */
|
||||
extern void SDL_CalculateAudioSpec(SDL_AudioSpec * spec);
|
||||
|
||||
/* The actual mixing thread function */
|
||||
extern int SDLCALL SDL_RunAudio(void *audiop);
|
||||
|
||||
/* this is used internally to access some autogenerated code. */
|
||||
typedef struct
|
||||
{
|
||||
SDL_AudioFormat src_fmt;
|
||||
SDL_AudioFormat dst_fmt;
|
||||
SDL_AudioFilter filter;
|
||||
} SDL_AudioTypeFilters;
|
||||
extern const SDL_AudioTypeFilters sdl_audio_type_filters[];
|
||||
|
||||
/* this is used internally to access some autogenerated code. */
|
||||
typedef struct
|
||||
{
|
||||
SDL_AudioFormat fmt;
|
||||
int channels;
|
||||
int upsample;
|
||||
int multiple;
|
||||
SDL_AudioFilter filter;
|
||||
} SDL_AudioRateFilters;
|
||||
extern const SDL_AudioRateFilters sdl_audio_rate_filters[];
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
1079
thirdparty/SDL/src/audio/SDL_audiocvt.c
vendored
Normal file
1079
thirdparty/SDL/src/audio/SDL_audiocvt.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
138
thirdparty/SDL/src/audio/SDL_audiodev.c
vendored
Normal file
138
thirdparty/SDL/src/audio/SDL_audiodev.c
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Get the name of the audio device we use for output */
|
||||
|
||||
#if SDL_AUDIO_DRIVER_BSD || SDL_AUDIO_DRIVER_OSS || SDL_AUDIO_DRIVER_SUNAUDIO
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h> /* For close() */
|
||||
|
||||
#include "SDL_stdinc.h"
|
||||
#include "SDL_audiodev_c.h"
|
||||
|
||||
#ifndef _PATH_DEV_DSP
|
||||
#if defined(__NETBSD__) || defined(__OPENBSD__)
|
||||
#define _PATH_DEV_DSP "/dev/audio"
|
||||
#else
|
||||
#define _PATH_DEV_DSP "/dev/dsp"
|
||||
#endif
|
||||
#endif
|
||||
#ifndef _PATH_DEV_DSP24
|
||||
#define _PATH_DEV_DSP24 "/dev/sound/dsp"
|
||||
#endif
|
||||
#ifndef _PATH_DEV_AUDIO
|
||||
#define _PATH_DEV_AUDIO "/dev/audio"
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
test_device(const char *fname, int flags, int (*test) (int fd),
|
||||
char ***devices, int *devCount)
|
||||
{
|
||||
struct stat sb;
|
||||
if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
|
||||
int audio_fd = open(fname, flags, 0);
|
||||
if ((audio_fd >= 0) && (test(audio_fd))) {
|
||||
void *p =
|
||||
SDL_realloc(*devices, ((*devCount) + 1) * sizeof(char *));
|
||||
if (p != NULL) {
|
||||
size_t len = strlen(fname) + 1;
|
||||
char *str = (char *) SDL_malloc(len);
|
||||
*devices = (char **) p;
|
||||
if (str != NULL) {
|
||||
SDL_strlcpy(str, fname, len);
|
||||
(*devices)[(*devCount)++] = str;
|
||||
}
|
||||
}
|
||||
close(audio_fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FreeUnixAudioDevices(char ***devices, int *devCount)
|
||||
{
|
||||
int i = *devCount;
|
||||
if ((i > 0) && (*devices != NULL)) {
|
||||
while (i--) {
|
||||
SDL_free((*devices)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (*devices != NULL) {
|
||||
SDL_free(*devices);
|
||||
}
|
||||
|
||||
*devices = NULL;
|
||||
*devCount = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_stub(int fd)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd),
|
||||
char ***devices, int *devCount)
|
||||
{
|
||||
const char *audiodev;
|
||||
char audiopath[1024];
|
||||
|
||||
if (test == NULL)
|
||||
test = test_stub;
|
||||
|
||||
/* Figure out what our audio device is */
|
||||
if (((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) &&
|
||||
((audiodev = SDL_getenv("AUDIODEV")) == NULL)) {
|
||||
if (classic) {
|
||||
audiodev = _PATH_DEV_AUDIO;
|
||||
} else {
|
||||
struct stat sb;
|
||||
|
||||
/* Added support for /dev/sound/\* in Linux 2.4 */
|
||||
if (((stat("/dev/sound", &sb) == 0) && S_ISDIR(sb.st_mode))
|
||||
&& ((stat(_PATH_DEV_DSP24, &sb) == 0)
|
||||
&& S_ISCHR(sb.st_mode))) {
|
||||
audiodev = _PATH_DEV_DSP24;
|
||||
} else {
|
||||
audiodev = _PATH_DEV_DSP;
|
||||
}
|
||||
}
|
||||
}
|
||||
test_device(audiodev, flags, test, devices, devCount);
|
||||
|
||||
if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
|
||||
int instance = 0;
|
||||
while (instance++ <= 64) {
|
||||
SDL_snprintf(audiopath, SDL_arraysize(audiopath),
|
||||
"%s%d", audiodev, instance);
|
||||
test_device(audiopath, flags, test, devices, devCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Audio driver selection */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
27
thirdparty/SDL/src/audio/SDL_audiodev_c.h
vendored
Normal file
27
thirdparty/SDL/src/audio/SDL_audiodev_c.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
void SDL_EnumUnixAudioDevices(int flags, int classic, int (*test) (int fd),
|
||||
char ***devs, int *count);
|
||||
void SDL_FreeUnixAudioDevices(char ***devices, int *devCount);
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
25
thirdparty/SDL/src/audio/SDL_audiomem.h
vendored
Normal file
25
thirdparty/SDL/src/audio/SDL_audiomem.h
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#define SDL_AllocAudioMem SDL_malloc
|
||||
#define SDL_FreeAudioMem SDL_free
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
16215
thirdparty/SDL/src/audio/SDL_audiotypecvt.c
vendored
Normal file
16215
thirdparty/SDL/src/audio/SDL_audiotypecvt.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
321
thirdparty/SDL/src/audio/SDL_mixer.c
vendored
Normal file
321
thirdparty/SDL/src/audio/SDL_mixer.c
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This provides the default mixing callback for the SDL audio routines */
|
||||
|
||||
#include "SDL_cpuinfo.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_sysaudio.h"
|
||||
|
||||
/* This table is used to add two sound values together and pin
|
||||
* the value to avoid overflow. (used with permission from ARDI)
|
||||
* Changed to use 0xFE instead of 0xFF for better sound quality.
|
||||
*/
|
||||
static const Uint8 mix8[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
|
||||
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
||||
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
|
||||
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
|
||||
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
|
||||
0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
|
||||
0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B,
|
||||
0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
|
||||
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
|
||||
0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
|
||||
0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
|
||||
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D,
|
||||
0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
|
||||
0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
|
||||
0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
|
||||
0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
|
||||
0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4,
|
||||
0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
|
||||
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
|
||||
0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
|
||||
0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
|
||||
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE
|
||||
};
|
||||
|
||||
/* The volume ranges from 0 - 128 */
|
||||
#define ADJUST_VOLUME(s, v) (s = (s*v)/SDL_MIX_MAXVOLUME)
|
||||
#define ADJUST_VOLUME_U8(s, v) (s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
|
||||
|
||||
|
||||
void
|
||||
SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
|
||||
Uint32 len, int volume)
|
||||
{
|
||||
if (volume == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
|
||||
case AUDIO_U8:
|
||||
{
|
||||
#if defined(__GNUC__) && defined(__M68000__) && !defined(__mcoldfire__) && defined(SDL_ASSEMBLY_ROUTINES)
|
||||
SDL_MixAudio_m68k_U8((char *) dst, (char *) src,
|
||||
(unsigned long) len, (long) volume,
|
||||
(char *) mix8);
|
||||
#else
|
||||
Uint8 src_sample;
|
||||
|
||||
while (len--) {
|
||||
src_sample = *src;
|
||||
ADJUST_VOLUME_U8(src_sample, volume);
|
||||
*dst = mix8[*dst + src_sample];
|
||||
++dst;
|
||||
++src;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S8:
|
||||
{
|
||||
Sint8 *dst8, *src8;
|
||||
Sint8 src_sample;
|
||||
int dst_sample;
|
||||
const int max_audioval = ((1 << (8 - 1)) - 1);
|
||||
const int min_audioval = -(1 << (8 - 1));
|
||||
|
||||
src8 = (Sint8 *) src;
|
||||
dst8 = (Sint8 *) dst;
|
||||
while (len--) {
|
||||
src_sample = *src8;
|
||||
ADJUST_VOLUME(src_sample, volume);
|
||||
dst_sample = *dst8 + src_sample;
|
||||
if (dst_sample > max_audioval) {
|
||||
*dst8 = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
*dst8 = min_audioval;
|
||||
} else {
|
||||
*dst8 = dst_sample;
|
||||
}
|
||||
++dst8;
|
||||
++src8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
{
|
||||
Sint16 src1, src2;
|
||||
int dst_sample;
|
||||
const int max_audioval = ((1 << (16 - 1)) - 1);
|
||||
const int min_audioval = -(1 << (16 - 1));
|
||||
|
||||
len /= 2;
|
||||
while (len--) {
|
||||
src1 = ((src[1]) << 8 | src[0]);
|
||||
ADJUST_VOLUME(src1, volume);
|
||||
src2 = ((dst[1]) << 8 | dst[0]);
|
||||
src += 2;
|
||||
dst_sample = src1 + src2;
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
dst[0] = dst_sample & 0xFF;
|
||||
dst_sample >>= 8;
|
||||
dst[1] = dst_sample & 0xFF;
|
||||
dst += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S16MSB:
|
||||
{
|
||||
#if defined(__GNUC__) && defined(__M68000__) && !defined(__mcoldfire__) && defined(SDL_ASSEMBLY_ROUTINES)
|
||||
SDL_MixAudio_m68k_S16MSB((short *) dst, (short *) src,
|
||||
(unsigned long) len, (long) volume);
|
||||
#else
|
||||
Sint16 src1, src2;
|
||||
int dst_sample;
|
||||
const int max_audioval = ((1 << (16 - 1)) - 1);
|
||||
const int min_audioval = -(1 << (16 - 1));
|
||||
|
||||
len /= 2;
|
||||
while (len--) {
|
||||
src1 = ((src[0]) << 8 | src[1]);
|
||||
ADJUST_VOLUME(src1, volume);
|
||||
src2 = ((dst[0]) << 8 | dst[1]);
|
||||
src += 2;
|
||||
dst_sample = src1 + src2;
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
dst[1] = dst_sample & 0xFF;
|
||||
dst_sample >>= 8;
|
||||
dst[0] = dst_sample & 0xFF;
|
||||
dst += 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S32LSB:
|
||||
{
|
||||
const Uint32 *src32 = (Uint32 *) src;
|
||||
Uint32 *dst32 = (Uint32 *) dst;
|
||||
Sint64 src1, src2;
|
||||
Sint64 dst_sample;
|
||||
const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
|
||||
const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
|
||||
|
||||
len /= 4;
|
||||
while (len--) {
|
||||
src1 = (Sint64) ((Sint32) SDL_SwapLE32(*src32));
|
||||
src32++;
|
||||
ADJUST_VOLUME(src1, volume);
|
||||
src2 = (Sint64) ((Sint32) SDL_SwapLE32(*dst32));
|
||||
dst_sample = src1 + src2;
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
*(dst32++) = SDL_SwapLE32((Uint32) ((Sint32) dst_sample));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_S32MSB:
|
||||
{
|
||||
const Uint32 *src32 = (Uint32 *) src;
|
||||
Uint32 *dst32 = (Uint32 *) dst;
|
||||
Sint64 src1, src2;
|
||||
Sint64 dst_sample;
|
||||
const Sint64 max_audioval = ((((Sint64) 1) << (32 - 1)) - 1);
|
||||
const Sint64 min_audioval = -(((Sint64) 1) << (32 - 1));
|
||||
|
||||
len /= 4;
|
||||
while (len--) {
|
||||
src1 = (Sint64) ((Sint32) SDL_SwapBE32(*src32));
|
||||
src32++;
|
||||
ADJUST_VOLUME(src1, volume);
|
||||
src2 = (Sint64) ((Sint32) SDL_SwapBE32(*dst32));
|
||||
dst_sample = src1 + src2;
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
*(dst32++) = SDL_SwapBE32((Uint32) ((Sint32) dst_sample));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_F32LSB:
|
||||
{
|
||||
const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
|
||||
const float fvolume = (float) volume;
|
||||
const float *src32 = (float *) src;
|
||||
float *dst32 = (float *) dst;
|
||||
float src1, src2;
|
||||
double dst_sample;
|
||||
/* !!! FIXME: are these right? */
|
||||
const double max_audioval = 3.402823466e+38F;
|
||||
const double min_audioval = -3.402823466e+38F;
|
||||
|
||||
len /= 4;
|
||||
while (len--) {
|
||||
src1 = ((SDL_SwapFloatLE(*src32) * fvolume) * fmaxvolume);
|
||||
src2 = SDL_SwapFloatLE(*dst32);
|
||||
src32++;
|
||||
|
||||
dst_sample = ((double) src1) + ((double) src2);
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
*(dst32++) = SDL_SwapFloatLE((float) dst_sample);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_F32MSB:
|
||||
{
|
||||
const float fmaxvolume = 1.0f / ((float) SDL_MIX_MAXVOLUME);
|
||||
const float fvolume = (float) volume;
|
||||
const float *src32 = (float *) src;
|
||||
float *dst32 = (float *) dst;
|
||||
float src1, src2;
|
||||
double dst_sample;
|
||||
/* !!! FIXME: are these right? */
|
||||
const double max_audioval = 3.402823466e+38F;
|
||||
const double min_audioval = -3.402823466e+38F;
|
||||
|
||||
len /= 4;
|
||||
while (len--) {
|
||||
src1 = ((SDL_SwapFloatBE(*src32) * fvolume) * fmaxvolume);
|
||||
src2 = SDL_SwapFloatBE(*dst32);
|
||||
src32++;
|
||||
|
||||
dst_sample = ((double) src1) + ((double) src2);
|
||||
if (dst_sample > max_audioval) {
|
||||
dst_sample = max_audioval;
|
||||
} else if (dst_sample < min_audioval) {
|
||||
dst_sample = min_audioval;
|
||||
}
|
||||
*(dst32++) = SDL_SwapFloatBE((float) dst_sample);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* If this happens... FIXME! */
|
||||
SDL_SetError("SDL_MixAudio(): unknown audio format");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
128
thirdparty/SDL/src/audio/SDL_sysaudio.h
vendored
Normal file
128
thirdparty/SDL/src/audio/SDL_sysaudio.h
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_sysaudio_h
|
||||
#define _SDL_sysaudio_h
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* The SDL audio driver */
|
||||
typedef struct SDL_AudioDevice SDL_AudioDevice;
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
|
||||
typedef struct SDL_AudioDriverImpl
|
||||
{
|
||||
int (*DetectDevices) (int iscapture);
|
||||
const char *(*GetDeviceName) (int index, int iscapture);
|
||||
int (*OpenDevice) (_THIS, const char *devname, int iscapture);
|
||||
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
|
||||
void (*WaitDevice) (_THIS);
|
||||
void (*PlayDevice) (_THIS);
|
||||
Uint8 *(*GetDeviceBuf) (_THIS);
|
||||
void (*WaitDone) (_THIS);
|
||||
void (*CloseDevice) (_THIS);
|
||||
void (*LockDevice) (_THIS);
|
||||
void (*UnlockDevice) (_THIS);
|
||||
void (*Deinitialize) (void);
|
||||
|
||||
/* Some flags to push duplicate code into the core and reduce #ifdefs. */
|
||||
int ProvidesOwnCallbackThread:1;
|
||||
int SkipMixerLock:1;
|
||||
int HasCaptureSupport:1;
|
||||
int OnlyHasDefaultOutputDevice:1;
|
||||
int OnlyHasDefaultInputDevice:1;
|
||||
} SDL_AudioDriverImpl;
|
||||
|
||||
|
||||
typedef struct SDL_AudioDriver
|
||||
{
|
||||
/* * * */
|
||||
/* The name of this audio driver */
|
||||
const char *name;
|
||||
|
||||
/* * * */
|
||||
/* The description of this audio driver */
|
||||
const char *desc;
|
||||
|
||||
SDL_AudioDriverImpl impl;
|
||||
} SDL_AudioDriver;
|
||||
|
||||
|
||||
/* Streamer */
|
||||
typedef struct
|
||||
{
|
||||
Uint8 *buffer;
|
||||
int max_len; /* the maximum length in bytes */
|
||||
int read_pos, write_pos; /* the position of the write and read heads in bytes */
|
||||
} SDL_AudioStreamer;
|
||||
|
||||
|
||||
/* Define the SDL audio driver structure */
|
||||
struct SDL_AudioDevice
|
||||
{
|
||||
/* * * */
|
||||
/* Data common to all devices */
|
||||
|
||||
/* The current audio specification (shared with audio thread) */
|
||||
SDL_AudioSpec spec;
|
||||
|
||||
/* An audio conversion block for audio format emulation */
|
||||
SDL_AudioCVT convert;
|
||||
|
||||
/* The streamer, if sample rate conversion necessitates it */
|
||||
int use_streamer;
|
||||
SDL_AudioStreamer streamer;
|
||||
|
||||
/* Current state flags */
|
||||
int iscapture;
|
||||
int enabled;
|
||||
int paused;
|
||||
int opened;
|
||||
|
||||
/* Fake audio buffer for when the audio hardware is busy */
|
||||
Uint8 *fake_stream;
|
||||
|
||||
/* A semaphore for locking the mixing buffers */
|
||||
SDL_mutex *mixer_lock;
|
||||
|
||||
/* A thread to feed the audio device */
|
||||
SDL_Thread *thread;
|
||||
SDL_threadID threadid;
|
||||
|
||||
/* * * */
|
||||
/* Data private to this driver */
|
||||
struct SDL_PrivateAudioData *hidden;
|
||||
};
|
||||
#undef _THIS
|
||||
|
||||
typedef struct AudioBootStrap
|
||||
{
|
||||
const char *name;
|
||||
const char *desc;
|
||||
int (*init) (SDL_AudioDriverImpl * impl);
|
||||
int demand_only:1; /* 1==request explicitly, or it won't be available. */
|
||||
} AudioBootStrap;
|
||||
|
||||
#endif /* _SDL_sysaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
635
thirdparty/SDL/src/audio/SDL_wave.c
vendored
Normal file
635
thirdparty/SDL/src/audio/SDL_wave.c
vendored
Normal file
@@ -0,0 +1,635 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Microsoft WAVE file loading routines */
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_wave.h"
|
||||
|
||||
|
||||
static int ReadChunk(SDL_RWops * src, Chunk * chunk);
|
||||
|
||||
struct MS_ADPCM_decodestate
|
||||
{
|
||||
Uint8 hPredictor;
|
||||
Uint16 iDelta;
|
||||
Sint16 iSamp1;
|
||||
Sint16 iSamp2;
|
||||
};
|
||||
static struct MS_ADPCM_decoder
|
||||
{
|
||||
WaveFMT wavefmt;
|
||||
Uint16 wSamplesPerBlock;
|
||||
Uint16 wNumCoef;
|
||||
Sint16 aCoeff[7][2];
|
||||
/* * * */
|
||||
struct MS_ADPCM_decodestate state[2];
|
||||
} MS_ADPCM_state;
|
||||
|
||||
static int
|
||||
InitMS_ADPCM(WaveFMT * format)
|
||||
{
|
||||
Uint8 *rogue_feel;
|
||||
Uint16 extra_info;
|
||||
int i;
|
||||
|
||||
/* Set the rogue pointer to the MS_ADPCM specific data */
|
||||
MS_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
|
||||
MS_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
|
||||
MS_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
|
||||
MS_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
|
||||
MS_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
|
||||
MS_ADPCM_state.wavefmt.bitspersample =
|
||||
SDL_SwapLE16(format->bitspersample);
|
||||
rogue_feel = (Uint8 *) format + sizeof(*format);
|
||||
if (sizeof(*format) == 16) {
|
||||
extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
}
|
||||
MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
MS_ADPCM_state.wNumCoef = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
if (MS_ADPCM_state.wNumCoef != 7) {
|
||||
SDL_SetError("Unknown set of MS_ADPCM coefficients");
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0; i < MS_ADPCM_state.wNumCoef; ++i) {
|
||||
MS_ADPCM_state.aCoeff[i][0] = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
MS_ADPCM_state.aCoeff[i][1] = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static Sint32
|
||||
MS_ADPCM_nibble(struct MS_ADPCM_decodestate *state,
|
||||
Uint8 nybble, Sint16 * coeff)
|
||||
{
|
||||
const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
|
||||
const Sint32 min_audioval = -(1 << (16 - 1));
|
||||
const Sint32 adaptive[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
Sint32 new_sample, delta;
|
||||
|
||||
new_sample = ((state->iSamp1 * coeff[0]) +
|
||||
(state->iSamp2 * coeff[1])) / 256;
|
||||
if (nybble & 0x08) {
|
||||
new_sample += state->iDelta * (nybble - 0x10);
|
||||
} else {
|
||||
new_sample += state->iDelta * nybble;
|
||||
}
|
||||
if (new_sample < min_audioval) {
|
||||
new_sample = min_audioval;
|
||||
} else if (new_sample > max_audioval) {
|
||||
new_sample = max_audioval;
|
||||
}
|
||||
delta = ((Sint32) state->iDelta * adaptive[nybble]) / 256;
|
||||
if (delta < 16) {
|
||||
delta = 16;
|
||||
}
|
||||
state->iDelta = (Uint16) delta;
|
||||
state->iSamp2 = state->iSamp1;
|
||||
state->iSamp1 = (Sint16) new_sample;
|
||||
return (new_sample);
|
||||
}
|
||||
|
||||
static int
|
||||
MS_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
|
||||
{
|
||||
struct MS_ADPCM_decodestate *state[2];
|
||||
Uint8 *freeable, *encoded, *decoded;
|
||||
Sint32 encoded_len, samplesleft;
|
||||
Sint8 nybble, stereo;
|
||||
Sint16 *coeff[2];
|
||||
Sint32 new_sample;
|
||||
|
||||
/* Allocate the proper sized output buffer */
|
||||
encoded_len = *audio_len;
|
||||
encoded = *audio_buf;
|
||||
freeable = *audio_buf;
|
||||
*audio_len = (encoded_len / MS_ADPCM_state.wavefmt.blockalign) *
|
||||
MS_ADPCM_state.wSamplesPerBlock *
|
||||
MS_ADPCM_state.wavefmt.channels * sizeof(Sint16);
|
||||
*audio_buf = (Uint8 *) SDL_malloc(*audio_len);
|
||||
if (*audio_buf == NULL) {
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return (-1);
|
||||
}
|
||||
decoded = *audio_buf;
|
||||
|
||||
/* Get ready... Go! */
|
||||
stereo = (MS_ADPCM_state.wavefmt.channels == 2);
|
||||
state[0] = &MS_ADPCM_state.state[0];
|
||||
state[1] = &MS_ADPCM_state.state[stereo];
|
||||
while (encoded_len >= MS_ADPCM_state.wavefmt.blockalign) {
|
||||
/* Grab the initial information for this block */
|
||||
state[0]->hPredictor = *encoded++;
|
||||
if (stereo) {
|
||||
state[1]->hPredictor = *encoded++;
|
||||
}
|
||||
state[0]->iDelta = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
if (stereo) {
|
||||
state[1]->iDelta = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
}
|
||||
state[0]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
if (stereo) {
|
||||
state[1]->iSamp1 = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
}
|
||||
state[0]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
if (stereo) {
|
||||
state[1]->iSamp2 = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += sizeof(Sint16);
|
||||
}
|
||||
coeff[0] = MS_ADPCM_state.aCoeff[state[0]->hPredictor];
|
||||
coeff[1] = MS_ADPCM_state.aCoeff[state[1]->hPredictor];
|
||||
|
||||
/* Store the two initial samples we start with */
|
||||
decoded[0] = state[0]->iSamp2 & 0xFF;
|
||||
decoded[1] = state[0]->iSamp2 >> 8;
|
||||
decoded += 2;
|
||||
if (stereo) {
|
||||
decoded[0] = state[1]->iSamp2 & 0xFF;
|
||||
decoded[1] = state[1]->iSamp2 >> 8;
|
||||
decoded += 2;
|
||||
}
|
||||
decoded[0] = state[0]->iSamp1 & 0xFF;
|
||||
decoded[1] = state[0]->iSamp1 >> 8;
|
||||
decoded += 2;
|
||||
if (stereo) {
|
||||
decoded[0] = state[1]->iSamp1 & 0xFF;
|
||||
decoded[1] = state[1]->iSamp1 >> 8;
|
||||
decoded += 2;
|
||||
}
|
||||
|
||||
/* Decode and store the other samples in this block */
|
||||
samplesleft = (MS_ADPCM_state.wSamplesPerBlock - 2) *
|
||||
MS_ADPCM_state.wavefmt.channels;
|
||||
while (samplesleft > 0) {
|
||||
nybble = (*encoded) >> 4;
|
||||
new_sample = MS_ADPCM_nibble(state[0], nybble, coeff[0]);
|
||||
decoded[0] = new_sample & 0xFF;
|
||||
new_sample >>= 8;
|
||||
decoded[1] = new_sample & 0xFF;
|
||||
decoded += 2;
|
||||
|
||||
nybble = (*encoded) & 0x0F;
|
||||
new_sample = MS_ADPCM_nibble(state[1], nybble, coeff[1]);
|
||||
decoded[0] = new_sample & 0xFF;
|
||||
new_sample >>= 8;
|
||||
decoded[1] = new_sample & 0xFF;
|
||||
decoded += 2;
|
||||
|
||||
++encoded;
|
||||
samplesleft -= 2;
|
||||
}
|
||||
encoded_len -= MS_ADPCM_state.wavefmt.blockalign;
|
||||
}
|
||||
SDL_free(freeable);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct IMA_ADPCM_decodestate
|
||||
{
|
||||
Sint32 sample;
|
||||
Sint8 index;
|
||||
};
|
||||
static struct IMA_ADPCM_decoder
|
||||
{
|
||||
WaveFMT wavefmt;
|
||||
Uint16 wSamplesPerBlock;
|
||||
/* * * */
|
||||
struct IMA_ADPCM_decodestate state[2];
|
||||
} IMA_ADPCM_state;
|
||||
|
||||
static int
|
||||
InitIMA_ADPCM(WaveFMT * format)
|
||||
{
|
||||
Uint8 *rogue_feel;
|
||||
Uint16 extra_info;
|
||||
|
||||
/* Set the rogue pointer to the IMA_ADPCM specific data */
|
||||
IMA_ADPCM_state.wavefmt.encoding = SDL_SwapLE16(format->encoding);
|
||||
IMA_ADPCM_state.wavefmt.channels = SDL_SwapLE16(format->channels);
|
||||
IMA_ADPCM_state.wavefmt.frequency = SDL_SwapLE32(format->frequency);
|
||||
IMA_ADPCM_state.wavefmt.byterate = SDL_SwapLE32(format->byterate);
|
||||
IMA_ADPCM_state.wavefmt.blockalign = SDL_SwapLE16(format->blockalign);
|
||||
IMA_ADPCM_state.wavefmt.bitspersample =
|
||||
SDL_SwapLE16(format->bitspersample);
|
||||
rogue_feel = (Uint8 *) format + sizeof(*format);
|
||||
if (sizeof(*format) == 16) {
|
||||
extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
rogue_feel += sizeof(Uint16);
|
||||
}
|
||||
IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static Sint32
|
||||
IMA_ADPCM_nibble(struct IMA_ADPCM_decodestate *state, Uint8 nybble)
|
||||
{
|
||||
const Sint32 max_audioval = ((1 << (16 - 1)) - 1);
|
||||
const Sint32 min_audioval = -(1 << (16 - 1));
|
||||
const int index_table[16] = {
|
||||
-1, -1, -1, -1,
|
||||
2, 4, 6, 8,
|
||||
-1, -1, -1, -1,
|
||||
2, 4, 6, 8
|
||||
};
|
||||
const Sint32 step_table[89] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31,
|
||||
34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130,
|
||||
143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408,
|
||||
449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282,
|
||||
1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
|
||||
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630,
|
||||
9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350,
|
||||
22385, 24623, 27086, 29794, 32767
|
||||
};
|
||||
Sint32 delta, step;
|
||||
|
||||
/* Compute difference and new sample value */
|
||||
step = step_table[state->index];
|
||||
delta = step >> 3;
|
||||
if (nybble & 0x04)
|
||||
delta += step;
|
||||
if (nybble & 0x02)
|
||||
delta += (step >> 1);
|
||||
if (nybble & 0x01)
|
||||
delta += (step >> 2);
|
||||
if (nybble & 0x08)
|
||||
delta = -delta;
|
||||
state->sample += delta;
|
||||
|
||||
/* Update index value */
|
||||
state->index += index_table[nybble];
|
||||
if (state->index > 88) {
|
||||
state->index = 88;
|
||||
} else if (state->index < 0) {
|
||||
state->index = 0;
|
||||
}
|
||||
|
||||
/* Clamp output sample */
|
||||
if (state->sample > max_audioval) {
|
||||
state->sample = max_audioval;
|
||||
} else if (state->sample < min_audioval) {
|
||||
state->sample = min_audioval;
|
||||
}
|
||||
return (state->sample);
|
||||
}
|
||||
|
||||
/* Fill the decode buffer with a channel block of data (8 samples) */
|
||||
static void
|
||||
Fill_IMA_ADPCM_block(Uint8 * decoded, Uint8 * encoded,
|
||||
int channel, int numchannels,
|
||||
struct IMA_ADPCM_decodestate *state)
|
||||
{
|
||||
int i;
|
||||
Sint8 nybble;
|
||||
Sint32 new_sample;
|
||||
|
||||
decoded += (channel * 2);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
nybble = (*encoded) & 0x0F;
|
||||
new_sample = IMA_ADPCM_nibble(state, nybble);
|
||||
decoded[0] = new_sample & 0xFF;
|
||||
new_sample >>= 8;
|
||||
decoded[1] = new_sample & 0xFF;
|
||||
decoded += 2 * numchannels;
|
||||
|
||||
nybble = (*encoded) >> 4;
|
||||
new_sample = IMA_ADPCM_nibble(state, nybble);
|
||||
decoded[0] = new_sample & 0xFF;
|
||||
new_sample >>= 8;
|
||||
decoded[1] = new_sample & 0xFF;
|
||||
decoded += 2 * numchannels;
|
||||
|
||||
++encoded;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
IMA_ADPCM_decode(Uint8 ** audio_buf, Uint32 * audio_len)
|
||||
{
|
||||
struct IMA_ADPCM_decodestate *state;
|
||||
Uint8 *freeable, *encoded, *decoded;
|
||||
Sint32 encoded_len, samplesleft;
|
||||
unsigned int c, channels;
|
||||
|
||||
/* Check to make sure we have enough variables in the state array */
|
||||
channels = IMA_ADPCM_state.wavefmt.channels;
|
||||
if (channels > SDL_arraysize(IMA_ADPCM_state.state)) {
|
||||
SDL_SetError("IMA ADPCM decoder can only handle %d channels",
|
||||
SDL_arraysize(IMA_ADPCM_state.state));
|
||||
return (-1);
|
||||
}
|
||||
state = IMA_ADPCM_state.state;
|
||||
|
||||
/* Allocate the proper sized output buffer */
|
||||
encoded_len = *audio_len;
|
||||
encoded = *audio_buf;
|
||||
freeable = *audio_buf;
|
||||
*audio_len = (encoded_len / IMA_ADPCM_state.wavefmt.blockalign) *
|
||||
IMA_ADPCM_state.wSamplesPerBlock *
|
||||
IMA_ADPCM_state.wavefmt.channels * sizeof(Sint16);
|
||||
*audio_buf = (Uint8 *) SDL_malloc(*audio_len);
|
||||
if (*audio_buf == NULL) {
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return (-1);
|
||||
}
|
||||
decoded = *audio_buf;
|
||||
|
||||
/* Get ready... Go! */
|
||||
while (encoded_len >= IMA_ADPCM_state.wavefmt.blockalign) {
|
||||
/* Grab the initial information for this block */
|
||||
for (c = 0; c < channels; ++c) {
|
||||
/* Fill the state information for this block */
|
||||
state[c].sample = ((encoded[1] << 8) | encoded[0]);
|
||||
encoded += 2;
|
||||
if (state[c].sample & 0x8000) {
|
||||
state[c].sample -= 0x10000;
|
||||
}
|
||||
state[c].index = *encoded++;
|
||||
/* Reserved byte in buffer header, should be 0 */
|
||||
if (*encoded++ != 0) {
|
||||
/* Uh oh, corrupt data? Buggy code? */ ;
|
||||
}
|
||||
|
||||
/* Store the initial sample we start with */
|
||||
decoded[0] = (Uint8) (state[c].sample & 0xFF);
|
||||
decoded[1] = (Uint8) (state[c].sample >> 8);
|
||||
decoded += 2;
|
||||
}
|
||||
|
||||
/* Decode and store the other samples in this block */
|
||||
samplesleft = (IMA_ADPCM_state.wSamplesPerBlock - 1) * channels;
|
||||
while (samplesleft > 0) {
|
||||
for (c = 0; c < channels; ++c) {
|
||||
Fill_IMA_ADPCM_block(decoded, encoded,
|
||||
c, channels, &state[c]);
|
||||
encoded += 4;
|
||||
samplesleft -= 8;
|
||||
}
|
||||
decoded += (channels * 8 * 2);
|
||||
}
|
||||
encoded_len -= IMA_ADPCM_state.wavefmt.blockalign;
|
||||
}
|
||||
SDL_free(freeable);
|
||||
return (0);
|
||||
}
|
||||
|
||||
SDL_AudioSpec *
|
||||
SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
|
||||
SDL_AudioSpec * spec, Uint8 ** audio_buf, Uint32 * audio_len)
|
||||
{
|
||||
int was_error;
|
||||
Chunk chunk;
|
||||
int lenread;
|
||||
int IEEE_float_encoded, MS_ADPCM_encoded, IMA_ADPCM_encoded;
|
||||
int samplesize;
|
||||
|
||||
/* WAV magic header */
|
||||
Uint32 RIFFchunk;
|
||||
Uint32 wavelen = 0;
|
||||
Uint32 WAVEmagic;
|
||||
Uint32 headerDiff = 0;
|
||||
|
||||
/* FMT chunk */
|
||||
WaveFMT *format = NULL;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
was_error = 0;
|
||||
if (src == NULL) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check the magic header */
|
||||
RIFFchunk = SDL_ReadLE32(src);
|
||||
wavelen = SDL_ReadLE32(src);
|
||||
if (wavelen == WAVE) { /* The RIFFchunk has already been read */
|
||||
WAVEmagic = wavelen;
|
||||
wavelen = RIFFchunk;
|
||||
RIFFchunk = RIFF;
|
||||
} else {
|
||||
WAVEmagic = SDL_ReadLE32(src);
|
||||
}
|
||||
if ((RIFFchunk != RIFF) || (WAVEmagic != WAVE)) {
|
||||
SDL_SetError("Unrecognized file type (not WAVE)");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
headerDiff += sizeof(Uint32); /* for WAVE */
|
||||
|
||||
/* Read the audio data format chunk */
|
||||
chunk.data = NULL;
|
||||
do {
|
||||
if (chunk.data != NULL) {
|
||||
SDL_free(chunk.data);
|
||||
chunk.data = NULL;
|
||||
}
|
||||
lenread = ReadChunk(src, &chunk);
|
||||
if (lenread < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
/* 2 Uint32's for chunk header+len, plus the lenread */
|
||||
headerDiff += lenread + 2 * sizeof(Uint32);
|
||||
} while ((chunk.magic == FACT) || (chunk.magic == LIST));
|
||||
|
||||
/* Decode the audio data format */
|
||||
format = (WaveFMT *) chunk.data;
|
||||
if (chunk.magic != FMT) {
|
||||
SDL_SetError("Complex WAVE files not supported");
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
IEEE_float_encoded = MS_ADPCM_encoded = IMA_ADPCM_encoded = 0;
|
||||
switch (SDL_SwapLE16(format->encoding)) {
|
||||
case PCM_CODE:
|
||||
/* We can understand this */
|
||||
break;
|
||||
case IEEE_FLOAT_CODE:
|
||||
IEEE_float_encoded = 1;
|
||||
/* We can understand this */
|
||||
break;
|
||||
case MS_ADPCM_CODE:
|
||||
/* Try to understand this */
|
||||
if (InitMS_ADPCM(format) < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
MS_ADPCM_encoded = 1;
|
||||
break;
|
||||
case IMA_ADPCM_CODE:
|
||||
/* Try to understand this */
|
||||
if (InitIMA_ADPCM(format) < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
IMA_ADPCM_encoded = 1;
|
||||
break;
|
||||
case MP3_CODE:
|
||||
SDL_SetError("MPEG Layer 3 data not supported",
|
||||
SDL_SwapLE16(format->encoding));
|
||||
was_error = 1;
|
||||
goto done;
|
||||
default:
|
||||
SDL_SetError("Unknown WAVE data format: 0x%.4x",
|
||||
SDL_SwapLE16(format->encoding));
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
SDL_memset(spec, 0, (sizeof *spec));
|
||||
spec->freq = SDL_SwapLE32(format->frequency);
|
||||
|
||||
if (IEEE_float_encoded) {
|
||||
if ((SDL_SwapLE16(format->bitspersample)) != 32) {
|
||||
was_error = 1;
|
||||
} else {
|
||||
spec->format = AUDIO_F32;
|
||||
}
|
||||
} else {
|
||||
switch (SDL_SwapLE16(format->bitspersample)) {
|
||||
case 4:
|
||||
if (MS_ADPCM_encoded || IMA_ADPCM_encoded) {
|
||||
spec->format = AUDIO_S16;
|
||||
} else {
|
||||
was_error = 1;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
spec->format = AUDIO_U8;
|
||||
break;
|
||||
case 16:
|
||||
spec->format = AUDIO_S16;
|
||||
break;
|
||||
case 32:
|
||||
spec->format = AUDIO_S32;
|
||||
break;
|
||||
default:
|
||||
was_error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (was_error) {
|
||||
SDL_SetError("Unknown %d-bit PCM data format",
|
||||
SDL_SwapLE16(format->bitspersample));
|
||||
goto done;
|
||||
}
|
||||
spec->channels = (Uint8) SDL_SwapLE16(format->channels);
|
||||
spec->samples = 4096; /* Good default buffer size */
|
||||
|
||||
/* Read the audio data chunk */
|
||||
*audio_buf = NULL;
|
||||
do {
|
||||
if (*audio_buf != NULL) {
|
||||
SDL_free(*audio_buf);
|
||||
*audio_buf = NULL;
|
||||
}
|
||||
lenread = ReadChunk(src, &chunk);
|
||||
if (lenread < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
*audio_len = lenread;
|
||||
*audio_buf = chunk.data;
|
||||
if (chunk.magic != DATA)
|
||||
headerDiff += lenread + 2 * sizeof(Uint32);
|
||||
} while (chunk.magic != DATA);
|
||||
headerDiff += 2 * sizeof(Uint32); /* for the data chunk and len */
|
||||
|
||||
if (MS_ADPCM_encoded) {
|
||||
if (MS_ADPCM_decode(audio_buf, audio_len) < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (IMA_ADPCM_encoded) {
|
||||
if (IMA_ADPCM_decode(audio_buf, audio_len) < 0) {
|
||||
was_error = 1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't return a buffer that isn't a multiple of samplesize */
|
||||
samplesize = ((SDL_AUDIO_BITSIZE(spec->format)) / 8) * spec->channels;
|
||||
*audio_len &= ~(samplesize - 1);
|
||||
|
||||
done:
|
||||
if (format != NULL) {
|
||||
SDL_free(format);
|
||||
}
|
||||
if (src) {
|
||||
if (freesrc) {
|
||||
SDL_RWclose(src);
|
||||
} else {
|
||||
/* seek to the end of the file (given by the RIFF chunk) */
|
||||
SDL_RWseek(src, wavelen - chunk.length - headerDiff, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
if (was_error) {
|
||||
spec = NULL;
|
||||
}
|
||||
return (spec);
|
||||
}
|
||||
|
||||
/* Since the WAV memory is allocated in the shared library, it must also
|
||||
be freed here. (Necessary under Win32, VC++)
|
||||
*/
|
||||
void
|
||||
SDL_FreeWAV(Uint8 * audio_buf)
|
||||
{
|
||||
if (audio_buf != NULL) {
|
||||
SDL_free(audio_buf);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ReadChunk(SDL_RWops * src, Chunk * chunk)
|
||||
{
|
||||
chunk->magic = SDL_ReadLE32(src);
|
||||
chunk->length = SDL_ReadLE32(src);
|
||||
chunk->data = (Uint8 *) SDL_malloc(chunk->length);
|
||||
if (chunk->data == NULL) {
|
||||
SDL_Error(SDL_ENOMEM);
|
||||
return (-1);
|
||||
}
|
||||
if (SDL_RWread(src, chunk->data, chunk->length, 1) != 1) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
SDL_free(chunk->data);
|
||||
chunk->data = NULL;
|
||||
return (-1);
|
||||
}
|
||||
return (chunk->length);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
64
thirdparty/SDL/src/audio/SDL_wave.h
vendored
Normal file
64
thirdparty/SDL/src/audio/SDL_wave.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* WAVE files are little-endian */
|
||||
|
||||
/*******************************************/
|
||||
/* Define values for Microsoft WAVE format */
|
||||
/*******************************************/
|
||||
#define RIFF 0x46464952 /* "RIFF" */
|
||||
#define WAVE 0x45564157 /* "WAVE" */
|
||||
#define FACT 0x74636166 /* "fact" */
|
||||
#define LIST 0x5453494c /* "LIST" */
|
||||
#define FMT 0x20746D66 /* "fmt " */
|
||||
#define DATA 0x61746164 /* "data" */
|
||||
#define PCM_CODE 0x0001
|
||||
#define MS_ADPCM_CODE 0x0002
|
||||
#define IEEE_FLOAT_CODE 0x0003
|
||||
#define IMA_ADPCM_CODE 0x0011
|
||||
#define MP3_CODE 0x0055
|
||||
#define WAVE_MONO 1
|
||||
#define WAVE_STEREO 2
|
||||
|
||||
/* Normally, these three chunks come consecutively in a WAVE file */
|
||||
typedef struct WaveFMT
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* The general chunk found in the WAVE file */
|
||||
typedef struct Chunk
|
||||
{
|
||||
Uint32 magic;
|
||||
Uint32 length;
|
||||
Uint8 *data;
|
||||
} Chunk;
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
690
thirdparty/SDL/src/audio/alsa/SDL_alsa_audio.c
vendored
Normal file
690
thirdparty/SDL/src/audio/alsa/SDL_alsa_audio.c
vendored
Normal file
@@ -0,0 +1,690 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h> /* For kill() */
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_alsa_audio.h"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
|
||||
#include "SDL_loadso.h"
|
||||
#endif
|
||||
|
||||
/* The tag name used by ALSA audio */
|
||||
#define DRIVER_NAME "alsa"
|
||||
|
||||
static int (*ALSA_snd_pcm_open)
|
||||
(snd_pcm_t **, const char *, snd_pcm_stream_t, int);
|
||||
static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
|
||||
static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
|
||||
(snd_pcm_t *, const void *, snd_pcm_uframes_t);
|
||||
static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
|
||||
static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
|
||||
static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
|
||||
static const char *(*ALSA_snd_strerror) (int);
|
||||
static size_t(*ALSA_snd_pcm_hw_params_sizeof) (void);
|
||||
static size_t(*ALSA_snd_pcm_sw_params_sizeof) (void);
|
||||
static void (*ALSA_snd_pcm_hw_params_copy)
|
||||
(snd_pcm_hw_params_t *, const snd_pcm_hw_params_t *);
|
||||
static int (*ALSA_snd_pcm_hw_params_any) (snd_pcm_t *, snd_pcm_hw_params_t *);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_access)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_format)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_channels)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int);
|
||||
static int (*ALSA_snd_pcm_hw_params_get_channels)
|
||||
(const snd_pcm_hw_params_t *, unsigned int *);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_rate_near)
|
||||
(snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
|
||||
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)
|
||||
(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 *);
|
||||
static int (*ALSA_snd_pcm_hw_params_set_buffer_size_near)
|
||||
(snd_pcm_t *pcm, snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
|
||||
static int (*ALSA_snd_pcm_hw_params_get_buffer_size)
|
||||
(const snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
|
||||
static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *);
|
||||
static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *,
|
||||
snd_pcm_sw_params_t *);
|
||||
static int (*ALSA_snd_pcm_sw_params_set_start_threshold)
|
||||
(snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
|
||||
static int (*ALSA_snd_pcm_sw_params) (snd_pcm_t *, snd_pcm_sw_params_t *);
|
||||
static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
|
||||
static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
|
||||
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
|
||||
#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
|
||||
#define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof
|
||||
|
||||
static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC;
|
||||
static void *alsa_handle = NULL;
|
||||
|
||||
static int
|
||||
load_alsa_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(alsa_handle, fn);
|
||||
if (*addr == NULL) {
|
||||
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
#define SDL_ALSA_SYM(x) \
|
||||
if (!load_alsa_sym(#x, (void **) (char *) &ALSA_##x)) return -1
|
||||
#else
|
||||
#define SDL_ALSA_SYM(x) ALSA_##x = x
|
||||
#endif
|
||||
|
||||
static int
|
||||
load_alsa_syms(void)
|
||||
{
|
||||
SDL_ALSA_SYM(snd_pcm_open);
|
||||
SDL_ALSA_SYM(snd_pcm_close);
|
||||
SDL_ALSA_SYM(snd_pcm_writei);
|
||||
SDL_ALSA_SYM(snd_pcm_recover);
|
||||
SDL_ALSA_SYM(snd_pcm_prepare);
|
||||
SDL_ALSA_SYM(snd_pcm_drain);
|
||||
SDL_ALSA_SYM(snd_strerror);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
|
||||
SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_copy);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_any);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_access);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
|
||||
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_get_periods);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
|
||||
SDL_ALSA_SYM(snd_pcm_hw_params);
|
||||
SDL_ALSA_SYM(snd_pcm_sw_params_current);
|
||||
SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold);
|
||||
SDL_ALSA_SYM(snd_pcm_sw_params);
|
||||
SDL_ALSA_SYM(snd_pcm_nonblock);
|
||||
SDL_ALSA_SYM(snd_pcm_wait);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef SDL_ALSA_SYM
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
|
||||
|
||||
static void
|
||||
UnloadALSALibrary(void)
|
||||
{
|
||||
if (alsa_handle != NULL) {
|
||||
SDL_UnloadObject(alsa_handle);
|
||||
alsa_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadALSALibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (alsa_handle == NULL) {
|
||||
alsa_handle = SDL_LoadObject(alsa_library);
|
||||
if (alsa_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
} else {
|
||||
retval = load_alsa_syms();
|
||||
if (retval < 0) {
|
||||
UnloadALSALibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
UnloadALSALibrary(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
LoadALSALibrary(void)
|
||||
{
|
||||
load_alsa_syms();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */
|
||||
|
||||
static const char *
|
||||
get_audio_device(int channels)
|
||||
{
|
||||
const char *device;
|
||||
|
||||
device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */
|
||||
if (device == NULL) {
|
||||
switch (channels) {
|
||||
case 6:
|
||||
device = "plug:surround51";
|
||||
break;
|
||||
case 4:
|
||||
device = "plug:surround40";
|
||||
break;
|
||||
default:
|
||||
device = "default";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
ALSA_WaitDevice(_THIS)
|
||||
{
|
||||
/* We're in blocking mode, so there's nothing to do here */
|
||||
}
|
||||
|
||||
|
||||
/* !!! FIXME: is there a channel swizzler in alsalib instead? */
|
||||
/*
|
||||
* http://bugzilla.libsdl.org/show_bug.cgi?id=110
|
||||
* "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
|
||||
* and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
|
||||
*/
|
||||
#define SWIZ6(T) \
|
||||
T *ptr = (T *) this->hidden->mixbuf; \
|
||||
Uint32 i; \
|
||||
for (i = 0; i < this->spec.samples; i++, ptr += 6) { \
|
||||
T tmp; \
|
||||
tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
|
||||
tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
swizzle_alsa_channels_6_64bit(_THIS)
|
||||
{
|
||||
SWIZ6(Uint64);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
swizzle_alsa_channels_6_32bit(_THIS)
|
||||
{
|
||||
SWIZ6(Uint32);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
swizzle_alsa_channels_6_16bit(_THIS)
|
||||
{
|
||||
SWIZ6(Uint16);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
swizzle_alsa_channels_6_8bit(_THIS)
|
||||
{
|
||||
SWIZ6(Uint8);
|
||||
}
|
||||
|
||||
#undef SWIZ6
|
||||
|
||||
|
||||
/*
|
||||
* Called right before feeding this->hidden->mixbuf to the hardware. Swizzle
|
||||
* channels from Windows/Mac order to the format alsalib will want.
|
||||
*/
|
||||
static __inline__ void
|
||||
swizzle_alsa_channels(_THIS)
|
||||
{
|
||||
if (this->spec.channels == 6) {
|
||||
const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */
|
||||
if (fmtsize == 16)
|
||||
swizzle_alsa_channels_6_16bit(this);
|
||||
else if (fmtsize == 8)
|
||||
swizzle_alsa_channels_6_8bit(this);
|
||||
else if (fmtsize == 32)
|
||||
swizzle_alsa_channels_6_32bit(this);
|
||||
else if (fmtsize == 64)
|
||||
swizzle_alsa_channels_6_64bit(this);
|
||||
}
|
||||
|
||||
/* !!! FIXME: update this for 7.1 if needed, later. */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ALSA_PlayDevice(_THIS)
|
||||
{
|
||||
int status;
|
||||
const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
|
||||
const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) *
|
||||
this->spec.channels;
|
||||
snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
|
||||
|
||||
swizzle_alsa_channels(this);
|
||||
|
||||
while ( frames_left > 0 && this->enabled ) {
|
||||
/* !!! FIXME: This works, but needs more testing before going live */
|
||||
/*ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1);*/
|
||||
status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
|
||||
sample_buf, frames_left);
|
||||
|
||||
if (status < 0) {
|
||||
if (status == -EAGAIN) {
|
||||
/* Apparently snd_pcm_recover() doesn't handle this case -
|
||||
does it assume snd_pcm_wait() above? */
|
||||
SDL_Delay(1);
|
||||
continue;
|
||||
}
|
||||
status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
|
||||
if (status < 0) {
|
||||
/* Hmm, not much we can do - abort */
|
||||
fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
|
||||
ALSA_snd_strerror(status));
|
||||
this->enabled = 0;
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
sample_buf += status * frame_size;
|
||||
frames_left -= status;
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
ALSA_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
ALSA_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->pcm_handle) {
|
||||
ALSA_snd_pcm_drain(this->hidden->pcm_handle);
|
||||
ALSA_snd_pcm_close(this->hidden->pcm_handle);
|
||||
this->hidden->pcm_handle = NULL;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
|
||||
{
|
||||
int status;
|
||||
snd_pcm_uframes_t bufsize;
|
||||
|
||||
/* "set" the hardware with the desired parameters */
|
||||
status = ALSA_snd_pcm_hw_params(this->hidden->pcm_handle, hwparams);
|
||||
if ( status < 0 ) {
|
||||
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 is useful for debugging */
|
||||
if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
|
||||
snd_pcm_uframes_t persize = 0;
|
||||
unsigned int periods = 0;
|
||||
|
||||
ALSA_snd_pcm_hw_params_get_period_size(hwparams, &persize, NULL);
|
||||
ALSA_snd_pcm_hw_params_get_periods(hwparams, &periods, NULL);
|
||||
|
||||
fprintf(stderr,
|
||||
"ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
|
||||
persize, periods, bufsize);
|
||||
}
|
||||
|
||||
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, const char *devname, int iscapture)
|
||||
{
|
||||
int status = 0;
|
||||
snd_pcm_t *pcm_handle = NULL;
|
||||
snd_pcm_hw_params_t *hwparams = NULL;
|
||||
snd_pcm_sw_params_t *swparams = NULL;
|
||||
snd_pcm_format_t format = 0;
|
||||
SDL_AudioFormat test_format = 0;
|
||||
unsigned int rate = 0;
|
||||
unsigned int channels = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
/* Name of device should depend on # channels in spec */
|
||||
status = ALSA_snd_pcm_open(&pcm_handle,
|
||||
get_audio_device(this->spec.channels),
|
||||
SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't open audio device: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->pcm_handle = pcm_handle;
|
||||
|
||||
/* Figure out what the hardware is capable of */
|
||||
snd_pcm_hw_params_alloca(&hwparams);
|
||||
status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't get hardware config: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SDL only uses interleaved sample output */
|
||||
status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
|
||||
SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't set interleaved access: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
status = -1;
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
test_format && (status < 0);) {
|
||||
status = 0; /* if we can't support a format, it'll become -1. */
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
format = SND_PCM_FORMAT_U8;
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
format = SND_PCM_FORMAT_S8;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
format = SND_PCM_FORMAT_S16_LE;
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
format = SND_PCM_FORMAT_S16_BE;
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
format = SND_PCM_FORMAT_U16_LE;
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
format = SND_PCM_FORMAT_U16_BE;
|
||||
break;
|
||||
case AUDIO_S32LSB:
|
||||
format = SND_PCM_FORMAT_S32_LE;
|
||||
break;
|
||||
case AUDIO_S32MSB:
|
||||
format = SND_PCM_FORMAT_S32_BE;
|
||||
break;
|
||||
case AUDIO_F32LSB:
|
||||
format = SND_PCM_FORMAT_FLOAT_LE;
|
||||
break;
|
||||
case AUDIO_F32MSB:
|
||||
format = SND_PCM_FORMAT_FLOAT_BE;
|
||||
break;
|
||||
default:
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
if (status >= 0) {
|
||||
status = ALSA_snd_pcm_hw_params_set_format(pcm_handle,
|
||||
hwparams, format);
|
||||
}
|
||||
if (status < 0) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Set the number of channels */
|
||||
status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams,
|
||||
this->spec.channels);
|
||||
channels = this->spec.channels;
|
||||
if (status < 0) {
|
||||
status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't set audio channels");
|
||||
return 0;
|
||||
}
|
||||
this->spec.channels = channels;
|
||||
}
|
||||
|
||||
/* Set the audio rate */
|
||||
rate = this->spec.freq;
|
||||
status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
|
||||
&rate, NULL);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't set audio frequency: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
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... */
|
||||
if ( ALSA_set_period_size(this, hwparams, 1) < 0 ) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
/* Set the software parameters */
|
||||
snd_pcm_sw_params_alloca(&swparams);
|
||||
status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't get software config: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
status =
|
||||
ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("ALSA: Couldn't set start threshold: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
|
||||
if (status < 0) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set software audio parameters: %s",
|
||||
ALSA_snd_strerror(status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
ALSA_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* Switch to blocking mode for playback */
|
||||
ALSA_snd_pcm_nonblock(pcm_handle, 0);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ALSA_Deinitialize(void)
|
||||
{
|
||||
UnloadALSALibrary();
|
||||
}
|
||||
|
||||
static int
|
||||
ALSA_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadALSALibrary() < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = ALSA_OpenDevice;
|
||||
impl->WaitDevice = ALSA_WaitDevice;
|
||||
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
|
||||
impl->PlayDevice = ALSA_PlayDevice;
|
||||
impl->CloseDevice = ALSA_CloseDevice;
|
||||
impl->Deinitialize = ALSA_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Add device enum! */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap ALSA_bootstrap = {
|
||||
DRIVER_NAME, "ALSA PCM audio", ALSA_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
45
thirdparty/SDL/src/audio/alsa/SDL_alsa_audio.h
vendored
Normal file
45
thirdparty/SDL/src/audio/alsa/SDL_alsa_audio.h
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _ALSA_PCM_audio_h
|
||||
#define _ALSA_PCM_audio_h
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The audio device handle */
|
||||
snd_pcm_t *pcm_handle;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
};
|
||||
|
||||
#endif /* _ALSA_PCM_audio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
157
thirdparty/SDL/src/audio/android/SDL_androidaudio.c
vendored
Normal file
157
thirdparty/SDL/src/audio/android/SDL_androidaudio.c
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Output audio to Android */
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_androidaudio.h"
|
||||
|
||||
#include "../../core/android/SDL_android.h"
|
||||
|
||||
#include <android/log.h>
|
||||
|
||||
static void * audioDevice;
|
||||
|
||||
static int
|
||||
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format;
|
||||
int valid_datatype = 0;
|
||||
|
||||
if (iscapture) {
|
||||
//TODO: implement capture
|
||||
SDL_SetError("Capture not supported on Android");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (audioDevice != NULL) {
|
||||
SDL_SetError("Only one audio device at a time please!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
audioDevice = this;
|
||||
|
||||
this->hidden = SDL_malloc(sizeof(*(this->hidden)));
|
||||
if (!this->hidden) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
while (test_format != 0) { // no "UNKNOWN" constant
|
||||
if ((test_format == AUDIO_U8) || (test_format == AUDIO_S16LSB)) {
|
||||
this->spec.format = test_format;
|
||||
break;
|
||||
}
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
if (test_format == 0) {
|
||||
// Didn't find a compatible format :(
|
||||
SDL_SetError("No compatible audio format!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, also whether we're opening for input or output
|
||||
this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
if (this->spec.samples == 0) {
|
||||
// Init failed?
|
||||
SDL_SetError("Java-side initialization failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
AndroidAUD_PlayDevice(_THIS)
|
||||
{
|
||||
Android_JNI_WriteAudioBuffer();
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
AndroidAUD_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return Android_JNI_GetAudioBuffer();
|
||||
}
|
||||
|
||||
static void
|
||||
AndroidAUD_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
Android_JNI_CloseAudioDevice();
|
||||
|
||||
if (audioDevice == this) {
|
||||
audioDevice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
AndroidAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = AndroidAUD_OpenDevice;
|
||||
impl->PlayDevice = AndroidAUD_PlayDevice;
|
||||
impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
|
||||
impl->CloseDevice = AndroidAUD_CloseDevice;
|
||||
|
||||
/* and the capabilities */
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
impl->HasCaptureSupport = 0; //TODO
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
impl->OnlyHasDefaultInputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap ANDROIDAUD_bootstrap = {
|
||||
"android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */
|
||||
};
|
||||
|
||||
/* Called by the Java code to start the audio processing on a thread */
|
||||
void
|
||||
Android_RunAudioThread()
|
||||
{
|
||||
SDL_RunAudio(audioDevice);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
37
thirdparty/SDL/src/audio/android/SDL_androidaudio.h
vendored
Normal file
37
thirdparty/SDL/src/audio/android/SDL_androidaudio.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_androidaudio_h
|
||||
#define _SDL_androidaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
};
|
||||
|
||||
#endif /* _SDL_androidaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
378
thirdparty/SDL/src/audio/arts/SDL_artsaudio.c
vendored
Normal file
378
thirdparty/SDL/src/audio/arts/SDL_artsaudio.c
vendored
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_artsaudio.h"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
|
||||
#include "SDL_name.h"
|
||||
#include "SDL_loadso.h"
|
||||
#else
|
||||
#define SDL_NAME(X) X
|
||||
#endif
|
||||
|
||||
/* The tag name used by artsc audio */
|
||||
#define ARTS_DRIVER_NAME "arts"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
|
||||
|
||||
static const char *arts_library = SDL_AUDIO_DRIVER_ARTS_DYNAMIC;
|
||||
static void *arts_handle = NULL;
|
||||
|
||||
/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
|
||||
static int (*SDL_NAME(arts_init)) (void);
|
||||
static void (*SDL_NAME(arts_free)) (void);
|
||||
static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
|
||||
int channels,
|
||||
const char *name);
|
||||
static int (*SDL_NAME(arts_stream_set)) (arts_stream_t s,
|
||||
arts_parameter_t param, int value);
|
||||
static int (*SDL_NAME(arts_stream_get)) (arts_stream_t s,
|
||||
arts_parameter_t param);
|
||||
static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
|
||||
int count);
|
||||
static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
|
||||
static int (*SDL_NAME(arts_suspended)) (void);
|
||||
static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
|
||||
|
||||
#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
void **func;
|
||||
} arts_functions[] = {
|
||||
/* *INDENT-OFF* */
|
||||
SDL_ARTS_SYM(arts_init),
|
||||
SDL_ARTS_SYM(arts_free),
|
||||
SDL_ARTS_SYM(arts_play_stream),
|
||||
SDL_ARTS_SYM(arts_stream_set),
|
||||
SDL_ARTS_SYM(arts_stream_get),
|
||||
SDL_ARTS_SYM(arts_write),
|
||||
SDL_ARTS_SYM(arts_close_stream),
|
||||
SDL_ARTS_SYM(arts_suspended),
|
||||
SDL_ARTS_SYM(arts_error_text),
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
#undef SDL_ARTS_SYM
|
||||
|
||||
static void
|
||||
UnloadARTSLibrary()
|
||||
{
|
||||
if (arts_handle != NULL) {
|
||||
SDL_UnloadObject(arts_handle);
|
||||
arts_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadARTSLibrary(void)
|
||||
{
|
||||
int i, retval = -1;
|
||||
|
||||
if (arts_handle == NULL) {
|
||||
arts_handle = SDL_LoadObject(arts_library);
|
||||
if (arts_handle != NULL) {
|
||||
retval = 0;
|
||||
for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
|
||||
*arts_functions[i].func =
|
||||
SDL_LoadFunction(arts_handle, arts_functions[i].name);
|
||||
if (!*arts_functions[i].func) {
|
||||
retval = -1;
|
||||
UnloadARTSLibrary();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
UnloadARTSLibrary()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
LoadARTSLibrary(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ARTS_DYNAMIC */
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
ARTS_WaitDevice(_THIS)
|
||||
{
|
||||
Sint32 ticks;
|
||||
|
||||
/* Check to see if the thread-parent process is still alive */
|
||||
{
|
||||
static int cnt = 0;
|
||||
/* Note that this only works with thread implementations
|
||||
that use a different process id for each thread.
|
||||
*/
|
||||
/* Check every 10 loops */
|
||||
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
|
||||
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Use timer for general audio synchronization */
|
||||
ticks =
|
||||
((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
|
||||
if (ticks > 0) {
|
||||
SDL_Delay(ticks);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ARTS_PlayDevice(_THIS)
|
||||
{
|
||||
/* Write the audio data */
|
||||
int written = SDL_NAME(arts_write) (this->hidden->stream,
|
||||
this->hidden->mixbuf,
|
||||
this->hidden->mixlen);
|
||||
|
||||
/* If timer synchronization is enabled, set the next write frame */
|
||||
if (this->hidden->frame_ticks) {
|
||||
this->hidden->next_frame += this->hidden->frame_ticks;
|
||||
}
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
ARTS_WaitDone(_THIS)
|
||||
{
|
||||
/* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
|
||||
}
|
||||
|
||||
|
||||
static Uint8 *
|
||||
ARTS_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ARTS_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->stream) {
|
||||
SDL_NAME(arts_close_stream) (this->hidden->stream);
|
||||
this->hidden->stream = 0;
|
||||
}
|
||||
SDL_NAME(arts_free) ();
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
int rc = 0;
|
||||
int bits = 0, frag_spec = 0;
|
||||
SDL_AudioFormat test_format = 0, format = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
bits = 8;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
bits = 16;
|
||||
format = 1;
|
||||
break;
|
||||
default:
|
||||
format = 0;
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (format == 0) {
|
||||
ARTS_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
if ((rc = SDL_NAME(arts_init) ()) != 0) {
|
||||
ARTS_CloseDevice(this);
|
||||
SDL_SetError("Unable to initialize ARTS: %s",
|
||||
SDL_NAME(arts_error_text) (rc));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SDL_NAME(arts_suspended) ()) {
|
||||
ARTS_CloseDevice(this);
|
||||
SDL_SetError("ARTS can not open audio device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->stream = SDL_NAME(arts_play_stream) (this->spec.freq,
|
||||
bits,
|
||||
this->spec.channels,
|
||||
"SDL");
|
||||
|
||||
/* Play nothing so we have at least one write (server bug workaround). */
|
||||
SDL_NAME(arts_write) (this->hidden->stream, "", 0);
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Determine the power of two of the fragment size */
|
||||
for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
|
||||
if ((0x01 << frag_spec) != this->spec.size) {
|
||||
ARTS_CloseDevice(this);
|
||||
SDL_SetError("Fragment size must be a power of two");
|
||||
return 0;
|
||||
}
|
||||
frag_spec |= 0x00020000; /* two fragments, for low latency */
|
||||
|
||||
#ifdef ARTS_P_PACKET_SETTINGS
|
||||
SDL_NAME(arts_stream_set) (this->hidden->stream,
|
||||
ARTS_P_PACKET_SETTINGS, frag_spec);
|
||||
#else
|
||||
SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
|
||||
frag_spec & 0xffff);
|
||||
SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
|
||||
frag_spec >> 16);
|
||||
#endif
|
||||
this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
|
||||
ARTS_P_PACKET_SIZE);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
ARTS_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* Get the parent process id (we're the parent of the audio thread) */
|
||||
this->hidden->parent = getpid();
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ARTS_Deinitialize(void)
|
||||
{
|
||||
UnloadARTSLibrary();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ARTS_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadARTSLibrary() < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
if (SDL_NAME(arts_init) () != 0) {
|
||||
UnloadARTSLibrary();
|
||||
SDL_SetError("ARTS: arts_init failed (no audio server?)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Play a stream so aRts doesn't crash */
|
||||
if (SDL_NAME(arts_suspended) ()) {
|
||||
arts_stream_t stream;
|
||||
stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
|
||||
SDL_NAME(arts_write) (stream, "", 0);
|
||||
SDL_NAME(arts_close_stream) (stream);
|
||||
}
|
||||
|
||||
SDL_NAME(arts_free) ();
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = ARTS_OpenDevice;
|
||||
impl->PlayDevice = ARTS_PlayDevice;
|
||||
impl->WaitDevice = ARTS_WaitDevice;
|
||||
impl->GetDeviceBuf = ARTS_GetDeviceBuf;
|
||||
impl->CloseDevice = ARTS_CloseDevice;
|
||||
impl->WaitDone = ARTS_WaitDone;
|
||||
impl->Deinitialize = ARTS_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap ARTS_bootstrap = {
|
||||
ARTS_DRIVER_NAME, "Analog RealTime Synthesizer", ARTS_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
52
thirdparty/SDL/src/audio/arts/SDL_artsaudio.h
vendored
Normal file
52
thirdparty/SDL/src/audio/arts/SDL_artsaudio.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_artscaudio_h
|
||||
#define _SDL_artscaudio_h
|
||||
|
||||
#include <artsc.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The stream descriptor for the audio device */
|
||||
arts_stream_t stream;
|
||||
|
||||
/* The parent process id, to detect when application quits */
|
||||
pid_t parent;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
/* Support for audio timing using a timer, in addition to select() */
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
#endif /* _SDL_artscaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
217
thirdparty/SDL/src/audio/baudio/SDL_beaudio.cc
vendored
Normal file
217
thirdparty/SDL/src/audio/baudio/SDL_beaudio.cc
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to the audio stream on BeOS */
|
||||
|
||||
#include <SoundPlayer.h>
|
||||
|
||||
#include "../../main/beos/SDL_BeApp.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "../../thread/beos/SDL_systhread_c.h"
|
||||
#include "SDL_beaudio.h"
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* !!! FIXME: have the callback call the higher level to avoid code dupe. */
|
||||
/* The BeOS callback for handling the audio buffer */
|
||||
static void
|
||||
FillSound(void *device, void *stream, size_t len,
|
||||
const media_raw_audio_format & format)
|
||||
{
|
||||
SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
|
||||
|
||||
/* Silence the buffer, since it's ours */
|
||||
SDL_memset(stream, audio->spec.silence, len);
|
||||
|
||||
/* Only do soemthing if audio is enabled */
|
||||
if (!audio->enabled)
|
||||
return;
|
||||
|
||||
if (!audio->paused) {
|
||||
if (audio->convert.needed) {
|
||||
SDL_mutexP(audio->mixer_lock);
|
||||
(*audio->spec.callback) (audio->spec.userdata,
|
||||
(Uint8 *) audio->convert.buf,
|
||||
audio->convert.len);
|
||||
SDL_mutexV(audio->mixer_lock);
|
||||
SDL_ConvertAudio(&audio->convert);
|
||||
SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
|
||||
} else {
|
||||
SDL_mutexP(audio->mixer_lock);
|
||||
(*audio->spec.callback) (audio->spec.userdata,
|
||||
(Uint8 *) stream, len);
|
||||
SDL_mutexV(audio->mixer_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BEOSAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (_this->hidden != NULL) {
|
||||
if (_this->hidden->audio_obj) {
|
||||
_this->hidden->audio_obj->Stop();
|
||||
delete _this->hidden->audio_obj;
|
||||
_this->hidden->audio_obj = NULL;
|
||||
}
|
||||
|
||||
delete _this->hidden;
|
||||
_this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
BEOSAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
int valid_datatype = 0;
|
||||
media_raw_audio_format format;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
_this->hidden = new SDL_PrivateAudioData;
|
||||
if (_this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
|
||||
|
||||
/* Parse the audio format and fill the Be raw audio format */
|
||||
SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
|
||||
format.byte_order = B_MEDIA_LITTLE_ENDIAN;
|
||||
format.frame_rate = (float) _this->spec.freq;
|
||||
format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
valid_datatype = 1;
|
||||
_this->spec.format = test_format;
|
||||
switch (test_format) {
|
||||
case AUDIO_S8:
|
||||
format.format = media_raw_audio_format::B_AUDIO_CHAR;
|
||||
break;
|
||||
|
||||
case AUDIO_U8:
|
||||
format.format = media_raw_audio_format::B_AUDIO_UCHAR;
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
break;
|
||||
|
||||
case AUDIO_S16MSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_SHORT;
|
||||
format.byte_order = B_MEDIA_BIG_ENDIAN;
|
||||
break;
|
||||
|
||||
case AUDIO_S32LSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_INT;
|
||||
break;
|
||||
|
||||
case AUDIO_S32MSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_INT;
|
||||
format.byte_order = B_MEDIA_BIG_ENDIAN;
|
||||
break;
|
||||
|
||||
case AUDIO_F32LSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
break;
|
||||
|
||||
case AUDIO_F32MSB:
|
||||
format.format = media_raw_audio_format::B_AUDIO_FLOAT;
|
||||
format.byte_order = B_MEDIA_BIG_ENDIAN;
|
||||
break;
|
||||
|
||||
default:
|
||||
valid_datatype = 0;
|
||||
test_format = SDL_NextAudioFormat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
format.buffer_size = _this->spec.samples;
|
||||
|
||||
if (!valid_datatype) { /* shouldn't happen, but just in case... */
|
||||
BEOSAUDIO_CloseDevice(_this);
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&_this->spec);
|
||||
|
||||
/* Subscribe to the audio stream (creates a new thread) */
|
||||
sigset_t omask;
|
||||
SDL_MaskSignals(&omask);
|
||||
_this->hidden->audio_obj = new BSoundPlayer(&format, "SDL Audio",
|
||||
FillSound, NULL, _this);
|
||||
SDL_UnmaskSignals(&omask);
|
||||
|
||||
if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
|
||||
_this->hidden->audio_obj->SetHasData(true);
|
||||
} else {
|
||||
BEOSAUDIO_CloseDevice(_this);
|
||||
SDL_SetError("Unable to start Be audio");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're running! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
BEOSAUDIO_Deinitialize(void)
|
||||
{
|
||||
SDL_QuitBeApp();
|
||||
}
|
||||
|
||||
static int
|
||||
BEOSAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Initialize the Be Application, if it's not already started */
|
||||
if (SDL_InitBeApp() < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = BEOSAUDIO_OpenDevice;
|
||||
impl->CloseDevice = BEOSAUDIO_CloseDevice;
|
||||
impl->Deinitialize = BEOSAUDIO_Deinitialize;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern AudioBootStrap BEOSAUDIO_bootstrap;
|
||||
}
|
||||
AudioBootStrap BEOSAUDIO_bootstrap = {
|
||||
"baudio", "BeOS BSoundPlayer", BEOSAUDIO_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
38
thirdparty/SDL/src/audio/baudio/SDL_beaudio.h
vendored
Normal file
38
thirdparty/SDL/src/audio/baudio/SDL_beaudio.h
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_beaudio_h
|
||||
#define _SDL_beaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *_this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
BSoundPlayer *audio_obj;
|
||||
};
|
||||
|
||||
#endif /* _SDL_beaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
455
thirdparty/SDL/src/audio/bsd/SDL_bsdaudio.c
vendored
Normal file
455
thirdparty/SDL/src/audio/bsd/SDL_bsdaudio.c
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/*
|
||||
* Driver for native OpenBSD/NetBSD audio(4).
|
||||
* vedge@vedge.com.ar.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/audioio.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_bsdaudio.h"
|
||||
|
||||
/* The tag name used by NetBSD/OpenBSD audio */
|
||||
#ifdef __NetBSD__
|
||||
#define BSD_AUDIO_DRIVER_NAME "netbsd"
|
||||
#define BSD_AUDIO_DRIVER_DESC "Native NetBSD audio"
|
||||
#else
|
||||
#define BSD_AUDIO_DRIVER_NAME "openbsd"
|
||||
#define BSD_AUDIO_DRIVER_DESC "Native OpenBSD audio"
|
||||
#endif
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
/* #define USE_BLOCKING_WRITES */
|
||||
|
||||
/* Use timer for synchronization */
|
||||
/* #define USE_TIMER_SYNC */
|
||||
|
||||
/* #define DEBUG_AUDIO */
|
||||
/* #define DEBUG_AUDIO_STREAM */
|
||||
|
||||
#ifdef USE_BLOCKING_WRITES
|
||||
#define OPEN_FLAGS_OUTPUT O_WRONLY
|
||||
#define OPEN_FLAGS_INPUT O_RDONLY
|
||||
#else
|
||||
#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK)
|
||||
#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
|
||||
#endif
|
||||
|
||||
/* !!! FIXME: so much cut and paste with dsp/dma drivers... */
|
||||
static char **outputDevices = NULL;
|
||||
static int outputDeviceCount = 0;
|
||||
static char **inputDevices = NULL;
|
||||
static int inputDeviceCount = 0;
|
||||
|
||||
static inline void
|
||||
free_device_list(char ***devs, int *count)
|
||||
{
|
||||
SDL_FreeUnixAudioDevices(devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_list(int iscapture, char ***devs, int *count)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
free_device_list(devs, count);
|
||||
SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_lists(void)
|
||||
{
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
free_device_lists(void)
|
||||
{
|
||||
free_device_list(&outputDevices, &outputDeviceCount);
|
||||
free_device_list(&inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
BSDAUDIO_Deinitialize(void)
|
||||
{
|
||||
free_device_lists();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
BSDAUDIO_DetectDevices(int iscapture)
|
||||
{
|
||||
if (iscapture) {
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
return inputDeviceCount;
|
||||
} else {
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
return outputDeviceCount;
|
||||
}
|
||||
|
||||
return 0; /* shouldn't ever hit this. */
|
||||
}
|
||||
|
||||
static const char *
|
||||
BSDAUDIO_GetDeviceName(int index, int iscapture)
|
||||
{
|
||||
if ((iscapture) && (index < inputDeviceCount)) {
|
||||
return inputDevices[index];
|
||||
} else if ((!iscapture) && (index < outputDeviceCount)) {
|
||||
return outputDevices[index];
|
||||
}
|
||||
|
||||
SDL_SetError("No such device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
BSDAUDIO_Status(_THIS)
|
||||
{
|
||||
#ifdef DEBUG_AUDIO
|
||||
/* *INDENT-OFF* */
|
||||
audio_info_t info;
|
||||
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
|
||||
fprintf(stderr, "AUDIO_GETINFO failed.\n");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "\n"
|
||||
"[play/record info]\n"
|
||||
"buffer size : %d bytes\n"
|
||||
"sample rate : %i Hz\n"
|
||||
"channels : %i\n"
|
||||
"precision : %i-bit\n"
|
||||
"encoding : 0x%x\n"
|
||||
"seek : %i\n"
|
||||
"sample count : %i\n"
|
||||
"EOF count : %i\n"
|
||||
"paused : %s\n"
|
||||
"error occured : %s\n"
|
||||
"waiting : %s\n"
|
||||
"active : %s\n"
|
||||
"",
|
||||
info.play.buffer_size,
|
||||
info.play.sample_rate,
|
||||
info.play.channels,
|
||||
info.play.precision,
|
||||
info.play.encoding,
|
||||
info.play.seek,
|
||||
info.play.samples,
|
||||
info.play.eof,
|
||||
info.play.pause ? "yes" : "no",
|
||||
info.play.error ? "yes" : "no",
|
||||
info.play.waiting ? "yes" : "no",
|
||||
info.play.active ? "yes" : "no");
|
||||
|
||||
fprintf(stderr, "\n"
|
||||
"[audio info]\n"
|
||||
"monitor_gain : %i\n"
|
||||
"hw block size : %d bytes\n"
|
||||
"hi watermark : %i\n"
|
||||
"lo watermark : %i\n"
|
||||
"audio mode : %s\n"
|
||||
"",
|
||||
info.monitor_gain,
|
||||
info.blocksize,
|
||||
info.hiwat, info.lowat,
|
||||
(info.mode == AUMODE_PLAY) ? "PLAY"
|
||||
: (info.mode = AUMODE_RECORD) ? "RECORD"
|
||||
: (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
|
||||
/* *INDENT-ON* */
|
||||
#endif /* DEBUG_AUDIO */
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
BSDAUDIO_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 select() for audio synchronization */
|
||||
fd_set fdset;
|
||||
struct timeval timeout;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(this->hidden->audio_fd, &fdset);
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Waiting for audio to get ready\n");
|
||||
#endif
|
||||
if (select(this->hidden->audio_fd + 1, NULL, &fdset, NULL, &timeout)
|
||||
<= 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);
|
||||
this->enabled = 0;
|
||||
/* 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
|
||||
BSDAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
int written, p = 0;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (p < written
|
||||
|| ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
|
||||
SDL_Delay(1); /* Let a little CPU time go by */
|
||||
}
|
||||
} while (p < written);
|
||||
|
||||
/* 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) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
BSDAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
BSDAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->audio_fd >= 0) {
|
||||
close(this->hidden->audio_fd);
|
||||
this->hidden->audio_fd = -1;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
SDL_AudioFormat format = 0;
|
||||
audio_info_t info;
|
||||
|
||||
/* We don't care what the devname is...we'll try to open anything. */
|
||||
/* ...but default to first name in the list... */
|
||||
if (devname == NULL) {
|
||||
if (((iscapture) && (inputDeviceCount == 0)) ||
|
||||
((!iscapture) && (outputDeviceCount == 0))) {
|
||||
SDL_SetError("No such audio device");
|
||||
return 0;
|
||||
}
|
||||
devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
|
||||
}
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
this->hidden->audio_fd = open(devname, flags, 0);
|
||||
if (this->hidden->audio_fd < 0) {
|
||||
SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Set to play mode */
|
||||
info.mode = AUMODE_PLAY;
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
|
||||
BSDAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Couldn't put device into play mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
for (format = SDL_FirstAudioFormat(this->spec.format);
|
||||
format; format = SDL_NextAudioFormat()) {
|
||||
switch (format) {
|
||||
case AUDIO_U8:
|
||||
info.play.encoding = AUDIO_ENCODING_ULINEAR;
|
||||
info.play.precision = 8;
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
info.play.encoding = AUDIO_ENCODING_SLINEAR;
|
||||
info.play.precision = 8;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
|
||||
info.play.precision = 16;
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
|
||||
info.play.precision = 16;
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
|
||||
info.play.precision = 16;
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
|
||||
info.play.precision = 16;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!format) {
|
||||
BSDAUDIO_CloseDevice(this);
|
||||
SDL_SetError("No supported encoding for 0x%x", this->spec.format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->spec.format = format;
|
||||
|
||||
AUDIO_INITINFO(&info);
|
||||
info.play.channels = this->spec.channels;
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
|
||||
this->spec.channels = 1;
|
||||
}
|
||||
AUDIO_INITINFO(&info);
|
||||
info.play.sample_rate = this->spec.freq;
|
||||
info.blocksize = this->spec.size;
|
||||
info.hiwat = 5;
|
||||
info.lowat = 3;
|
||||
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
|
||||
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
|
||||
this->spec.freq = info.play.sample_rate;
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
BSDAUDIO_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
BSDAUDIO_Status(this);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = BSDAUDIO_DetectDevices;
|
||||
impl->GetDeviceName = BSDAUDIO_GetDeviceName;
|
||||
impl->OpenDevice = BSDAUDIO_OpenDevice;
|
||||
impl->PlayDevice = BSDAUDIO_PlayDevice;
|
||||
impl->WaitDevice = BSDAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = BSDAUDIO_CloseDevice;
|
||||
impl->Deinitialize = BSDAUDIO_Deinitialize;
|
||||
|
||||
build_device_lists();
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap BSD_AUDIO_bootstrap = {
|
||||
BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, BSDAUDIO_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
51
thirdparty/SDL/src/audio/bsd/SDL_bsdaudio.h
vendored
Normal file
51
thirdparty/SDL/src/audio/bsd/SDL_bsdaudio.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_bsdaudio_h
|
||||
#define _SDL_bsdaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
/* The parent process id, to detect when application quits */
|
||||
pid_t parent;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
/* Support for audio timing using a timer, in addition to select() */
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
#endif /* _SDL_bsdaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
165
thirdparty/SDL/src/audio/disk/SDL_diskaudio.c
vendored
Normal file
165
thirdparty/SDL/src/audio/disk/SDL_diskaudio.c
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Output raw audio data to a file. */
|
||||
|
||||
#if HAVE_STDIO_H
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_diskaudio.h"
|
||||
|
||||
/* The tag name used by DISK audio */
|
||||
#define DISKAUD_DRIVER_NAME "disk"
|
||||
|
||||
/* environment variables and defaults. */
|
||||
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
|
||||
#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
|
||||
#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY"
|
||||
#define DISKDEFAULT_WRITEDELAY 150
|
||||
|
||||
static const char *
|
||||
DISKAUD_GetOutputFilename(const char *devname)
|
||||
{
|
||||
if (devname == NULL) {
|
||||
devname = SDL_getenv(DISKENVR_OUTFILE);
|
||||
if (devname == NULL) {
|
||||
devname = DISKDEFAULT_OUTFILE;
|
||||
}
|
||||
}
|
||||
return devname;
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
DISKAUD_WaitDevice(_THIS)
|
||||
{
|
||||
SDL_Delay(this->hidden->write_delay);
|
||||
}
|
||||
|
||||
static void
|
||||
DISKAUD_PlayDevice(_THIS)
|
||||
{
|
||||
size_t written;
|
||||
|
||||
/* Write the audio data */
|
||||
written = SDL_RWwrite(this->hidden->output,
|
||||
this->hidden->mixbuf, 1, this->hidden->mixlen);
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written != this->hidden->mixlen) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
DISKAUD_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
DISKAUD_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->output != NULL) {
|
||||
SDL_RWclose(this->hidden->output);
|
||||
this->hidden->output = NULL;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
|
||||
const char *fname = DISKAUD_GetOutputFilename(devname);
|
||||
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc(sizeof(*this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, sizeof(*this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
this->hidden->output = SDL_RWFromFile(fname, "wb");
|
||||
if (this->hidden->output == NULL) {
|
||||
DISKAUD_CloseDevice(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
DISKAUD_CloseDevice(this);
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->write_delay =
|
||||
(envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
|
||||
|
||||
#if HAVE_STDIO_H
|
||||
fprintf(stderr,
|
||||
"WARNING: You are using the SDL disk writer audio driver!\n"
|
||||
" Writing to file [%s].\n", fname);
|
||||
#endif
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
DISKAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = DISKAUD_OpenDevice;
|
||||
impl->WaitDevice = DISKAUD_WaitDevice;
|
||||
impl->PlayDevice = DISKAUD_PlayDevice;
|
||||
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
|
||||
impl->CloseDevice = DISKAUD_CloseDevice;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap DISKAUD_bootstrap = {
|
||||
DISKAUD_DRIVER_NAME, "direct-to-disk audio", DISKAUD_Init, 1
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
42
thirdparty/SDL/src/audio/disk/SDL_diskaudio.h
vendored
Normal file
42
thirdparty/SDL/src/audio/disk/SDL_diskaudio.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_diskaudio_h
|
||||
#define _SDL_diskaudio_h
|
||||
|
||||
#include "SDL_rwops.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
SDL_RWops *output;
|
||||
Uint8 *mixbuf;
|
||||
Uint32 mixlen;
|
||||
Uint32 write_delay;
|
||||
};
|
||||
|
||||
#endif /* _SDL_diskaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
534
thirdparty/SDL/src/audio/dma/SDL_dmaaudio.c
vendored
Normal file
534
thirdparty/SDL/src/audio/dma/SDL_dmaaudio.c
vendored
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* !!! FIXME: merge this driver with "dsp". */
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* For strerror() */
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
|
||||
/* This is installed on some systems */
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
/* This is recommended by OSS */
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAP_FAILED
|
||||
#define MAP_FAILED ((Uint8 *)-1)
|
||||
#endif
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_dmaaudio.h"
|
||||
|
||||
/* The tag name used by DMA audio */
|
||||
#define DMA_DRIVER_NAME "dma"
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
#define OPEN_FLAGS_INPUT (O_RDWR|O_NONBLOCK)
|
||||
#define OPEN_FLAGS_OUTPUT (O_RDWR|O_NONBLOCK)
|
||||
|
||||
static char **outputDevices = NULL;
|
||||
static int outputDeviceCount = 0;
|
||||
static char **inputDevices = NULL;
|
||||
static int inputDeviceCount = 0;
|
||||
|
||||
static int
|
||||
test_for_mmap(int fd)
|
||||
{
|
||||
int caps = 0;
|
||||
struct audio_buf_info info;
|
||||
if ((ioctl(fd, SNDCTL_DSP_GETCAPS, &caps) == 0) &&
|
||||
(caps & DSP_CAP_TRIGGER) && (caps & DSP_CAP_MMAP) &&
|
||||
(ioctl(fd, SNDCTL_DSP_GETOSPACE, &info) == 0)) {
|
||||
size_t len = info.fragstotal * info.fragsize;
|
||||
Uint8 *buf = (Uint8 *) mmap(NULL, len, PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (buf != MAP_FAILED) {
|
||||
munmap(buf, len);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
free_device_list(char ***devs, int *count)
|
||||
{
|
||||
SDL_FreeUnixAudioDevices(devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_list(int iscapture, char ***devs, int *count)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
free_device_list(devs, count);
|
||||
SDL_EnumUnixAudioDevices(flags, 0, test_for_mmap, devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_lists(void)
|
||||
{
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
free_device_lists(void)
|
||||
{
|
||||
free_device_list(&outputDevices, &outputDeviceCount);
|
||||
free_device_list(&inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DMA_Deinitialize(void)
|
||||
{
|
||||
free_device_lists();
|
||||
}
|
||||
|
||||
static int
|
||||
DMA_DetectDevices(int iscapture)
|
||||
{
|
||||
if (iscapture) {
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
return inputDeviceCount;
|
||||
} else {
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
return outputDeviceCount;
|
||||
}
|
||||
|
||||
return 0; /* shouldn't ever hit this. */
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
DMA_GetDeviceName(int index, int iscapture)
|
||||
{
|
||||
if ((iscapture) && (index < inputDeviceCount)) {
|
||||
return inputDevices[index];
|
||||
} else if ((!iscapture) && (index < outputDeviceCount)) {
|
||||
return outputDevices[index];
|
||||
}
|
||||
|
||||
SDL_SetError("No such device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DMA_ReopenAudio(_THIS, const char *audiodev, int format, int stereo)
|
||||
{
|
||||
int frag_spec;
|
||||
int value;
|
||||
|
||||
/* Close and then reopen the audio device */
|
||||
close(audio_fd);
|
||||
audio_fd = open(audiodev, O_RDWR, 0);
|
||||
if (audio_fd < 0) {
|
||||
SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Determine the power of two of the fragment size */
|
||||
for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
|
||||
if ((0x01 << frag_spec) != this->spec.size) {
|
||||
SDL_SetError("Fragment size must be a power of two");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set the audio buffering parameters */
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
|
||||
SDL_SetError("Couldn't set audio fragment spec");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set the audio format */
|
||||
value = format;
|
||||
if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
|
||||
SDL_SetError("Couldn't set audio format");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set mono or stereo audio */
|
||||
value = (this->spec.channels > 1);
|
||||
if ((ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) < 0) ||
|
||||
(value != stereo)) {
|
||||
SDL_SetError("Couldn't set audio channels");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Set the DSP frequency */
|
||||
value = this->spec.freq;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
|
||||
SDL_SetError("Couldn't set audio frequency");
|
||||
return (-1);
|
||||
}
|
||||
this->spec.freq = value;
|
||||
|
||||
/* We successfully re-opened the audio */
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DMA_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (dma_buf != NULL) {
|
||||
munmap(dma_buf, dma_len);
|
||||
dma_buf = NULL;
|
||||
}
|
||||
if (audio_fd >= 0) {
|
||||
close(audio_fd);
|
||||
audio_fd = -1;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DMA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
int format;
|
||||
int stereo;
|
||||
int value;
|
||||
SDL_AudioFormat test_format;
|
||||
struct audio_buf_info info;
|
||||
|
||||
/* We don't care what the devname is...we'll try to open anything. */
|
||||
/* ...but default to first name in the list... */
|
||||
if (devname == NULL) {
|
||||
if (((iscapture) && (inputDeviceCount == 0)) ||
|
||||
((!iscapture) && (outputDeviceCount == 0))) {
|
||||
SDL_SetError("No such audio device");
|
||||
return 0;
|
||||
}
|
||||
devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
|
||||
}
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
audio_fd = open(devname, flags, 0);
|
||||
if (audio_fd < 0) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
dma_buf = NULL;
|
||||
ioctl(audio_fd, SNDCTL_DSP_RESET, 0);
|
||||
|
||||
/* Get a list of supported hardware formats */
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't get audio format list");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
format = 0;
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
if (value & AFMT_U8) {
|
||||
format = AFMT_U8;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
if (value & AFMT_S8) {
|
||||
format = AFMT_S8;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
if (value & AFMT_S16_LE) {
|
||||
format = AFMT_S16_LE;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
if (value & AFMT_S16_BE) {
|
||||
format = AFMT_S16_BE;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
if (value & AFMT_U16_LE) {
|
||||
format = AFMT_U16_LE;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
if (value & AFMT_U16_BE) {
|
||||
format = AFMT_U16_BE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
format = 0;
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (format == 0) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Set the audio format */
|
||||
value = format;
|
||||
if ((ioctl(audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) || (value != format)) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set mono or stereo audio (currently only two channels supported) */
|
||||
stereo = (this->spec.channels > 1);
|
||||
ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
|
||||
if (stereo) {
|
||||
this->spec.channels = 2;
|
||||
} else {
|
||||
this->spec.channels = 1;
|
||||
}
|
||||
|
||||
/* Because some drivers don't allow setting the buffer size
|
||||
after setting the format, we must re-open the audio device
|
||||
once we know what format and channels are supported
|
||||
*/
|
||||
if (DMA_ReopenAudio(this, devname, format, stereo) < 0) {
|
||||
DMA_CloseDevice(this);
|
||||
/* Error is set by DMA_ReopenAudio() */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Memory map the audio buffer */
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't get OSPACE parameters");
|
||||
return 0;
|
||||
}
|
||||
this->spec.size = info.fragsize;
|
||||
this->spec.samples = this->spec.size / ((this->spec.format & 0xFF) / 8);
|
||||
this->spec.samples /= this->spec.channels;
|
||||
num_buffers = info.fragstotal;
|
||||
dma_len = num_buffers * this->spec.size;
|
||||
dma_buf = (Uint8 *) mmap(NULL, dma_len, PROT_WRITE, MAP_SHARED,
|
||||
audio_fd, 0);
|
||||
if (dma_buf == MAP_FAILED) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("DMA memory map failed");
|
||||
dma_buf = NULL;
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(dma_buf, this->spec.silence, dma_len);
|
||||
|
||||
/* Check to see if we need to use select() workaround */
|
||||
{
|
||||
char *workaround;
|
||||
workaround = SDL_getenv("SDL_DSP_NOSELECT");
|
||||
if (workaround) {
|
||||
frame_ticks =
|
||||
(float) (this->spec.samples * 1000) / this->spec.freq;
|
||||
next_frame = SDL_GetTicks() + frame_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/* Trigger audio playback */
|
||||
value = 0;
|
||||
ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value);
|
||||
value = PCM_ENABLE_OUTPUT;
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_SETTRIGGER, &value) < 0) {
|
||||
DMA_CloseDevice(this);
|
||||
SDL_SetError("Couldn't trigger audio output");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the parent process id (we're the parent of the audio thread) */
|
||||
parent = getpid();
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
DMA_WaitDevice(_THIS)
|
||||
{
|
||||
fd_set fdset;
|
||||
|
||||
/* Check to see if the thread-parent process is still alive */
|
||||
{
|
||||
static int cnt = 0;
|
||||
/* Note that this only works with thread implementations
|
||||
that use a different process id for each thread.
|
||||
*/
|
||||
if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */
|
||||
if (kill(parent, 0) < 0 && errno == ESRCH) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we need to use timed audio synchronization */
|
||||
if (frame_ticks) {
|
||||
/* Use timer for general audio synchronization */
|
||||
Sint32 ticks;
|
||||
|
||||
ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
|
||||
if (ticks > 0) {
|
||||
SDL_Delay(ticks);
|
||||
}
|
||||
} else {
|
||||
/* Use select() for audio synchronization */
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(audio_fd, &fdset);
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Waiting for audio to get ready\n");
|
||||
#endif
|
||||
if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
|
||||
const char *message =
|
||||
#ifdef AUDIO_OSPACE_HACK
|
||||
"Audio timeout - buggy audio driver? (trying ospace)";
|
||||
#else
|
||||
"Audio timeout - buggy audio driver? (disabled)";
|
||||
#endif
|
||||
/* 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);
|
||||
#ifdef AUDIO_OSPACE_HACK
|
||||
/* We may be able to use GET_OSPACE trick */
|
||||
frame_ticks = (float) (this->spec.samples * 1000) /
|
||||
this->spec.freq;
|
||||
next_frame = SDL_GetTicks() + frame_ticks;
|
||||
#else
|
||||
this->enabled = 0;
|
||||
/* Don't try to close - may hang */
|
||||
audio_fd = -1;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Done disabling audio\n");
|
||||
#endif
|
||||
#endif /* AUDIO_OSPACE_HACK */
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Ready!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DMA_PlayDevice(_THIS)
|
||||
{
|
||||
/* If timer synchronization is enabled, set the next write frame */
|
||||
if (frame_ticks) {
|
||||
next_frame += frame_ticks;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
DMA_GetDeviceBuf(_THIS)
|
||||
{
|
||||
count_info info;
|
||||
int playing;
|
||||
int filling;
|
||||
|
||||
/* Get number of blocks, looping if we're not using select() */
|
||||
do {
|
||||
if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
|
||||
/* Uh oh... */
|
||||
this->enabled = 0;
|
||||
return (NULL);
|
||||
}
|
||||
} while (frame_ticks && (info.blocks < 1));
|
||||
#ifdef DEBUG_AUDIO
|
||||
if (info.blocks > 1) {
|
||||
printf("Warning: audio underflow (%d frags)\n", info.blocks - 1);
|
||||
}
|
||||
#endif
|
||||
playing = info.ptr / this->spec.size;
|
||||
filling = (playing + 1) % num_buffers;
|
||||
return (dma_buf + (filling * this->spec.size));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DMA_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = DMA_DetectDevices;
|
||||
impl->GetDeviceName = DMA_GetDeviceName;
|
||||
impl->OpenDevice = DMA_OpenDevice;
|
||||
impl->WaitDevice = DMA_WaitDevice;
|
||||
impl->PlayDevice = DMA_PlayDevice;
|
||||
impl->GetDeviceBuf = DMA_GetDeviceBuf;
|
||||
impl->CloseDevice = DMA_CloseDevice;
|
||||
impl->Deinitialize = DMA_Deinitialize;
|
||||
|
||||
build_device_lists();
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap DMA_bootstrap = {
|
||||
DMA_DRIVER_NAME, "OSS /dev/dsp DMA audio", DMA_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
62
thirdparty/SDL/src/audio/dma/SDL_dmaaudio.h
vendored
Normal file
62
thirdparty/SDL/src/audio/dma/SDL_dmaaudio.h
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_dmaaudio_h
|
||||
#define _SDL_dmaaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
/* The parent process id, to detect when application quits */
|
||||
pid_t parent;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *dma_buf;
|
||||
int dma_len;
|
||||
int num_buffers;
|
||||
|
||||
/* Support for audio timing using a timer, in addition to select() */
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
/* Old variable names */
|
||||
/* !!! FIXME: remove these. */
|
||||
#define audio_fd (this->hidden->audio_fd)
|
||||
#define parent (this->hidden->parent)
|
||||
#define dma_buf (this->hidden->dma_buf)
|
||||
#define dma_len (this->hidden->dma_len)
|
||||
#define num_buffers (this->hidden->num_buffers)
|
||||
#define frame_ticks (this->hidden->frame_ticks)
|
||||
#define next_frame (this->hidden->next_frame)
|
||||
|
||||
#endif /* _SDL_dmaaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
389
thirdparty/SDL/src/audio/dsp/SDL_dspaudio.c
vendored
Normal file
389
thirdparty/SDL/src/audio/dsp/SDL_dspaudio.c
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <stdio.h> /* For perror() */
|
||||
#include <string.h> /* For strerror() */
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
|
||||
/* This is installed on some systems */
|
||||
#include <soundcard.h>
|
||||
#else
|
||||
/* This is recommended by OSS */
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_dspaudio.h"
|
||||
|
||||
/* The tag name used by DSP audio */
|
||||
#define DSP_DRIVER_NAME "dsp"
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
#define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK)
|
||||
#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
|
||||
|
||||
static char **outputDevices = NULL;
|
||||
static int outputDeviceCount = 0;
|
||||
static char **inputDevices = NULL;
|
||||
static int inputDeviceCount = 0;
|
||||
|
||||
static inline void
|
||||
free_device_list(char ***devs, int *count)
|
||||
{
|
||||
SDL_FreeUnixAudioDevices(devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_list(int iscapture, char ***devs, int *count)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
free_device_list(devs, count);
|
||||
SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_lists(void)
|
||||
{
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
free_device_lists(void)
|
||||
{
|
||||
free_device_list(&outputDevices, &outputDeviceCount);
|
||||
free_device_list(&inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DSP_Deinitialize(void)
|
||||
{
|
||||
free_device_lists();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DSP_DetectDevices(int iscapture)
|
||||
{
|
||||
if (iscapture) {
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
return inputDeviceCount;
|
||||
} else {
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
return outputDeviceCount;
|
||||
}
|
||||
|
||||
return 0; /* shouldn't ever hit this. */
|
||||
}
|
||||
|
||||
static const char *
|
||||
DSP_GetDeviceName(int index, int iscapture)
|
||||
{
|
||||
if ((iscapture) && (index < inputDeviceCount)) {
|
||||
return inputDevices[index];
|
||||
} else if ((!iscapture) && (index < outputDeviceCount)) {
|
||||
return outputDevices[index];
|
||||
}
|
||||
|
||||
SDL_SetError("No such device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DSP_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->audio_fd >= 0) {
|
||||
close(this->hidden->audio_fd);
|
||||
this->hidden->audio_fd = -1;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DSP_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
|
||||
int format;
|
||||
int value;
|
||||
int frag_spec;
|
||||
SDL_AudioFormat test_format;
|
||||
|
||||
/* We don't care what the devname is...we'll try to open anything. */
|
||||
/* ...but default to first name in the list... */
|
||||
if (devname == NULL) {
|
||||
if (((iscapture) && (inputDeviceCount == 0)) ||
|
||||
((!iscapture) && (outputDeviceCount == 0))) {
|
||||
SDL_SetError("No such audio device");
|
||||
return 0;
|
||||
}
|
||||
devname = ((iscapture) ? inputDevices[0] : outputDevices[0]);
|
||||
}
|
||||
|
||||
/* Make sure fragment size stays a power of 2, or OSS fails. */
|
||||
/* I don't know which of these are actually legal values, though... */
|
||||
if (this->spec.channels > 8)
|
||||
this->spec.channels = 8;
|
||||
else if (this->spec.channels > 4)
|
||||
this->spec.channels = 4;
|
||||
else if (this->spec.channels > 2)
|
||||
this->spec.channels = 2;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
this->hidden->audio_fd = open(devname, flags, 0);
|
||||
if (this->hidden->audio_fd < 0) {
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
this->hidden->mixbuf = NULL;
|
||||
|
||||
/* Make the file descriptor use blocking writes with fcntl() */
|
||||
{
|
||||
long ctlflags;
|
||||
ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
|
||||
ctlflags &= ~O_NONBLOCK;
|
||||
if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set audio blocking mode");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get a list of supported hardware formats */
|
||||
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
|
||||
perror("SNDCTL_DSP_GETFMTS");
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't get audio format list");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
format = 0;
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
if (value & AFMT_U8) {
|
||||
format = AFMT_U8;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
if (value & AFMT_S16_LE) {
|
||||
format = AFMT_S16_LE;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
if (value & AFMT_S16_BE) {
|
||||
format = AFMT_S16_BE;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
/*
|
||||
* These formats are not used by any real life systems so they are not
|
||||
* needed here.
|
||||
*/
|
||||
case AUDIO_S8:
|
||||
if (value & AFMT_S8) {
|
||||
format = AFMT_S8;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
if (value & AFMT_U16_LE) {
|
||||
format = AFMT_U16_LE;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
if (value & AFMT_U16_BE) {
|
||||
format = AFMT_U16_BE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
format = 0;
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (format == 0) {
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Set the audio format */
|
||||
value = format;
|
||||
if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
|
||||
(value != format)) {
|
||||
perror("SNDCTL_DSP_SETFMT");
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the number of channels of output */
|
||||
value = this->spec.channels;
|
||||
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
|
||||
perror("SNDCTL_DSP_CHANNELS");
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Cannot set the number of channels");
|
||||
return 0;
|
||||
}
|
||||
this->spec.channels = value;
|
||||
|
||||
/* Set the DSP frequency */
|
||||
value = this->spec.freq;
|
||||
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
|
||||
perror("SNDCTL_DSP_SPEED");
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Couldn't set audio frequency");
|
||||
return 0;
|
||||
}
|
||||
this->spec.freq = value;
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Determine the power of two of the fragment size */
|
||||
for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
|
||||
if ((0x01U << frag_spec) != this->spec.size) {
|
||||
DSP_CloseDevice(this);
|
||||
SDL_SetError("Fragment size must be a power of two");
|
||||
return 0;
|
||||
}
|
||||
frag_spec |= 0x00020000; /* two fragments, for low latency */
|
||||
|
||||
/* Set the audio buffering parameters */
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Requesting %d fragments of size %d\n",
|
||||
(frag_spec >> 16), 1 << (frag_spec & 0xFFFF));
|
||||
#endif
|
||||
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag_spec) < 0) {
|
||||
perror("SNDCTL_DSP_SETFRAGMENT");
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
{
|
||||
audio_buf_info info;
|
||||
ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETOSPACE, &info);
|
||||
fprintf(stderr, "fragments = %d\n", info.fragments);
|
||||
fprintf(stderr, "fragstotal = %d\n", info.fragstotal);
|
||||
fprintf(stderr, "fragsize = %d\n", info.fragsize);
|
||||
fprintf(stderr, "bytes = %d\n", info.bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
DSP_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DSP_PlayDevice(_THIS)
|
||||
{
|
||||
const Uint8 *mixbuf = this->hidden->mixbuf;
|
||||
const int mixlen = this->hidden->mixlen;
|
||||
if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
|
||||
perror("Audio write");
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
DSP_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static int
|
||||
DSP_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = DSP_DetectDevices;
|
||||
impl->GetDeviceName = DSP_GetDeviceName;
|
||||
impl->OpenDevice = DSP_OpenDevice;
|
||||
impl->PlayDevice = DSP_PlayDevice;
|
||||
impl->GetDeviceBuf = DSP_GetDeviceBuf;
|
||||
impl->CloseDevice = DSP_CloseDevice;
|
||||
impl->Deinitialize = DSP_Deinitialize;
|
||||
|
||||
build_device_lists();
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap DSP_bootstrap = {
|
||||
DSP_DRIVER_NAME, "OSS /dev/dsp standard audio", DSP_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
43
thirdparty/SDL/src/audio/dsp/SDL_dspaudio.h
vendored
Normal file
43
thirdparty/SDL/src/audio/dsp/SDL_dspaudio.h
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_dspaudio_h
|
||||
#define _SDL_dspaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
};
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
#endif /* _SDL_dspaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
48
thirdparty/SDL/src/audio/dummy/SDL_dummyaudio.c
vendored
Normal file
48
thirdparty/SDL/src/audio/dummy/SDL_dummyaudio.c
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Output audio to nowhere... */
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_dummyaudio.h"
|
||||
|
||||
static int
|
||||
DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
return 1; /* always succeeds. */
|
||||
}
|
||||
|
||||
static int
|
||||
DUMMYAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = DUMMYAUD_OpenDevice;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap DUMMYAUD_bootstrap = {
|
||||
"dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
41
thirdparty/SDL/src/audio/dummy/SDL_dummyaudio.h
vendored
Normal file
41
thirdparty/SDL/src/audio/dummy/SDL_dummyaudio.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_dummyaudio_h
|
||||
#define _SDL_dummyaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
Uint8 *mixbuf;
|
||||
Uint32 mixlen;
|
||||
Uint32 write_delay;
|
||||
Uint32 initial_calls;
|
||||
};
|
||||
|
||||
#endif /* _SDL_dummyaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
351
thirdparty/SDL/src/audio/esd/SDL_esdaudio.c
vendored
Normal file
351
thirdparty/SDL/src/audio/esd/SDL_esdaudio.c
vendored
Normal file
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to an ESD network stream mixing buffer */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <esd.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_esdaudio.h"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
|
||||
#include "SDL_name.h"
|
||||
#include "SDL_loadso.h"
|
||||
#else
|
||||
#define SDL_NAME(X) X
|
||||
#endif
|
||||
|
||||
/* The tag name used by ESD audio */
|
||||
#define ESD_DRIVER_NAME "esd"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_ESD_DYNAMIC
|
||||
|
||||
static const char *esd_library = SDL_AUDIO_DRIVER_ESD_DYNAMIC;
|
||||
static void *esd_handle = NULL;
|
||||
|
||||
static int (*SDL_NAME(esd_open_sound)) (const char *host);
|
||||
static int (*SDL_NAME(esd_close)) (int esd);
|
||||
static int (*SDL_NAME(esd_play_stream)) (esd_format_t format, int rate,
|
||||
const char *host, const char *name);
|
||||
|
||||
#define SDL_ESD_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
void **func;
|
||||
} const esd_functions[] = {
|
||||
SDL_ESD_SYM(esd_open_sound),
|
||||
SDL_ESD_SYM(esd_close), SDL_ESD_SYM(esd_play_stream),
|
||||
};
|
||||
|
||||
#undef SDL_ESD_SYM
|
||||
|
||||
static void
|
||||
UnloadESDLibrary()
|
||||
{
|
||||
if (esd_handle != NULL) {
|
||||
SDL_UnloadObject(esd_handle);
|
||||
esd_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadESDLibrary(void)
|
||||
{
|
||||
int i, retval = -1;
|
||||
|
||||
if (esd_handle == NULL) {
|
||||
esd_handle = SDL_LoadObject(esd_library);
|
||||
if (esd_handle) {
|
||||
retval = 0;
|
||||
for (i = 0; i < SDL_arraysize(esd_functions); ++i) {
|
||||
*esd_functions[i].func =
|
||||
SDL_LoadFunction(esd_handle, esd_functions[i].name);
|
||||
if (!*esd_functions[i].func) {
|
||||
retval = -1;
|
||||
UnloadESDLibrary();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
UnloadESDLibrary()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
LoadESDLibrary(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_ESD_DYNAMIC */
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
ESD_WaitDevice(_THIS)
|
||||
{
|
||||
Sint32 ticks;
|
||||
|
||||
/* Check to see if the thread-parent process is still alive */
|
||||
{
|
||||
static int cnt = 0;
|
||||
/* Note that this only works with thread implementations
|
||||
that use a different process id for each thread.
|
||||
*/
|
||||
/* Check every 10 loops */
|
||||
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
|
||||
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Use timer for general audio synchronization */
|
||||
ticks =
|
||||
((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
|
||||
if (ticks > 0) {
|
||||
SDL_Delay(ticks);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ESD_PlayDevice(_THIS)
|
||||
{
|
||||
int written = 0;
|
||||
|
||||
/* Write the audio data, checking for EAGAIN on broken audio drivers */
|
||||
do {
|
||||
written = write(this->hidden->audio_fd,
|
||||
this->hidden->mixbuf, this->hidden->mixlen);
|
||||
if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
|
||||
SDL_Delay(1); /* Let a little CPU time go by */
|
||||
}
|
||||
} while ((written < 0) &&
|
||||
((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
|
||||
|
||||
/* Set the next write frame */
|
||||
this->hidden->next_frame += this->hidden->frame_ticks;
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
ESD_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
ESD_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->audio_fd >= 0) {
|
||||
SDL_NAME(esd_close) (this->hidden->audio_fd);
|
||||
this->hidden->audio_fd = -1;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to get the name of the program */
|
||||
static char *
|
||||
get_progname(void)
|
||||
{
|
||||
char *progname = NULL;
|
||||
#ifdef __LINUX__
|
||||
FILE *fp;
|
||||
static char temp[BUFSIZ];
|
||||
|
||||
SDL_snprintf(temp, SDL_arraysize(temp), "/proc/%d/cmdline", getpid());
|
||||
fp = fopen(temp, "r");
|
||||
if (fp != NULL) {
|
||||
if (fgets(temp, sizeof(temp) - 1, fp)) {
|
||||
progname = SDL_strrchr(temp, '/');
|
||||
if (progname == NULL) {
|
||||
progname = temp;
|
||||
} else {
|
||||
progname = progname + 1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
#endif
|
||||
return (progname);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ESD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
esd_format_t format = (ESD_STREAM | ESD_PLAY);
|
||||
SDL_AudioFormat test_format = 0;
|
||||
int found = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
this->hidden->audio_fd = -1;
|
||||
|
||||
/* Convert audio spec to the ESD audio format */
|
||||
/* Try for a closest match on audio format */
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!found && test_format; test_format = SDL_NextAudioFormat()) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
found = 1;
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
format |= ESD_BITS8;
|
||||
break;
|
||||
case AUDIO_S16SYS:
|
||||
format |= ESD_BITS16;
|
||||
break;
|
||||
default:
|
||||
found = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
ESD_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->spec.channels == 1) {
|
||||
format |= ESD_MONO;
|
||||
} else {
|
||||
format |= ESD_STEREO;
|
||||
}
|
||||
#if 0
|
||||
this->spec.samples = ESD_BUF_SIZE; /* Darn, no way to change this yet */
|
||||
#endif
|
||||
|
||||
/* Open a connection to the ESD audio server */
|
||||
this->hidden->audio_fd =
|
||||
SDL_NAME(esd_play_stream) (format, this->spec.freq, NULL,
|
||||
get_progname());
|
||||
|
||||
if (this->hidden->audio_fd < 0) {
|
||||
ESD_CloseDevice(this);
|
||||
SDL_SetError("Couldn't open ESD connection");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
this->hidden->frame_ticks =
|
||||
(float) (this->spec.samples * 1000) / this->spec.freq;
|
||||
this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
ESD_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* Get the parent process id (we're the parent of the audio thread) */
|
||||
this->hidden->parent = getpid();
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ESD_Deinitialize(void)
|
||||
{
|
||||
UnloadESDLibrary();
|
||||
}
|
||||
|
||||
static int
|
||||
ESD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadESDLibrary() < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
int connection = 0;
|
||||
|
||||
/* Don't start ESD if it's not running */
|
||||
SDL_setenv("ESD_NO_SPAWN", "1", 0);
|
||||
|
||||
connection = SDL_NAME(esd_open_sound) (NULL);
|
||||
if (connection < 0) {
|
||||
UnloadESDLibrary();
|
||||
SDL_SetError("ESD: esd_open_sound failed (no audio server?)");
|
||||
return 0;
|
||||
}
|
||||
SDL_NAME(esd_close) (connection);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = ESD_OpenDevice;
|
||||
impl->PlayDevice = ESD_PlayDevice;
|
||||
impl->WaitDevice = ESD_WaitDevice;
|
||||
impl->GetDeviceBuf = ESD_GetDeviceBuf;
|
||||
impl->CloseDevice = ESD_CloseDevice;
|
||||
impl->Deinitialize = ESD_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap ESD_bootstrap = {
|
||||
ESD_DRIVER_NAME, "Enlightened Sound Daemon", ESD_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
50
thirdparty/SDL/src/audio/esd/SDL_esdaudio.h
vendored
Normal file
50
thirdparty/SDL/src/audio/esd/SDL_esdaudio.h
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_esdaudio_h
|
||||
#define _SDL_esdaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
/* The parent process id, to detect when application quits */
|
||||
pid_t parent;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
/* Support for audio timing using a timer */
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
#endif /* _SDL_esdaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
350
thirdparty/SDL/src/audio/fusionsound/SDL_fsaudio.c
vendored
Normal file
350
thirdparty/SDL/src/audio/fusionsound/SDL_fsaudio.c
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_fsaudio.h"
|
||||
|
||||
#include <fusionsound/fusionsound_version.h>
|
||||
|
||||
//#define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so"
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
|
||||
#include "SDL_name.h"
|
||||
#include "SDL_loadso.h"
|
||||
#else
|
||||
#define SDL_NAME(X) X
|
||||
#endif
|
||||
|
||||
#if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
|
||||
typedef DFBResult DirectResult;
|
||||
#endif
|
||||
|
||||
/* The tag name used by fusionsoundc audio */
|
||||
#define SDL_FS_DRIVER_NAME "fusionsound"
|
||||
/* Buffers to use - more than 2 gives a lot of latency */
|
||||
#define FUSION_BUFFERS (2)
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
|
||||
|
||||
static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
|
||||
static void *fs_handle = NULL;
|
||||
|
||||
static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
|
||||
static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
|
||||
ret_interface);
|
||||
|
||||
#define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
|
||||
static struct
|
||||
{
|
||||
const char *name;
|
||||
void **func;
|
||||
} fs_functions[] = {
|
||||
/* *INDENT-OFF* */
|
||||
SDL_FS_SYM(FusionSoundInit),
|
||||
SDL_FS_SYM(FusionSoundCreate),
|
||||
/* *INDENT-ON* */
|
||||
};
|
||||
|
||||
#undef SDL_FS_SYM
|
||||
|
||||
static void
|
||||
UnloadFusionSoundLibrary()
|
||||
{
|
||||
if (fs_handle != NULL) {
|
||||
SDL_UnloadObject(fs_handle);
|
||||
fs_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadFusionSoundLibrary(void)
|
||||
{
|
||||
int i, retval = -1;
|
||||
|
||||
if (fs_handle == NULL) {
|
||||
fs_handle = SDL_LoadObject(fs_library);
|
||||
if (fs_handle != NULL) {
|
||||
retval = 0;
|
||||
for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
|
||||
*fs_functions[i].func =
|
||||
SDL_LoadFunction(fs_handle, fs_functions[i].name);
|
||||
if (!*fs_functions[i].func) {
|
||||
retval = -1;
|
||||
UnloadFusionSoundLibrary();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
UnloadFusionSoundLibrary()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
LoadFusionSoundLibrary(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
SDL_FS_WaitDevice(_THIS)
|
||||
{
|
||||
this->hidden->stream->Wait(this->hidden->stream,
|
||||
this->hidden->mixsamples);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_FS_PlayDevice(_THIS)
|
||||
{
|
||||
DirectResult ret;
|
||||
|
||||
ret = this->hidden->stream->Write(this->hidden->stream,
|
||||
this->hidden->mixbuf,
|
||||
this->hidden->mixsamples);
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (ret) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_FS_WaitDone(_THIS)
|
||||
{
|
||||
this->hidden->stream->Wait(this->hidden->stream,
|
||||
this->hidden->mixsamples * FUSION_BUFFERS);
|
||||
}
|
||||
|
||||
|
||||
static Uint8 *
|
||||
SDL_FS_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SDL_FS_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->stream) {
|
||||
this->hidden->stream->Release(this->hidden->stream);
|
||||
this->hidden->stream = NULL;
|
||||
}
|
||||
if (this->hidden->fs) {
|
||||
this->hidden->fs->Release(this->hidden->fs);
|
||||
this->hidden->fs = NULL;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
int bytes;
|
||||
SDL_AudioFormat test_format = 0, format = 0;
|
||||
FSSampleFormat fs_format;
|
||||
FSStreamDescription desc;
|
||||
DirectResult ret;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
fs_format = FSSF_U8;
|
||||
bytes = 1;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S16SYS:
|
||||
fs_format = FSSF_S16;
|
||||
bytes = 2;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S32SYS:
|
||||
fs_format = FSSF_S32;
|
||||
bytes = 4;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_F32SYS:
|
||||
fs_format = FSSF_FLOAT;
|
||||
bytes = 4;
|
||||
format = 1;
|
||||
break;
|
||||
default:
|
||||
format = 0;
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
|
||||
if (format == 0) {
|
||||
SDL_FS_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Retrieve the main sound interface. */
|
||||
ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
|
||||
if (ret) {
|
||||
SDL_FS_CloseDevice(this);
|
||||
SDL_SetError("Unable to initialize FusionSound: %d", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
|
||||
|
||||
/* Fill stream description. */
|
||||
desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
|
||||
FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
|
||||
desc.samplerate = this->spec.freq;
|
||||
desc.buffersize = this->spec.size * FUSION_BUFFERS;
|
||||
desc.channels = this->spec.channels;
|
||||
desc.prebuffer = 10;
|
||||
desc.sampleformat = fs_format;
|
||||
|
||||
ret =
|
||||
this->hidden->fs->CreateStream(this->hidden->fs, &desc,
|
||||
&this->hidden->stream);
|
||||
if (ret) {
|
||||
SDL_FS_CloseDevice(this);
|
||||
SDL_SetError("Unable to create FusionSoundStream: %d", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See what we got */
|
||||
desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
|
||||
FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
|
||||
ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
|
||||
|
||||
this->spec.freq = desc.samplerate;
|
||||
this->spec.size =
|
||||
desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
|
||||
this->spec.channels = desc.channels;
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
SDL_FS_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SDL_FS_Deinitialize(void)
|
||||
{
|
||||
UnloadFusionSoundLibrary();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
SDL_FS_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadFusionSoundLibrary() < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
DirectResult ret;
|
||||
|
||||
ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
|
||||
if (ret) {
|
||||
UnloadFusionSoundLibrary();
|
||||
SDL_SetError
|
||||
("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
|
||||
ret);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = SDL_FS_OpenDevice;
|
||||
impl->PlayDevice = SDL_FS_PlayDevice;
|
||||
impl->WaitDevice = SDL_FS_WaitDevice;
|
||||
impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
|
||||
impl->CloseDevice = SDL_FS_CloseDevice;
|
||||
impl->WaitDone = SDL_FS_WaitDone;
|
||||
impl->Deinitialize = SDL_FS_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap FUSIONSOUND_bootstrap = {
|
||||
SDL_FS_DRIVER_NAME, "FusionSound", SDL_FS_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
49
thirdparty/SDL/src/audio/fusionsound/SDL_fsaudio.h
vendored
Normal file
49
thirdparty/SDL/src/audio/fusionsound/SDL_fsaudio.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_fsaudio_h
|
||||
#define _SDL_fsaudio_h
|
||||
|
||||
#include <fusionsound/fusionsound.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* Interface */
|
||||
IFusionSound *fs;
|
||||
|
||||
/* The stream interface for the audio device */
|
||||
IFusionSoundStream *stream;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
int mixsamples;
|
||||
|
||||
};
|
||||
|
||||
#endif /* _SDL_fsaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
339
thirdparty/SDL/src/audio/iphoneos/SDL_coreaudio_iphone.c
vendored
Normal file
339
thirdparty/SDL/src/audio/iphoneos/SDL_coreaudio_iphone.c
vendored
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_coreaudio_iphone.h"
|
||||
|
||||
#define DEBUG_COREAUDIO 0
|
||||
|
||||
static void
|
||||
COREAUDIO_Deinitialize(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* The CoreAudio callback */
|
||||
static OSStatus
|
||||
outputCallback(void *inRefCon,
|
||||
AudioUnitRenderActionFlags * ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList * ioDataList)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
|
||||
AudioBuffer *ioData = &ioDataList->mBuffers[0];
|
||||
UInt32 remaining, len;
|
||||
void *ptr;
|
||||
|
||||
/* Is there ever more than one buffer, and what do you do with it? */
|
||||
if (ioDataList->mNumberBuffers != 1) {
|
||||
return noErr;
|
||||
}
|
||||
|
||||
/* Only do anything if audio is enabled and not paused */
|
||||
if (!this->enabled || this->paused) {
|
||||
SDL_memset(ioData->mData, this->spec.silence, ioData->mDataByteSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No SDL conversion should be needed here, ever, since we accept
|
||||
any input format in OpenAudio, and leave the conversion to CoreAudio.
|
||||
*/
|
||||
/*
|
||||
assert(!this->convert.needed);
|
||||
assert(this->spec.channels == ioData->mNumberChannels);
|
||||
*/
|
||||
|
||||
remaining = ioData->mDataByteSize;
|
||||
ptr = ioData->mData;
|
||||
while (remaining > 0) {
|
||||
if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
|
||||
/* Generate the data */
|
||||
SDL_memset(this->hidden->buffer, this->spec.silence,
|
||||
this->hidden->bufferSize);
|
||||
SDL_mutexP(this->mixer_lock);
|
||||
(*this->spec.callback) (this->spec.userdata, this->hidden->buffer,
|
||||
this->hidden->bufferSize);
|
||||
SDL_mutexV(this->mixer_lock);
|
||||
this->hidden->bufferOffset = 0;
|
||||
}
|
||||
|
||||
len = this->hidden->bufferSize - this->hidden->bufferOffset;
|
||||
if (len > remaining)
|
||||
len = remaining;
|
||||
SDL_memcpy(ptr,
|
||||
(char *) this->hidden->buffer + this->hidden->bufferOffset,
|
||||
len);
|
||||
ptr = (char *) ptr + len;
|
||||
remaining -= len;
|
||||
this->hidden->bufferOffset += len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
inputCallback(void *inRefCon,
|
||||
AudioUnitRenderActionFlags * ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList * ioData)
|
||||
{
|
||||
//err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer);
|
||||
// !!! FIXME: write me!
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
COREAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->audioUnitOpened) {
|
||||
OSStatus result = noErr;
|
||||
AURenderCallbackStruct callback;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
const int iscapture = this->iscapture;
|
||||
const AudioUnitElement bus =
|
||||
((iscapture) ? input_bus : output_bus);
|
||||
const AudioUnitScope scope =
|
||||
((iscapture) ? kAudioUnitScope_Output :
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
/* stop processing the audio unit */
|
||||
result = AudioOutputUnitStop(this->hidden->audioUnit);
|
||||
|
||||
/* Remove the input callback */
|
||||
SDL_memset(&callback, '\0', sizeof(AURenderCallbackStruct));
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback,
|
||||
sizeof(callback));
|
||||
|
||||
//CloseComponent(this->hidden->audioUnit);
|
||||
this->hidden->audioUnitOpened = 0;
|
||||
}
|
||||
SDL_free(this->hidden->buffer);
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_RESULT(msg) \
|
||||
if (result != noErr) { \
|
||||
COREAUDIO_CloseDevice(this); \
|
||||
SDL_SetError("CoreAudio error (%s): %d", msg, result); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
static int
|
||||
prepare_audiounit(_THIS, const char *devname, int iscapture,
|
||||
const AudioStreamBasicDescription * strdesc)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
AURenderCallbackStruct callback;
|
||||
AudioComponentDescription desc;
|
||||
AudioComponent comp = NULL;
|
||||
|
||||
UInt32 enableIO = 0;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
|
||||
const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
SDL_memset(&desc, '\0', sizeof(AudioComponentDescription));
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_RemoteIO;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
||||
comp = AudioComponentFindNext(NULL, &desc);
|
||||
if (comp == NULL) {
|
||||
SDL_SetError("Couldn't find requested CoreAudio component");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open & initialize the audio unit */
|
||||
/*
|
||||
AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6
|
||||
We can't use OpenAComponent on iPhone because it is not present
|
||||
*/
|
||||
result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioComponentInstanceNew");
|
||||
|
||||
this->hidden->audioUnitOpened = 1;
|
||||
|
||||
// !!! FIXME: this is wrong?
|
||||
enableIO = ((iscapture) ? 1 : 0);
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioOutputUnitProperty_EnableIO,
|
||||
kAudioUnitScope_Input, input_bus,
|
||||
&enableIO, sizeof(enableIO));
|
||||
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO input)");
|
||||
|
||||
// !!! FIXME: this is wrong?
|
||||
enableIO = ((iscapture) ? 0 : 1);
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioOutputUnitProperty_EnableIO,
|
||||
kAudioUnitScope_Output, output_bus,
|
||||
&enableIO, sizeof(enableIO));
|
||||
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_EnableIO output)");
|
||||
|
||||
/*result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioOutputUnitProperty_CurrentDevice,
|
||||
kAudioUnitScope_Global, 0,
|
||||
&this->hidden->deviceID,
|
||||
sizeof(AudioDeviceID));
|
||||
|
||||
CHECK_RESULT("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)"); */
|
||||
|
||||
/* Set the data format of the audio unit. */
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
scope, bus, strdesc, sizeof(*strdesc));
|
||||
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
|
||||
|
||||
/* Set the audio callback */
|
||||
SDL_memset(&callback, '\0', sizeof(AURenderCallbackStruct));
|
||||
callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
|
||||
callback.inputProcRefCon = this;
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback, sizeof(callback));
|
||||
CHECK_RESULT
|
||||
("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate a sample buffer */
|
||||
this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
|
||||
this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
|
||||
|
||||
result = AudioUnitInitialize(this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioUnitInitialize");
|
||||
|
||||
/* Finally, start processing of the audio unit */
|
||||
result = AudioOutputUnitStart(this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioOutputUnitStart");
|
||||
/* We're running! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
AudioStreamBasicDescription strdesc;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int valid_datatype = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Setup a AudioStreamBasicDescription with the requested format */
|
||||
SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
|
||||
strdesc.mFormatID = kAudioFormatLinearPCM;
|
||||
strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
|
||||
strdesc.mChannelsPerFrame = this->spec.channels;
|
||||
strdesc.mSampleRate = this->spec.freq;
|
||||
strdesc.mFramesPerPacket = 1;
|
||||
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
this->spec.format = test_format;
|
||||
/* Just a list of valid SDL formats, so people don't pass junk here. */
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S8:
|
||||
case AUDIO_U16LSB:
|
||||
case AUDIO_S16LSB:
|
||||
case AUDIO_U16MSB:
|
||||
case AUDIO_S16MSB:
|
||||
case AUDIO_S32LSB:
|
||||
case AUDIO_S32MSB:
|
||||
case AUDIO_F32LSB:
|
||||
case AUDIO_F32MSB:
|
||||
valid_datatype = 1;
|
||||
strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
|
||||
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
|
||||
else if (SDL_AUDIO_ISSIGNED(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_datatype) { /* shouldn't happen, but just in case... */
|
||||
COREAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
strdesc.mBytesPerFrame =
|
||||
strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
|
||||
strdesc.mBytesPerPacket =
|
||||
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
|
||||
|
||||
if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
|
||||
COREAUDIO_CloseDevice(this);
|
||||
return 0; /* prepare_audiounit() will call SDL_SetError()... */
|
||||
}
|
||||
|
||||
return 1; /* good to go. */
|
||||
}
|
||||
|
||||
static int
|
||||
COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
|
||||
/* added for iPhone */
|
||||
impl->OnlyHasDefaultInputDevice = 1;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
impl->HasCaptureSupport = 0; /* still needs to be written */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap COREAUDIOIPHONE_bootstrap = {
|
||||
"coreaudio-iphoneos", "SDL CoreAudio (iPhone OS) audio driver",
|
||||
COREAUDIO_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
42
thirdparty/SDL/src/audio/iphoneos/SDL_coreaudio_iphone.h
vendored
Normal file
42
thirdparty/SDL/src/audio/iphoneos/SDL_coreaudio_iphone.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_coreaudio_h
|
||||
#define _SDL_coreaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
AudioUnit audioUnit;
|
||||
int audioUnitOpened;
|
||||
void *buffer;
|
||||
UInt32 bufferOffset;
|
||||
UInt32 bufferSize;
|
||||
// AudioDeviceID deviceID;
|
||||
};
|
||||
|
||||
#endif /* _SDL_coreaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
583
thirdparty/SDL/src/audio/macosx/SDL_coreaudio.c
vendored
Normal file
583
thirdparty/SDL/src/audio/macosx/SDL_coreaudio.c
vendored
Normal file
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <CoreAudio/CoreAudio.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5
|
||||
#include <AudioUnit/AUNTComponent.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include "SDL_coreaudio.h"
|
||||
|
||||
#define DEBUG_COREAUDIO 0
|
||||
|
||||
typedef struct COREAUDIO_DeviceList
|
||||
{
|
||||
AudioDeviceID id;
|
||||
const char *name;
|
||||
} COREAUDIO_DeviceList;
|
||||
|
||||
static COREAUDIO_DeviceList *inputDevices = NULL;
|
||||
static int inputDeviceCount = 0;
|
||||
static COREAUDIO_DeviceList *outputDevices = NULL;
|
||||
static int outputDeviceCount = 0;
|
||||
|
||||
static void
|
||||
free_device_list(COREAUDIO_DeviceList ** devices, int *devCount)
|
||||
{
|
||||
if (*devices) {
|
||||
int i = *devCount;
|
||||
while (i--)
|
||||
SDL_free((void *) (*devices)[i].name);
|
||||
SDL_free(*devices);
|
||||
*devices = NULL;
|
||||
}
|
||||
*devCount = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
build_device_list(int iscapture, COREAUDIO_DeviceList ** devices,
|
||||
int *devCount)
|
||||
{
|
||||
Boolean outWritable = 0;
|
||||
OSStatus result = noErr;
|
||||
UInt32 size = 0;
|
||||
AudioDeviceID *devs = NULL;
|
||||
UInt32 i = 0;
|
||||
UInt32 max = 0;
|
||||
|
||||
free_device_list(devices, devCount);
|
||||
|
||||
result = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
|
||||
&size, &outWritable);
|
||||
|
||||
if (result != kAudioHardwareNoError)
|
||||
return;
|
||||
|
||||
devs = (AudioDeviceID *) alloca(size);
|
||||
if (devs == NULL)
|
||||
return;
|
||||
|
||||
max = size / sizeof(AudioDeviceID);
|
||||
*devices = (COREAUDIO_DeviceList *) SDL_malloc(max * sizeof(**devices));
|
||||
if (*devices == NULL)
|
||||
return;
|
||||
|
||||
result = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
|
||||
&size, devs);
|
||||
if (result != kAudioHardwareNoError)
|
||||
return;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
CFStringRef cfstr = NULL;
|
||||
char *ptr = NULL;
|
||||
AudioDeviceID dev = devs[i];
|
||||
AudioBufferList *buflist = NULL;
|
||||
int usable = 0;
|
||||
CFIndex len = 0;
|
||||
|
||||
result = AudioDeviceGetPropertyInfo(dev, 0, iscapture,
|
||||
kAudioDevicePropertyStreamConfiguration,
|
||||
&size, &outWritable);
|
||||
if (result != noErr)
|
||||
continue;
|
||||
|
||||
buflist = (AudioBufferList *) SDL_malloc(size);
|
||||
if (buflist == NULL)
|
||||
continue;
|
||||
|
||||
result = AudioDeviceGetProperty(dev, 0, iscapture,
|
||||
kAudioDevicePropertyStreamConfiguration,
|
||||
&size, buflist);
|
||||
|
||||
if (result == noErr) {
|
||||
UInt32 j;
|
||||
for (j = 0; j < buflist->mNumberBuffers; j++) {
|
||||
if (buflist->mBuffers[j].mNumberChannels > 0) {
|
||||
usable = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(buflist);
|
||||
|
||||
if (!usable)
|
||||
continue;
|
||||
|
||||
size = sizeof(CFStringRef);
|
||||
result = AudioDeviceGetProperty(dev, 0, iscapture,
|
||||
kAudioDevicePropertyDeviceNameCFString,
|
||||
&size, &cfstr);
|
||||
|
||||
if (result != kAudioHardwareNoError)
|
||||
continue;
|
||||
|
||||
len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
|
||||
kCFStringEncodingUTF8);
|
||||
|
||||
ptr = (char *) SDL_malloc(len + 1);
|
||||
usable = ((ptr != NULL) &&
|
||||
(CFStringGetCString
|
||||
(cfstr, ptr, len + 1, kCFStringEncodingUTF8)));
|
||||
|
||||
CFRelease(cfstr);
|
||||
|
||||
if (usable) {
|
||||
len = strlen(ptr);
|
||||
/* Some devices have whitespace at the end...trim it. */
|
||||
while ((len > 0) && (ptr[len - 1] == ' ')) {
|
||||
len--;
|
||||
}
|
||||
usable = (len > 0);
|
||||
}
|
||||
|
||||
if (!usable) {
|
||||
SDL_free(ptr);
|
||||
} else {
|
||||
ptr[len] = '\0';
|
||||
|
||||
#if DEBUG_COREAUDIO
|
||||
printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
|
||||
((iscapture) ? "capture" : "output"),
|
||||
(int) *devCount, ptr, (int) dev);
|
||||
#endif
|
||||
|
||||
(*devices)[*devCount].id = dev;
|
||||
(*devices)[*devCount].name = ptr;
|
||||
(*devCount)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
build_device_lists(void)
|
||||
{
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
free_device_lists(void)
|
||||
{
|
||||
free_device_list(&outputDevices, &outputDeviceCount);
|
||||
free_device_list(&inputDevices, &inputDeviceCount);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
find_device_id(const char *devname, int iscapture, AudioDeviceID * id)
|
||||
{
|
||||
int i = ((iscapture) ? inputDeviceCount : outputDeviceCount);
|
||||
COREAUDIO_DeviceList *devs = ((iscapture) ? inputDevices : outputDevices);
|
||||
while (i--) {
|
||||
if (SDL_strcmp(devname, devs->name) == 0) {
|
||||
*id = devs->id;
|
||||
return 1;
|
||||
}
|
||||
devs++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
COREAUDIO_DetectDevices(int iscapture)
|
||||
{
|
||||
if (iscapture) {
|
||||
build_device_list(1, &inputDevices, &inputDeviceCount);
|
||||
return inputDeviceCount;
|
||||
} else {
|
||||
build_device_list(0, &outputDevices, &outputDeviceCount);
|
||||
return outputDeviceCount;
|
||||
}
|
||||
|
||||
return 0; /* shouldn't ever hit this. */
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
COREAUDIO_GetDeviceName(int index, int iscapture)
|
||||
{
|
||||
if ((iscapture) && (index < inputDeviceCount)) {
|
||||
return inputDevices[index].name;
|
||||
} else if ((!iscapture) && (index < outputDeviceCount)) {
|
||||
return outputDevices[index].name;
|
||||
}
|
||||
|
||||
SDL_SetError("No such device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
COREAUDIO_Deinitialize(void)
|
||||
{
|
||||
free_device_lists();
|
||||
}
|
||||
|
||||
|
||||
/* The CoreAudio callback */
|
||||
static OSStatus
|
||||
outputCallback(void *inRefCon,
|
||||
AudioUnitRenderActionFlags * ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList * ioData)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
|
||||
AudioBuffer *abuf;
|
||||
UInt32 remaining, len;
|
||||
void *ptr;
|
||||
UInt32 i;
|
||||
|
||||
/* Only do anything if audio is enabled and not paused */
|
||||
if (!this->enabled || this->paused) {
|
||||
for (i = 0; i < ioData->mNumberBuffers; i++) {
|
||||
abuf = &ioData->mBuffers[i];
|
||||
SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No SDL conversion should be needed here, ever, since we accept
|
||||
any input format in OpenAudio, and leave the conversion to CoreAudio.
|
||||
*/
|
||||
/*
|
||||
assert(!this->convert.needed);
|
||||
assert(this->spec.channels == ioData->mNumberChannels);
|
||||
*/
|
||||
|
||||
for (i = 0; i < ioData->mNumberBuffers; i++) {
|
||||
abuf = &ioData->mBuffers[i];
|
||||
remaining = abuf->mDataByteSize;
|
||||
ptr = abuf->mData;
|
||||
while (remaining > 0) {
|
||||
if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
|
||||
/* Generate the data */
|
||||
SDL_memset(this->hidden->buffer, this->spec.silence,
|
||||
this->hidden->bufferSize);
|
||||
SDL_mutexP(this->mixer_lock);
|
||||
(*this->spec.callback)(this->spec.userdata,
|
||||
this->hidden->buffer, this->hidden->bufferSize);
|
||||
SDL_mutexV(this->mixer_lock);
|
||||
this->hidden->bufferOffset = 0;
|
||||
}
|
||||
|
||||
len = this->hidden->bufferSize - this->hidden->bufferOffset;
|
||||
if (len > remaining)
|
||||
len = remaining;
|
||||
SDL_memcpy(ptr, (char *)this->hidden->buffer +
|
||||
this->hidden->bufferOffset, len);
|
||||
ptr = (char *)ptr + len;
|
||||
remaining -= len;
|
||||
this->hidden->bufferOffset += len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static OSStatus
|
||||
inputCallback(void *inRefCon,
|
||||
AudioUnitRenderActionFlags * ioActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, UInt32 inNumberFrames,
|
||||
AudioBufferList * ioData)
|
||||
{
|
||||
//err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer);
|
||||
// !!! FIXME: write me!
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
COREAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->audioUnitOpened) {
|
||||
OSStatus result = noErr;
|
||||
AURenderCallbackStruct callback;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
const int iscapture = this->iscapture;
|
||||
const AudioUnitElement bus =
|
||||
((iscapture) ? input_bus : output_bus);
|
||||
const AudioUnitScope scope =
|
||||
((iscapture) ? kAudioUnitScope_Output :
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
/* stop processing the audio unit */
|
||||
result = AudioOutputUnitStop(this->hidden->audioUnit);
|
||||
|
||||
/* Remove the input callback */
|
||||
SDL_memset(&callback, '\0', sizeof(AURenderCallbackStruct));
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback,
|
||||
sizeof(callback));
|
||||
|
||||
CloseComponent(this->hidden->audioUnit);
|
||||
this->hidden->audioUnitOpened = 0;
|
||||
}
|
||||
SDL_free(this->hidden->buffer);
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define CHECK_RESULT(msg) \
|
||||
if (result != noErr) { \
|
||||
COREAUDIO_CloseDevice(this); \
|
||||
SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
static int
|
||||
find_device_by_name(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
AudioDeviceID devid = 0;
|
||||
OSStatus result = noErr;
|
||||
UInt32 size = 0;
|
||||
UInt32 alive = 0;
|
||||
pid_t pid = 0;
|
||||
|
||||
if (devname == NULL) {
|
||||
size = sizeof(AudioDeviceID);
|
||||
const AudioHardwarePropertyID propid =
|
||||
((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
|
||||
kAudioHardwarePropertyDefaultOutputDevice);
|
||||
|
||||
result = AudioHardwareGetProperty(propid, &size, &devid);
|
||||
CHECK_RESULT("AudioHardwareGetProperty (default device)");
|
||||
} else {
|
||||
if (!find_device_id(devname, iscapture, &devid)) {
|
||||
SDL_SetError("CoreAudio: No such audio device.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size = sizeof(alive);
|
||||
result = AudioDeviceGetProperty(devid, 0, iscapture,
|
||||
kAudioDevicePropertyDeviceIsAlive,
|
||||
&size, &alive);
|
||||
CHECK_RESULT
|
||||
("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
|
||||
|
||||
if (!alive) {
|
||||
SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = sizeof(pid);
|
||||
result = AudioDeviceGetProperty(devid, 0, iscapture,
|
||||
kAudioDevicePropertyHogMode, &size, &pid);
|
||||
|
||||
/* some devices don't support this property, so errors are fine here. */
|
||||
if ((result == noErr) && (pid != -1)) {
|
||||
SDL_SetError("CoreAudio: requested device is being hogged.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->deviceID = devid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
prepare_audiounit(_THIS, const char *devname, int iscapture,
|
||||
const AudioStreamBasicDescription * strdesc)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
AURenderCallbackStruct callback;
|
||||
ComponentDescription desc;
|
||||
Component comp = NULL;
|
||||
const AudioUnitElement output_bus = 0;
|
||||
const AudioUnitElement input_bus = 1;
|
||||
const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
|
||||
const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
|
||||
kAudioUnitScope_Input);
|
||||
|
||||
if (!find_device_by_name(this, devname, iscapture)) {
|
||||
SDL_SetError("Couldn't find requested CoreAudio device");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_memset(&desc, '\0', sizeof(ComponentDescription));
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
|
||||
comp = FindNextComponent(NULL, &desc);
|
||||
if (comp == NULL) {
|
||||
SDL_SetError("Couldn't find requested CoreAudio component");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Open & initialize the audio unit */
|
||||
result = OpenAComponent(comp, &this->hidden->audioUnit);
|
||||
CHECK_RESULT("OpenAComponent");
|
||||
|
||||
this->hidden->audioUnitOpened = 1;
|
||||
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioOutputUnitProperty_CurrentDevice,
|
||||
kAudioUnitScope_Global, 0,
|
||||
&this->hidden->deviceID,
|
||||
sizeof(AudioDeviceID));
|
||||
CHECK_RESULT
|
||||
("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)");
|
||||
|
||||
/* Set the data format of the audio unit. */
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_StreamFormat,
|
||||
scope, bus, strdesc, sizeof(*strdesc));
|
||||
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
|
||||
|
||||
/* Set the audio callback */
|
||||
SDL_memset(&callback, '\0', sizeof(AURenderCallbackStruct));
|
||||
callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
|
||||
callback.inputProcRefCon = this;
|
||||
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
||||
kAudioUnitProperty_SetRenderCallback,
|
||||
scope, bus, &callback, sizeof(callback));
|
||||
CHECK_RESULT
|
||||
("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate a sample buffer */
|
||||
this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
|
||||
this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
|
||||
|
||||
result = AudioUnitInitialize(this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioUnitInitialize");
|
||||
|
||||
/* Finally, start processing of the audio unit */
|
||||
result = AudioOutputUnitStart(this->hidden->audioUnit);
|
||||
CHECK_RESULT("AudioOutputUnitStart");
|
||||
|
||||
/* We're running! */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
AudioStreamBasicDescription strdesc;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int valid_datatype = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (0);
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Setup a AudioStreamBasicDescription with the requested format */
|
||||
SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
|
||||
strdesc.mFormatID = kAudioFormatLinearPCM;
|
||||
strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
|
||||
strdesc.mChannelsPerFrame = this->spec.channels;
|
||||
strdesc.mSampleRate = this->spec.freq;
|
||||
strdesc.mFramesPerPacket = 1;
|
||||
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
this->spec.format = test_format;
|
||||
/* Just a list of valid SDL formats, so people don't pass junk here. */
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S8:
|
||||
case AUDIO_U16LSB:
|
||||
case AUDIO_S16LSB:
|
||||
case AUDIO_U16MSB:
|
||||
case AUDIO_S16MSB:
|
||||
case AUDIO_S32LSB:
|
||||
case AUDIO_S32MSB:
|
||||
case AUDIO_F32LSB:
|
||||
case AUDIO_F32MSB:
|
||||
valid_datatype = 1;
|
||||
strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
|
||||
|
||||
if (SDL_AUDIO_ISFLOAT(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
|
||||
else if (SDL_AUDIO_ISSIGNED(this->spec.format))
|
||||
strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_datatype) { /* shouldn't happen, but just in case... */
|
||||
COREAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
strdesc.mBytesPerFrame =
|
||||
strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
|
||||
strdesc.mBytesPerPacket =
|
||||
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
|
||||
|
||||
if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
|
||||
COREAUDIO_CloseDevice(this);
|
||||
return 0; /* prepare_audiounit() will call SDL_SetError()... */
|
||||
}
|
||||
|
||||
return 1; /* good to go. */
|
||||
}
|
||||
|
||||
static int
|
||||
COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = COREAUDIO_DetectDevices;
|
||||
impl->GetDeviceName = COREAUDIO_GetDeviceName;
|
||||
impl->OpenDevice = COREAUDIO_OpenDevice;
|
||||
impl->CloseDevice = COREAUDIO_CloseDevice;
|
||||
impl->Deinitialize = COREAUDIO_Deinitialize;
|
||||
impl->ProvidesOwnCallbackThread = 1;
|
||||
|
||||
build_device_lists(); /* do an initial check for devices... */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap COREAUDIO_bootstrap = {
|
||||
"coreaudio", "Mac OS X CoreAudio", COREAUDIO_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
42
thirdparty/SDL/src/audio/macosx/SDL_coreaudio.h
vendored
Normal file
42
thirdparty/SDL/src/audio/macosx/SDL_coreaudio.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_coreaudio_h
|
||||
#define _SDL_coreaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
AudioUnit audioUnit;
|
||||
int audioUnitOpened;
|
||||
void *buffer;
|
||||
UInt32 bufferOffset;
|
||||
UInt32 bufferSize;
|
||||
AudioDeviceID deviceID;
|
||||
};
|
||||
|
||||
#endif /* _SDL_coreaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
403
thirdparty/SDL/src/audio/nas/SDL_nasaudio.c
vendored
Normal file
403
thirdparty/SDL/src/audio/nas/SDL_nasaudio.c
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_nasaudio.h"
|
||||
|
||||
/* The tag name used by nas audio */
|
||||
#define NAS_DRIVER_NAME "nas"
|
||||
|
||||
static struct SDL_PrivateAudioData *this2 = NULL;
|
||||
|
||||
|
||||
static void (*NAS_AuCloseServer) (AuServer *);
|
||||
static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
|
||||
static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
|
||||
static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
|
||||
static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
|
||||
static void (*NAS_AuSetElements)
|
||||
(AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
|
||||
static void (*NAS_AuWriteElement)
|
||||
(AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
|
||||
static AuServer *(*NAS_AuOpenServer)
|
||||
(_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
|
||||
static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
|
||||
(AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
|
||||
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
|
||||
|
||||
static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
|
||||
static void *nas_handle = NULL;
|
||||
|
||||
static int
|
||||
load_nas_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(nas_handle, fn);
|
||||
if (*addr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
#define SDL_NAS_SYM(x) \
|
||||
if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
|
||||
#else
|
||||
#define SDL_NAS_SYM(x) NAS_##x = x
|
||||
#endif
|
||||
|
||||
static int
|
||||
load_nas_syms(void)
|
||||
{
|
||||
SDL_NAS_SYM(AuCloseServer);
|
||||
SDL_NAS_SYM(AuNextEvent);
|
||||
SDL_NAS_SYM(AuDispatchEvent);
|
||||
SDL_NAS_SYM(AuCreateFlow);
|
||||
SDL_NAS_SYM(AuStartFlow);
|
||||
SDL_NAS_SYM(AuSetElements);
|
||||
SDL_NAS_SYM(AuWriteElement);
|
||||
SDL_NAS_SYM(AuOpenServer);
|
||||
SDL_NAS_SYM(AuRegisterEventHandler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef SDL_NAS_SYM
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
|
||||
|
||||
static void
|
||||
UnloadNASLibrary(void)
|
||||
{
|
||||
if (nas_handle != NULL) {
|
||||
SDL_UnloadObject(nas_handle);
|
||||
nas_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadNASLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (nas_handle == NULL) {
|
||||
nas_handle = SDL_LoadObject(nas_library);
|
||||
if (nas_handle == NULL) {
|
||||
/* Copy error string so we can use it in a new SDL_SetError(). */
|
||||
char *origerr = SDL_GetError();
|
||||
size_t len = SDL_strlen(origerr) + 1;
|
||||
char *err = (char *) alloca(len);
|
||||
SDL_strlcpy(err, origerr, len);
|
||||
retval = -1;
|
||||
SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n",
|
||||
nas_library, err);
|
||||
} else {
|
||||
retval = load_nas_syms();
|
||||
if (retval < 0) {
|
||||
UnloadNASLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void
|
||||
UnloadNASLibrary(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
LoadNASLibrary(void)
|
||||
{
|
||||
load_nas_syms();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
NAS_WaitDevice(_THIS)
|
||||
{
|
||||
while (this->hidden->buf_free < this->hidden->mixlen) {
|
||||
AuEvent ev;
|
||||
NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
|
||||
NAS_AuDispatchEvent(this->hidden->aud, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NAS_PlayDevice(_THIS)
|
||||
{
|
||||
while (this->hidden->mixlen > this->hidden->buf_free) {
|
||||
/*
|
||||
* We think the buffer is full? Yikes! Ask the server for events,
|
||||
* in the hope that some of them is LowWater events telling us more
|
||||
* of the buffer is free now than what we think.
|
||||
*/
|
||||
AuEvent ev;
|
||||
NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
|
||||
NAS_AuDispatchEvent(this->hidden->aud, &ev);
|
||||
}
|
||||
this->hidden->buf_free -= this->hidden->mixlen;
|
||||
|
||||
/* Write the audio data */
|
||||
NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0,
|
||||
this->hidden->mixlen, this->hidden->mixbuf, AuFalse,
|
||||
NULL);
|
||||
|
||||
this->hidden->written += this->hidden->mixlen;
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
NAS_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
NAS_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->aud) {
|
||||
NAS_AuCloseServer(this->hidden->aud);
|
||||
this->hidden->aud = 0;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this2 = this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
sdlformat_to_auformat(unsigned int fmt)
|
||||
{
|
||||
switch (fmt) {
|
||||
case AUDIO_U8:
|
||||
return AuFormatLinearUnsigned8;
|
||||
case AUDIO_S8:
|
||||
return AuFormatLinearSigned8;
|
||||
case AUDIO_U16LSB:
|
||||
return AuFormatLinearUnsigned16LSB;
|
||||
case AUDIO_U16MSB:
|
||||
return AuFormatLinearUnsigned16MSB;
|
||||
case AUDIO_S16LSB:
|
||||
return AuFormatLinearSigned16LSB;
|
||||
case AUDIO_S16MSB:
|
||||
return AuFormatLinearSigned16MSB;
|
||||
}
|
||||
return AuNone;
|
||||
}
|
||||
|
||||
static AuBool
|
||||
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
|
||||
{
|
||||
switch (ev->type) {
|
||||
case AuEventTypeElementNotify:
|
||||
{
|
||||
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
|
||||
|
||||
switch (event->kind) {
|
||||
case AuElementNotifyKindLowWater:
|
||||
if (this2->buf_free >= 0) {
|
||||
this2->really += event->num_bytes;
|
||||
gettimeofday(&this2->last_tv, 0);
|
||||
this2->buf_free += event->num_bytes;
|
||||
} else {
|
||||
this2->buf_free = event->num_bytes;
|
||||
}
|
||||
break;
|
||||
case AuElementNotifyKindState:
|
||||
switch (event->cur_state) {
|
||||
case AuStatePause:
|
||||
if (event->reason != AuReasonUser) {
|
||||
if (this2->buf_free >= 0) {
|
||||
this2->really += event->num_bytes;
|
||||
gettimeofday(&this2->last_tv, 0);
|
||||
this2->buf_free += event->num_bytes;
|
||||
} else {
|
||||
this2->buf_free = event->num_bytes;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return AuTrue;
|
||||
}
|
||||
|
||||
static AuDeviceID
|
||||
find_device(_THIS, int nch)
|
||||
{
|
||||
/* These "Au" things are all macros, not functions... */
|
||||
int i;
|
||||
for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
|
||||
if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
|
||||
AuComponentKindPhysicalOutput) &&
|
||||
AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
|
||||
return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
|
||||
}
|
||||
}
|
||||
return AuNone;
|
||||
}
|
||||
|
||||
static int
|
||||
NAS_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
AuElement elms[3];
|
||||
int buffer_size;
|
||||
SDL_AudioFormat test_format, format;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
format = 0;
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
format = sdlformat_to_auformat(test_format);
|
||||
if (format == AuNone) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (format == 0) {
|
||||
NAS_CloseDevice(this);
|
||||
SDL_SetError("NAS: Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
|
||||
if (this->hidden->aud == 0) {
|
||||
NAS_CloseDevice(this);
|
||||
SDL_SetError("NAS: Couldn't open connection to NAS server");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->hidden->dev = find_device(this, this->spec.channels);
|
||||
if ((this->hidden->dev == AuNone)
|
||||
|| (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
|
||||
NAS_CloseDevice(this);
|
||||
SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer_size = this->spec.freq;
|
||||
if (buffer_size < 4096)
|
||||
buffer_size = 4096;
|
||||
|
||||
if (buffer_size > 32768)
|
||||
buffer_size = 32768; /* So that the buffer won't get unmanageably big. */
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
this2 = this->hidden;
|
||||
|
||||
AuMakeElementImportClient(elms, this->spec.freq, format,
|
||||
this->spec.channels, AuTrue, buffer_size,
|
||||
buffer_size / 4, 0, NULL);
|
||||
AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
|
||||
AuUnlimitedSamples, 0, NULL);
|
||||
NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
|
||||
NULL);
|
||||
NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
|
||||
this->hidden->flow, event_handler,
|
||||
(AuPointer) NULL);
|
||||
|
||||
NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
NAS_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
NAS_Deinitialize(void)
|
||||
{
|
||||
UnloadNASLibrary();
|
||||
}
|
||||
|
||||
static int
|
||||
NAS_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadNASLibrary() < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
|
||||
if (aud == NULL) {
|
||||
SDL_SetError("NAS: AuOpenServer() failed (no audio server?)");
|
||||
return 0;
|
||||
}
|
||||
NAS_AuCloseServer(aud);
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = NAS_OpenDevice;
|
||||
impl->PlayDevice = NAS_PlayDevice;
|
||||
impl->WaitDevice = NAS_WaitDevice;
|
||||
impl->GetDeviceBuf = NAS_GetDeviceBuf;
|
||||
impl->CloseDevice = NAS_CloseDevice;
|
||||
impl->Deinitialize = NAS_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap NAS_bootstrap = {
|
||||
NAS_DRIVER_NAME, "Network Audio System", NAS_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
56
thirdparty/SDL/src/audio/nas/SDL_nasaudio.h
vendored
Normal file
56
thirdparty/SDL/src/audio/nas/SDL_nasaudio.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_nasaudio_h
|
||||
#define _SDL_nasaudio_h
|
||||
|
||||
#ifdef __sgi
|
||||
#include <nas/audiolib.h>
|
||||
#else
|
||||
#include <audio/audiolib.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
AuServer *aud;
|
||||
AuFlowID flow;
|
||||
AuDeviceID dev;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
int written;
|
||||
int really;
|
||||
int bps;
|
||||
struct timeval last_tv;
|
||||
int buf_free;
|
||||
};
|
||||
#endif /* _SDL_nasaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
125
thirdparty/SDL/src/audio/nds/SDL_ndsaudio.c
vendored
Normal file
125
thirdparty/SDL/src/audio/nds/SDL_ndsaudio.c
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Output audio to NDS */
|
||||
|
||||
#include <nds.h>
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_ndsaudio.h"
|
||||
|
||||
static int
|
||||
NDSAUD_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int valid_datatype = 0;
|
||||
|
||||
this->hidden = SDL_malloc(sizeof(*(this->hidden)));
|
||||
if (!this->hidden) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
this->spec.format = test_format;
|
||||
switch (test_format) {
|
||||
case AUDIO_S8:
|
||||
/*case AUDIO_S16LSB: */
|
||||
valid_datatype = 1;
|
||||
break;
|
||||
default:
|
||||
test_format = SDL_NextAudioFormat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* set the generic sound parameters */
|
||||
setGenericSound(22050, /* sample rate */
|
||||
127, /* volume */
|
||||
64, /* panning/balance */
|
||||
0); /* sound format */
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
NDSAUD_PlayDevice(_THIS)
|
||||
{
|
||||
#if 0
|
||||
playGenericSound(this->hidden->mixbuf, this->hidden->mixlen);
|
||||
|
||||
// sound->data = this->hidden->mixbuf;/* pointer to raw audio data */
|
||||
// sound->len = this->hidden->mixlen; /* size of raw data pointed to above */
|
||||
// sound->rate = 22050; /* sample rate = 22050Hz */
|
||||
// sound->vol = 127; /* volume [0..127] for [min..max] */
|
||||
// sound->pan = 64; /* balance [0..127] for [left..right] */
|
||||
// sound->format = 0; /* 0 for 16-bit, 1 for 8-bit */
|
||||
// playSound(sound);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static Uint8 *
|
||||
NDSAUD_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->mixbuf; /* is this right? */
|
||||
}
|
||||
|
||||
static void
|
||||
NDSAUD_WaitDevice(_THIS)
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
static void
|
||||
NDSAUD_CloseDevice(_THIS)
|
||||
{
|
||||
/* stub */
|
||||
}
|
||||
|
||||
static int
|
||||
NDSAUD_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = NDSAUD_OpenDevice;
|
||||
impl->PlayDevice = NDSAUD_PlayDevice;
|
||||
impl->WaitDevice = NDSAUD_WaitDevice;
|
||||
impl->GetDeviceBuf = NDSAUD_GetDeviceBuf;
|
||||
impl->CloseDevice = NDSAUD_CloseDevice;
|
||||
|
||||
/* and the capabilities */
|
||||
impl->HasCaptureSupport = 1;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
impl->OnlyHasDefaultInputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap NDSAUD_bootstrap = {
|
||||
"nds", "SDL NDS audio driver", NDSAUD_Init, 0 /*1? */
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
42
thirdparty/SDL/src/audio/nds/SDL_ndsaudio.h
vendored
Normal file
42
thirdparty/SDL/src/audio/nds/SDL_ndsaudio.h
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_ndsaudio_h
|
||||
#define _SDL_ndsaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
#include <nds/arm9/sound.h>
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
Uint8 *mixbuf;
|
||||
Uint32 mixlen;
|
||||
Uint32 write_delay;
|
||||
Uint32 initial_calls;
|
||||
};
|
||||
|
||||
#endif /* _SDL_ndsaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
551
thirdparty/SDL/src/audio/paudio/SDL_paudio.c
vendored
Normal file
551
thirdparty/SDL/src/audio/paudio/SDL_paudio.c
vendored
Normal file
@@ -0,0 +1,551 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_paudio.h"
|
||||
|
||||
#define DEBUG_AUDIO 0
|
||||
|
||||
/* A conflict within AIX 4.3.3 <sys/> headers and probably others as well.
|
||||
* I guess nobody ever uses audio... Shame over AIX header files. */
|
||||
#include <sys/machine.h>
|
||||
#undef BIG_ENDIAN
|
||||
#include <sys/audio.h>
|
||||
|
||||
/* The tag name used by paud audio */
|
||||
#define PAUDIO_DRIVER_NAME "paud"
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
/* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */
|
||||
#define OPEN_FLAGS O_WRONLY
|
||||
|
||||
/* Get the name of the audio device we use for output */
|
||||
|
||||
#ifndef _PATH_DEV_DSP
|
||||
#define _PATH_DEV_DSP "/dev/%caud%c/%c"
|
||||
#endif
|
||||
|
||||
static char devsettings[][3] = {
|
||||
{'p', '0', '1'}, {'p', '0', '2'}, {'p', '0', '3'}, {'p', '0', '4'},
|
||||
{'p', '1', '1'}, {'p', '1', '2'}, {'p', '1', '3'}, {'p', '1', '4'},
|
||||
{'p', '2', '1'}, {'p', '2', '2'}, {'p', '2', '3'}, {'p', '2', '4'},
|
||||
{'p', '3', '1'}, {'p', '3', '2'}, {'p', '3', '3'}, {'p', '3', '4'},
|
||||
{'b', '0', '1'}, {'b', '0', '2'}, {'b', '0', '3'}, {'b', '0', '4'},
|
||||
{'b', '1', '1'}, {'b', '1', '2'}, {'b', '1', '3'}, {'b', '1', '4'},
|
||||
{'b', '2', '1'}, {'b', '2', '2'}, {'b', '2', '3'}, {'b', '2', '4'},
|
||||
{'b', '3', '1'}, {'b', '3', '2'}, {'b', '3', '3'}, {'b', '3', '4'},
|
||||
{'\0', '\0', '\0'}
|
||||
};
|
||||
|
||||
static int
|
||||
OpenUserDefinedDevice(char *path, int maxlen, int flags)
|
||||
{
|
||||
const char *audiodev;
|
||||
int fd;
|
||||
|
||||
/* Figure out what our audio device is */
|
||||
if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) {
|
||||
audiodev = SDL_getenv("AUDIODEV");
|
||||
}
|
||||
if (audiodev == NULL) {
|
||||
return -1;
|
||||
}
|
||||
fd = open(audiodev, flags, 0);
|
||||
if (path != NULL) {
|
||||
SDL_strlcpy(path, audiodev, maxlen);
|
||||
path[maxlen - 1] = '\0';
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
OpenAudioPath(char *path, int maxlen, int flags, int classic)
|
||||
{
|
||||
struct stat sb;
|
||||
int cycle = 0;
|
||||
int fd = OpenUserDefinedDevice(path, maxlen, flags);
|
||||
|
||||
if (fd != -1) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* !!! FIXME: do we really need a table here? */
|
||||
while (devsettings[cycle][0] != '\0') {
|
||||
char audiopath[1024];
|
||||
SDL_snprintf(audiopath, SDL_arraysize(audiopath),
|
||||
_PATH_DEV_DSP,
|
||||
devsettings[cycle][0],
|
||||
devsettings[cycle][1], devsettings[cycle][2]);
|
||||
|
||||
if (stat(audiopath, &sb) == 0) {
|
||||
fd = open(audiopath, flags, 0);
|
||||
if (fd > 0) {
|
||||
if (path != NULL) {
|
||||
SDL_strlcpy(path, audiopath, maxlen);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
PAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
fd_set fdset;
|
||||
|
||||
/* See if we need to use timed audio synchronization */
|
||||
if (this->hidden->frame_ticks) {
|
||||
/* Use timer for general audio synchronization */
|
||||
Sint32 ticks;
|
||||
|
||||
ticks =
|
||||
((Sint32) (this->hidden->next_frame - SDL_GetTicks())) -
|
||||
FUDGE_TICKS;
|
||||
if (ticks > 0) {
|
||||
SDL_Delay(ticks);
|
||||
}
|
||||
} else {
|
||||
audio_buffer paud_bufinfo;
|
||||
|
||||
/* Use select() for audio synchronization */
|
||||
struct timeval timeout;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(this->hidden->audio_fd, &fdset);
|
||||
|
||||
if (ioctl(this->hidden->audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Couldn't get audio buffer information\n");
|
||||
#endif
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
} else {
|
||||
long ms_in_buf = paud_bufinfo.write_buf_time;
|
||||
timeout.tv_sec = ms_in_buf / 1000;
|
||||
ms_in_buf = ms_in_buf - timeout.tv_sec * 1000;
|
||||
timeout.tv_usec = ms_in_buf * 1000;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr,
|
||||
"Waiting for write_buf_time=%ld,%ld\n",
|
||||
timeout.tv_sec, timeout.tv_usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Waiting for audio to get ready\n");
|
||||
#endif
|
||||
if (select(this->hidden->audio_fd + 1, NULL, &fdset, NULL, &timeout)
|
||||
<= 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 - %s\n", strerror(errno), message);
|
||||
this->enabled = 0;
|
||||
/* Don't try to close - may hang */
|
||||
this->hidden->audio_fd = -1;
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Done disabling audio\n");
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Ready!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
int written = 0;
|
||||
const Uint8 *mixbuf = this->hidden->mixbuf;
|
||||
const size_t mixlen = this->hidden->mixlen;
|
||||
|
||||
/* Write the audio data, checking for EAGAIN on broken audio drivers */
|
||||
do {
|
||||
written = write(this->hidden->audio_fd, mixbuf, mixlen);
|
||||
if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) {
|
||||
SDL_Delay(1); /* Let a little CPU time go by */
|
||||
}
|
||||
} while ((written < 0) &&
|
||||
((errno == 0) || (errno == EAGAIN) || (errno == EINTR)));
|
||||
|
||||
/* If timer synchronization is enabled, set the next write frame */
|
||||
if (this->hidden->frame_ticks) {
|
||||
this->hidden->next_frame += this->hidden->frame_ticks;
|
||||
}
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (written < 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
|
||||
#endif
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
PAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->mixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
PAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->audio_fd >= 0) {
|
||||
close(this->hidden->audio_fd);
|
||||
this->hidden->audio_fd = -1;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
|
||||
char audiodev[1024];
|
||||
const char *err = NULL;
|
||||
int format;
|
||||
int bytes_per_sample;
|
||||
SDL_AudioFormat test_format;
|
||||
audio_init paud_init;
|
||||
audio_buffer paud_bufinfo;
|
||||
audio_status paud_status;
|
||||
audio_control paud_control;
|
||||
audio_change paud_change;
|
||||
int fd = -1;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Open the audio device */
|
||||
fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
|
||||
this->hidden->audio_fd = fd;
|
||||
if (fd < 0) {
|
||||
PAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't set the buffer size - just ask the device for the maximum
|
||||
* that we can have.
|
||||
*/
|
||||
if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
|
||||
PAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Couldn't get audio buffer information");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->spec.channels > 1)
|
||||
this->spec.channels = 2;
|
||||
else
|
||||
this->spec.channels = 1;
|
||||
|
||||
/*
|
||||
* Fields in the audio_init structure:
|
||||
*
|
||||
* Ignored by us:
|
||||
*
|
||||
* paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only?
|
||||
* paud.slot_number; * slot number of the adapter
|
||||
* paud.device_id; * adapter identification number
|
||||
*
|
||||
* Input:
|
||||
*
|
||||
* paud.srate; * the sampling rate in Hz
|
||||
* paud.bits_per_sample; * 8, 16, 32, ...
|
||||
* paud.bsize; * block size for this rate
|
||||
* paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX
|
||||
* paud.channels; * 1=mono, 2=stereo
|
||||
* paud.flags; * FIXED - fixed length data
|
||||
* * LEFT_ALIGNED, RIGHT_ALIGNED (var len only)
|
||||
* * TWOS_COMPLEMENT - 2's complement data
|
||||
* * SIGNED - signed? comment seems wrong in sys/audio.h
|
||||
* * BIG_ENDIAN
|
||||
* paud.operation; * PLAY, RECORD
|
||||
*
|
||||
* Output:
|
||||
*
|
||||
* paud.flags; * PITCH - pitch is supported
|
||||
* * INPUT - input is supported
|
||||
* * OUTPUT - output is supported
|
||||
* * MONITOR - monitor is supported
|
||||
* * VOLUME - volume is supported
|
||||
* * VOLUME_DELAY - volume delay is supported
|
||||
* * BALANCE - balance is supported
|
||||
* * BALANCE_DELAY - balance delay is supported
|
||||
* * TREBLE - treble control is supported
|
||||
* * BASS - bass control is supported
|
||||
* * BESTFIT_PROVIDED - best fit returned
|
||||
* * LOAD_CODE - DSP load needed
|
||||
* paud.rc; * NO_PLAY - DSP code can't do play requests
|
||||
* * NO_RECORD - DSP code can't do record requests
|
||||
* * INVALID_REQUEST - request was invalid
|
||||
* * CONFLICT - conflict with open's flags
|
||||
* * OVERLOADED - out of DSP MIPS or memory
|
||||
* paud.position_resolution; * smallest increment for position
|
||||
*/
|
||||
|
||||
paud_init.srate = this->spec.freq;
|
||||
paud_init.mode = PCM;
|
||||
paud_init.operation = PLAY;
|
||||
paud_init.channels = this->spec.channels;
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
format = 0;
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
!format && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
bytes_per_sample = 1;
|
||||
paud_init.bits_per_sample = 8;
|
||||
paud_init.flags = TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
bytes_per_sample = 1;
|
||||
paud_init.bits_per_sample = 8;
|
||||
paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
bytes_per_sample = 2;
|
||||
paud_init.bits_per_sample = 16;
|
||||
paud_init.flags = SIGNED | TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
bytes_per_sample = 2;
|
||||
paud_init.bits_per_sample = 16;
|
||||
paud_init.flags = BIG_ENDIAN | SIGNED | TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
bytes_per_sample = 2;
|
||||
paud_init.bits_per_sample = 16;
|
||||
paud_init.flags = TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
bytes_per_sample = 2;
|
||||
paud_init.bits_per_sample = 16;
|
||||
paud_init.flags = BIG_ENDIAN | TWOS_COMPLEMENT | FIXED;
|
||||
format = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!format) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (format == 0) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Couldn't find any hardware audio formats\n");
|
||||
#endif
|
||||
PAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/*
|
||||
* We know the buffer size and the max number of subsequent writes
|
||||
* that can be pending. If more than one can pend, allow the application
|
||||
* to do something like double buffering between our write buffer and
|
||||
* the device's own buffer that we are filling with write() anyway.
|
||||
*
|
||||
* We calculate this->spec.samples like this because
|
||||
* SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap
|
||||
* (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return.
|
||||
*/
|
||||
if (paud_bufinfo.request_buf_cap == 1) {
|
||||
this->spec.samples = paud_bufinfo.write_buf_cap
|
||||
/ bytes_per_sample / this->spec.channels;
|
||||
} else {
|
||||
this->spec.samples = paud_bufinfo.write_buf_cap
|
||||
/ bytes_per_sample / this->spec.channels / 2;
|
||||
}
|
||||
paud_init.bsize = bytes_per_sample * this->spec.channels;
|
||||
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/*
|
||||
* The AIX paud device init can't modify the values of the audio_init
|
||||
* structure that we pass to it. So we don't need any recalculation
|
||||
* of this stuff and no reinit call as in linux dsp and dma code.
|
||||
*
|
||||
* /dev/paud supports all of the encoding formats, so we don't need
|
||||
* to do anything like reopening the device, either.
|
||||
*/
|
||||
if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) {
|
||||
switch (paud_init.rc) {
|
||||
case 1:
|
||||
err = "Couldn't set audio format: DSP can't do play requests";
|
||||
break;
|
||||
case 2:
|
||||
err = "Couldn't set audio format: DSP can't do record requests";
|
||||
break;
|
||||
case 4:
|
||||
err = "Couldn't set audio format: request was invalid";
|
||||
break;
|
||||
case 5:
|
||||
err = "Couldn't set audio format: conflict with open's flags";
|
||||
break;
|
||||
case 6:
|
||||
err = "Couldn't set audio format: out of DSP MIPS or memory";
|
||||
break;
|
||||
default:
|
||||
err = "Couldn't set audio format: not documented in sys/audio.h";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != NULL) {
|
||||
PAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Paudio: %s", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
PAUDIO_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
/*
|
||||
* Set some paramters: full volume, first speaker that we can find.
|
||||
* Ignore the other settings for now.
|
||||
*/
|
||||
paud_change.input = AUDIO_IGNORE; /* the new input source */
|
||||
paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */
|
||||
paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */
|
||||
paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */
|
||||
paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */
|
||||
paud_change.balance = 0x3fffffff; /* the new balance */
|
||||
paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */
|
||||
paud_change.treble = AUDIO_IGNORE; /* the new treble state */
|
||||
paud_change.bass = AUDIO_IGNORE; /* the new bass state */
|
||||
paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */
|
||||
|
||||
paud_control.ioctl_request = AUDIO_CHANGE;
|
||||
paud_control.request_info = (char *) &paud_change;
|
||||
if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Can't change audio display settings\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell the device to expect data. Actual start will wait for
|
||||
* the first write() call.
|
||||
*/
|
||||
paud_control.ioctl_request = AUDIO_START;
|
||||
paud_control.position = 0;
|
||||
if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
|
||||
PAUDIO_CloseDevice(this);
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Can't start audio play\n");
|
||||
#endif
|
||||
SDL_SetError("Can't start audio play");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check to see if we need to use select() workaround */
|
||||
if (workaround != NULL) {
|
||||
this->hidden->frame_ticks = (float) (this->spec.samples * 1000) /
|
||||
this->spec.freq;
|
||||
this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks;
|
||||
}
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
PAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* !!! FIXME: not right for device enum? */
|
||||
int fd = OpenAudioPath(NULL, 0, OPEN_FLAGS, 0);
|
||||
if (fd < 0) {
|
||||
SDL_SetError("PAUDIO: Couldn't open audio device");
|
||||
return 0;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = DSP_OpenDevice;
|
||||
impl->PlayDevice = DSP_PlayDevice;
|
||||
impl->PlayDevice = DSP_WaitDevice;
|
||||
impl->GetDeviceBuf = DSP_GetDeviceBuf;
|
||||
impl->CloseDevice = DSP_CloseDevice;
|
||||
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap PAUDIO_bootstrap = {
|
||||
PAUDIO_DRIVER_NAME, "AIX Paudio", PAUDIO_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
47
thirdparty/SDL/src/audio/paudio/SDL_paudio.h
vendored
Normal file
47
thirdparty/SDL/src/audio/paudio/SDL_paudio.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_paudaudio_h
|
||||
#define _SDL_paudaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
|
||||
/* Support for audio timing using a timer, in addition to select() */
|
||||
float frame_ticks;
|
||||
float next_frame;
|
||||
};
|
||||
#define FUDGE_TICKS 10 /* The scheduler overhead ticks per frame */
|
||||
|
||||
#endif /* _SDL_paudaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
510
thirdparty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c
vendored
Normal file
510
thirdparty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c
vendored
Normal file
@@ -0,0 +1,510 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/*
|
||||
The PulseAudio target for SDL 1.3 is based on the 1.3 arts target, with
|
||||
the appropriate parts replaced with the 1.2 PulseAudio target code. This
|
||||
was the cleanest way to move it to 1.3. The 1.2 target was written by
|
||||
Stéphan Kochen: stephan .a.t. kochen.nl
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if SDL_AUDIO_DRIVER_PULSEAUDIO
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <pulse/pulseaudio.h>
|
||||
#include <pulse/simple.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_pulseaudio.h"
|
||||
#include "SDL_loadso.h"
|
||||
|
||||
/* The tag name used by pulse audio */
|
||||
#define PULSEAUDIO_DRIVER_NAME "pulseaudio"
|
||||
|
||||
#if (PA_API_VERSION < 12)
|
||||
/** Return non-zero if the passed state is one of the connected states */
|
||||
static inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
|
||||
return
|
||||
x == PA_CONTEXT_CONNECTING ||
|
||||
x == PA_CONTEXT_AUTHORIZING ||
|
||||
x == PA_CONTEXT_SETTING_NAME ||
|
||||
x == PA_CONTEXT_READY;
|
||||
}
|
||||
/** Return non-zero if the passed state is one of the connected states */
|
||||
static inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
|
||||
return
|
||||
x == PA_STREAM_CREATING ||
|
||||
x == PA_STREAM_READY;
|
||||
}
|
||||
#endif /* pulseaudio <= 0.9.10 */
|
||||
|
||||
|
||||
static pa_simple *(*PULSEAUDIO_pa_simple_new) (const char *, const char *,
|
||||
pa_stream_direction_t, const char *, const char *, const pa_sample_spec *,
|
||||
const pa_channel_map *, const pa_buffer_attr *, int *);
|
||||
static void (*PULSEAUDIO_pa_simple_free) (pa_simple *);
|
||||
static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto) (
|
||||
pa_channel_map *, unsigned, pa_channel_map_def_t);
|
||||
static const char * (*PULSEAUDIO_pa_strerror) (int);
|
||||
static pa_mainloop * (*PULSEAUDIO_pa_mainloop_new) (void);
|
||||
static pa_mainloop_api * (*PULSEAUDIO_pa_mainloop_get_api) (pa_mainloop *);
|
||||
static int (*PULSEAUDIO_pa_mainloop_iterate) (pa_mainloop *, int, int *);
|
||||
static void (*PULSEAUDIO_pa_mainloop_free) (pa_mainloop *);
|
||||
|
||||
static pa_operation_state_t (*PULSEAUDIO_pa_operation_get_state) (
|
||||
pa_operation *);
|
||||
static void (*PULSEAUDIO_pa_operation_cancel) (pa_operation *);
|
||||
static void (*PULSEAUDIO_pa_operation_unref) (pa_operation *);
|
||||
|
||||
static pa_context * (*PULSEAUDIO_pa_context_new) (pa_mainloop_api *,
|
||||
const char *);
|
||||
static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *,
|
||||
pa_context_flags_t, const pa_spawn_api *);
|
||||
static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *);
|
||||
static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *);
|
||||
static void (*PULSEAUDIO_pa_context_unref) (pa_context *);
|
||||
|
||||
static pa_stream * (*PULSEAUDIO_pa_stream_new) (pa_context *, const char *,
|
||||
const pa_sample_spec *, const pa_channel_map *);
|
||||
static int (*PULSEAUDIO_pa_stream_connect_playback) (pa_stream *, const char *,
|
||||
const pa_buffer_attr *, pa_stream_flags_t, pa_cvolume *, pa_stream *);
|
||||
static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state) (pa_stream *);
|
||||
static size_t (*PULSEAUDIO_pa_stream_writable_size) (pa_stream *);
|
||||
static int (*PULSEAUDIO_pa_stream_write) (pa_stream *, const void *, size_t,
|
||||
pa_free_cb_t, int64_t, pa_seek_mode_t);
|
||||
static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
|
||||
pa_stream_success_cb_t, void *);
|
||||
static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
|
||||
static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
|
||||
|
||||
static int load_pulseaudio_syms(void);
|
||||
|
||||
|
||||
#ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC
|
||||
|
||||
static const char *pulseaudio_library = SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC;
|
||||
static void *pulseaudio_handle = NULL;
|
||||
|
||||
static int
|
||||
load_pulseaudio_sym(const char *fn, void **addr)
|
||||
{
|
||||
*addr = SDL_LoadFunction(pulseaudio_handle, fn);
|
||||
if (*addr == NULL) {
|
||||
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
|
||||
#define SDL_PULSEAUDIO_SYM(x) \
|
||||
if (!load_pulseaudio_sym(#x, (void **) (char *) &PULSEAUDIO_##x)) return -1
|
||||
|
||||
static void
|
||||
UnloadPulseAudioLibrary(void)
|
||||
{
|
||||
if (pulseaudio_handle != NULL) {
|
||||
SDL_UnloadObject(pulseaudio_handle);
|
||||
pulseaudio_handle = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
LoadPulseAudioLibrary(void)
|
||||
{
|
||||
int retval = 0;
|
||||
if (pulseaudio_handle == NULL) {
|
||||
pulseaudio_handle = SDL_LoadObject(pulseaudio_library);
|
||||
if (pulseaudio_handle == NULL) {
|
||||
retval = -1;
|
||||
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
|
||||
} else {
|
||||
retval = load_pulseaudio_syms();
|
||||
if (retval < 0) {
|
||||
UnloadPulseAudioLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define SDL_PULSEAUDIO_SYM(x) PULSEAUDIO_##x = x
|
||||
|
||||
static void
|
||||
UnloadPulseAudioLibrary(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int
|
||||
LoadPulseAudioLibrary(void)
|
||||
{
|
||||
load_pulseaudio_syms();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC */
|
||||
|
||||
|
||||
static int
|
||||
load_pulseaudio_syms(void)
|
||||
{
|
||||
SDL_PULSEAUDIO_SYM(pa_simple_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_simple_free);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_get_api);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_iterate);
|
||||
SDL_PULSEAUDIO_SYM(pa_mainloop_free);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_cancel);
|
||||
SDL_PULSEAUDIO_SYM(pa_operation_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_connect);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_disconnect);
|
||||
SDL_PULSEAUDIO_SYM(pa_context_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_new);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_connect_playback);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_get_state);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_write);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_drain);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
|
||||
SDL_PULSEAUDIO_SYM(pa_stream_unref);
|
||||
SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
|
||||
SDL_PULSEAUDIO_SYM(pa_strerror);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
PULSEAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
|
||||
while(1) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
this->enabled = 0;
|
||||
return;
|
||||
}
|
||||
if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_PlayDevice(_THIS)
|
||||
{
|
||||
/* Write the audio data */
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL,
|
||||
PA_SEEK_RELATIVE) < 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stream_drain_complete(pa_stream *s, int success, void *userdata)
|
||||
{
|
||||
/* no-op for pa_stream_drain() to use for callback. */
|
||||
}
|
||||
|
||||
static void
|
||||
PULSEAUDIO_WaitDone(_THIS)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = this->hidden;
|
||||
pa_operation *o;
|
||||
|
||||
o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
|
||||
if (!o) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
|
||||
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
|
||||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
|
||||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_pa_operation_cancel(o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PULSEAUDIO_pa_operation_unref(o);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Uint8 *
|
||||
PULSEAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
PULSEAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
if (this->hidden->stream) {
|
||||
PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
|
||||
PULSEAUDIO_pa_stream_unref(this->hidden->stream);
|
||||
this->hidden->stream = NULL;
|
||||
}
|
||||
if (this->hidden->context != NULL) {
|
||||
PULSEAUDIO_pa_context_disconnect(this->hidden->context);
|
||||
PULSEAUDIO_pa_context_unref(this->hidden->context);
|
||||
this->hidden->context = NULL;
|
||||
}
|
||||
if (this->hidden->mainloop != NULL) {
|
||||
PULSEAUDIO_pa_mainloop_free(this->hidden->mainloop);
|
||||
this->hidden->mainloop = NULL;
|
||||
}
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
struct SDL_PrivateAudioData *h = NULL;
|
||||
Uint16 test_format = 0;
|
||||
pa_sample_spec paspec;
|
||||
pa_buffer_attr paattr;
|
||||
pa_channel_map pacmap;
|
||||
pa_stream_flags_t flags = 0;
|
||||
int state = 0;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
h = this->hidden;
|
||||
|
||||
paspec.format = PA_SAMPLE_INVALID;
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
(paspec.format == PA_SAMPLE_INVALID) && test_format;) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
paspec.format = PA_SAMPLE_U8;
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
paspec.format = PA_SAMPLE_S16LE;
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
paspec.format = PA_SAMPLE_S16BE;
|
||||
break;
|
||||
default:
|
||||
paspec.format = PA_SAMPLE_INVALID;
|
||||
break;
|
||||
}
|
||||
if (paspec.format == PA_SAMPLE_INVALID) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
if (paspec.format == PA_SAMPLE_INVALID) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
#ifdef PA_STREAM_ADJUST_LATENCY
|
||||
this->spec.samples /= 2; /* Mix in smaller chunck to avoid underruns */
|
||||
#endif
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
h->mixlen = this->spec.size;
|
||||
h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen);
|
||||
if (h->mixbuf == NULL) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
|
||||
|
||||
paspec.channels = this->spec.channels;
|
||||
paspec.rate = this->spec.freq;
|
||||
|
||||
/* Reduced prebuffering compared to the defaults. */
|
||||
#ifdef PA_STREAM_ADJUST_LATENCY
|
||||
/* 2x original requested bufsize */
|
||||
paattr.tlength = h->mixlen * 4;
|
||||
paattr.prebuf = -1;
|
||||
paattr.maxlength = -1;
|
||||
/* -1 can lead to pa_stream_writable_size() >= mixlen never being true */
|
||||
paattr.minreq = h->mixlen;
|
||||
flags = PA_STREAM_ADJUST_LATENCY;
|
||||
#else
|
||||
paattr.tlength = h->mixlen*2;
|
||||
paattr.prebuf = h->mixlen*2;
|
||||
paattr.maxlength = h->mixlen*2;
|
||||
paattr.minreq = h->mixlen;
|
||||
#endif
|
||||
|
||||
/* The SDL ALSA output hints us that we use Windows' channel mapping */
|
||||
/* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */
|
||||
PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels,
|
||||
PA_CHANNEL_MAP_WAVEEX);
|
||||
|
||||
/* Set up a new main loop */
|
||||
if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("pa_mainloop_new() failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
|
||||
h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, NULL);
|
||||
if (!h->context) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("pa_context_new() failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Connect to the PulseAudio server */
|
||||
if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Could not setup connection to PulseAudio");
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("pa_mainloop_iterate() failed");
|
||||
return 0;
|
||||
}
|
||||
state = PULSEAUDIO_pa_context_get_state(h->context);
|
||||
if (!PA_CONTEXT_IS_GOOD(state)) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Could not connect to PulseAudio");
|
||||
return 0;
|
||||
}
|
||||
} while (state != PA_CONTEXT_READY);
|
||||
|
||||
h->stream = PULSEAUDIO_pa_stream_new(
|
||||
h->context,
|
||||
"Simple DirectMedia Layer", /* stream description */
|
||||
&paspec, /* sample format spec */
|
||||
&pacmap /* channel map */
|
||||
);
|
||||
|
||||
if (h->stream == NULL) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Could not set up PulseAudio stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags,
|
||||
NULL, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Could not connect PulseAudio stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("pa_mainloop_iterate() failed");
|
||||
return 0;
|
||||
}
|
||||
state = PULSEAUDIO_pa_stream_get_state(h->stream);
|
||||
if (!PA_STREAM_IS_GOOD(state)) {
|
||||
PULSEAUDIO_CloseDevice(this);
|
||||
SDL_SetError("Could not create to PulseAudio stream");
|
||||
return 0;
|
||||
}
|
||||
} while (state != PA_STREAM_READY);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
PULSEAUDIO_Deinitialize(void)
|
||||
{
|
||||
UnloadPulseAudioLibrary();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
if (LoadPulseAudioLibrary() < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = PULSEAUDIO_OpenDevice;
|
||||
impl->PlayDevice = PULSEAUDIO_PlayDevice;
|
||||
impl->WaitDevice = PULSEAUDIO_WaitDevice;
|
||||
impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf;
|
||||
impl->CloseDevice = PULSEAUDIO_CloseDevice;
|
||||
impl->WaitDone = PULSEAUDIO_WaitDone;
|
||||
impl->Deinitialize = PULSEAUDIO_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap PULSEAUDIO_bootstrap = {
|
||||
PULSEAUDIO_DRIVER_NAME, "PulseAudio", PULSEAUDIO_Init, 0
|
||||
};
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_PULSEAUDIO */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
48
thirdparty/SDL/src/audio/pulseaudio/SDL_pulseaudio.h
vendored
Normal file
48
thirdparty/SDL/src/audio/pulseaudio/SDL_pulseaudio.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_pulseaudio_h
|
||||
#define _SDL_pulseaudio_h
|
||||
|
||||
#include <pulse/simple.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* pulseaudio structures */
|
||||
pa_mainloop *mainloop;
|
||||
pa_mainloop_api *mainloop_api;
|
||||
pa_context *context;
|
||||
pa_stream *stream;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *mixbuf;
|
||||
int mixlen;
|
||||
};
|
||||
|
||||
#endif /* _SDL_pulseaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
892
thirdparty/SDL/src/audio/qsa/SDL_qsa_audio.c
vendored
Normal file
892
thirdparty/SDL/src/audio/qsa/SDL_qsa_audio.c
vendored
Normal file
@@ -0,0 +1,892 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sched.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/neutrino.h>
|
||||
#include <sys/asoundlib.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_qsa_audio.h"
|
||||
|
||||
/* The tag name used by QSA audio framework */
|
||||
#define DRIVER_NAME "qsa"
|
||||
|
||||
/* default channel communication parameters */
|
||||
#define DEFAULT_CPARAMS_RATE 44100
|
||||
#define DEFAULT_CPARAMS_VOICES 1
|
||||
|
||||
#define DEFAULT_CPARAMS_FRAG_SIZE 4096
|
||||
#define DEFAULT_CPARAMS_FRAGS_MIN 1
|
||||
#define DEFAULT_CPARAMS_FRAGS_MAX 1
|
||||
|
||||
#define QSA_NO_WORKAROUNDS 0x00000000
|
||||
#define QSA_MMAP_WORKAROUND 0x00000001
|
||||
|
||||
struct BuggyCards
|
||||
{
|
||||
char *cardname;
|
||||
unsigned long bugtype;
|
||||
};
|
||||
|
||||
#define QSA_WA_CARDS 3
|
||||
#define QSA_MAX_CARD_NAME_LENGTH 33
|
||||
|
||||
struct BuggyCards buggycards[QSA_WA_CARDS] = {
|
||||
{"Sound Blaster Live!", QSA_MMAP_WORKAROUND},
|
||||
{"Vortex 8820", QSA_MMAP_WORKAROUND},
|
||||
{"Vortex 8830", QSA_MMAP_WORKAROUND},
|
||||
};
|
||||
|
||||
/* List of found devices */
|
||||
#define QSA_MAX_DEVICES 32
|
||||
#define QSA_MAX_NAME_LENGTH 81+16 /* Hardcoded in QSA, can't be changed */
|
||||
|
||||
typedef struct _QSA_Device
|
||||
{
|
||||
char name[QSA_MAX_NAME_LENGTH]; /* Long audio device name for SDL */
|
||||
int cardno;
|
||||
int deviceno;
|
||||
} QSA_Device;
|
||||
|
||||
QSA_Device qsa_playback_device[QSA_MAX_DEVICES];
|
||||
uint32_t qsa_playback_devices;
|
||||
|
||||
QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
|
||||
uint32_t qsa_capture_devices;
|
||||
|
||||
static inline void
|
||||
QSA_SetError(const char *fn, int status)
|
||||
{
|
||||
SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status));
|
||||
}
|
||||
|
||||
/* card names check to apply the workarounds */
|
||||
static int
|
||||
QSA_CheckBuggyCards(_THIS, unsigned long checkfor)
|
||||
{
|
||||
char scardname[QSA_MAX_CARD_NAME_LENGTH];
|
||||
int it;
|
||||
|
||||
if (snd_card_get_name
|
||||
(this->hidden->cardno, scardname, QSA_MAX_CARD_NAME_LENGTH - 1) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (it = 0; it < QSA_WA_CARDS; it++) {
|
||||
if (SDL_strcmp(buggycards[it].cardname, scardname) == 0) {
|
||||
if (buggycards[it].bugtype == checkfor) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
QSA_ThreadInit(_THIS)
|
||||
{
|
||||
struct sched_param param;
|
||||
int status;
|
||||
|
||||
/* Increase default 10 priority to 25 to avoid jerky sound */
|
||||
status = SchedGet(0, 0, ¶m);
|
||||
param.sched_priority = param.sched_curpriority + 15;
|
||||
status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m);
|
||||
}
|
||||
|
||||
/* PCM channel parameters initialize function */
|
||||
static void
|
||||
QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
|
||||
{
|
||||
SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t));
|
||||
|
||||
cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
cpars->mode = SND_PCM_MODE_BLOCK;
|
||||
cpars->start_mode = SND_PCM_START_DATA;
|
||||
cpars->stop_mode = SND_PCM_STOP_STOP;
|
||||
cpars->format.format = SND_PCM_SFMT_S16_LE;
|
||||
cpars->format.interleave = 1;
|
||||
cpars->format.rate = DEFAULT_CPARAMS_RATE;
|
||||
cpars->format.voices = DEFAULT_CPARAMS_VOICES;
|
||||
cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE;
|
||||
cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
|
||||
cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
|
||||
}
|
||||
|
||||
/* This function waits until it is possible to write a full sound buffer */
|
||||
static void
|
||||
QSA_WaitDevice(_THIS)
|
||||
{
|
||||
fd_set wfds;
|
||||
fd_set rfds;
|
||||
int selectret;
|
||||
struct timeval timeout;
|
||||
|
||||
if (!this->hidden->iscapture) {
|
||||
FD_ZERO(&wfds);
|
||||
FD_SET(this->hidden->audio_fd, &wfds);
|
||||
} else {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(this->hidden->audio_fd, &rfds);
|
||||
}
|
||||
|
||||
do {
|
||||
/* Setup timeout for playing one fragment equal to 2 seconds */
|
||||
/* If timeout occured than something wrong with hardware or driver */
|
||||
/* For example, Vortex 8820 audio driver stucks on second DAC because */
|
||||
/* it doesn't exist ! */
|
||||
timeout.tv_sec = 2;
|
||||
timeout.tv_usec = 0;
|
||||
this->hidden->timeout_on_wait = 0;
|
||||
|
||||
if (!this->hidden->iscapture) {
|
||||
selectret =
|
||||
select(this->hidden->audio_fd + 1, NULL, &wfds, NULL,
|
||||
&timeout);
|
||||
} else {
|
||||
selectret =
|
||||
select(this->hidden->audio_fd + 1, &rfds, NULL, NULL,
|
||||
&timeout);
|
||||
}
|
||||
|
||||
switch (selectret) {
|
||||
case -1:
|
||||
{
|
||||
SDL_SetError("QSA: select() failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
{
|
||||
SDL_SetError("QSA: timeout on buffer waiting occured\n");
|
||||
this->hidden->timeout_on_wait = 1;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (!this->hidden->iscapture) {
|
||||
if (FD_ISSET(this->hidden->audio_fd, &wfds)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (FD_ISSET(this->hidden->audio_fd, &rfds)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static void
|
||||
QSA_PlayDevice(_THIS)
|
||||
{
|
||||
snd_pcm_channel_status_t cstatus;
|
||||
int written;
|
||||
int status;
|
||||
int towrite;
|
||||
void *pcmbuffer;
|
||||
|
||||
if ((!this->enabled) || (!this->hidden)) {
|
||||
return;
|
||||
}
|
||||
|
||||
towrite = this->spec.size;
|
||||
pcmbuffer = this->hidden->pcm_buf;
|
||||
|
||||
/* Write the audio data, checking for EAGAIN (buffer full) and underrun */
|
||||
do {
|
||||
written =
|
||||
snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer,
|
||||
towrite);
|
||||
if (written != towrite) {
|
||||
/* Check if samples playback got stuck somewhere in hardware or in */
|
||||
/* the audio device driver */
|
||||
if ((errno == EAGAIN) && (written == 0)) {
|
||||
if (this->hidden->timeout_on_wait != 0) {
|
||||
SDL_SetError("QSA: buffer playback timeout\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for errors or conditions */
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
/* Let a little CPU time go by and try to write again */
|
||||
SDL_Delay(1);
|
||||
|
||||
/* if we wrote some data */
|
||||
towrite -= written;
|
||||
pcmbuffer += written * this->spec.channels;
|
||||
continue;
|
||||
} else {
|
||||
if ((errno == EINVAL) || (errno == EIO)) {
|
||||
SDL_memset(&cstatus, 0, sizeof(cstatus));
|
||||
if (!this->hidden->iscapture) {
|
||||
cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
} else {
|
||||
cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||
}
|
||||
|
||||
status =
|
||||
snd_pcm_plugin_status(this->hidden->audio_handle,
|
||||
&cstatus);
|
||||
if (status < 0) {
|
||||
QSA_SetError("snd_pcm_plugin_status", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
|
||||
(cstatus.status == SND_PCM_STATUS_READY)) {
|
||||
if (!this->hidden->iscapture) {
|
||||
status =
|
||||
snd_pcm_plugin_prepare(this->hidden->
|
||||
audio_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
} else {
|
||||
status =
|
||||
snd_pcm_plugin_prepare(this->hidden->
|
||||
audio_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
}
|
||||
if (status < 0) {
|
||||
QSA_SetError("snd_pcm_plugin_prepare", status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* we wrote all remaining data */
|
||||
towrite -= written;
|
||||
pcmbuffer += written * this->spec.channels;
|
||||
}
|
||||
} while ((towrite > 0) && (this->enabled));
|
||||
|
||||
/* If we couldn't write, assume fatal error for now */
|
||||
if (towrite != 0) {
|
||||
this->enabled = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
QSA_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return this->hidden->pcm_buf;
|
||||
}
|
||||
|
||||
static void
|
||||
QSA_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->audio_handle != NULL) {
|
||||
if (!this->hidden->iscapture) {
|
||||
/* Finish playing available samples */
|
||||
snd_pcm_plugin_flush(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
} else {
|
||||
/* Cancel unread samples during capture */
|
||||
snd_pcm_plugin_flush(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
}
|
||||
snd_pcm_close(this->hidden->audio_handle);
|
||||
this->hidden->audio_handle = NULL;
|
||||
}
|
||||
|
||||
if (this->hidden->pcm_buf != NULL) {
|
||||
SDL_FreeAudioMem(this->hidden->pcm_buf);
|
||||
this->hidden->pcm_buf = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
int status = 0;
|
||||
int format = 0;
|
||||
SDL_AudioFormat test_format = 0;
|
||||
int found = 0;
|
||||
snd_pcm_channel_setup_t csetup;
|
||||
snd_pcm_channel_params_t cparams;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden =
|
||||
(struct SDL_PrivateAudioData *) SDL_calloc(1,
|
||||
(sizeof
|
||||
(struct
|
||||
SDL_PrivateAudioData)));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));
|
||||
|
||||
/* Initialize channel transfer parameters to default */
|
||||
QSA_InitAudioParams(&cparams);
|
||||
|
||||
/* Initialize channel direction: capture or playback */
|
||||
this->hidden->iscapture = iscapture;
|
||||
|
||||
/* Find deviceid and cardid by device name for playback */
|
||||
if ((!this->hidden->iscapture) && (devname != NULL)) {
|
||||
uint32_t device;
|
||||
int32_t status;
|
||||
|
||||
/* Search in the playback devices */
|
||||
device = 0;
|
||||
do {
|
||||
status = SDL_strcmp(qsa_playback_device[device].name, devname);
|
||||
if (status == 0) {
|
||||
/* Found requested device */
|
||||
this->hidden->deviceno = qsa_playback_device[device].deviceno;
|
||||
this->hidden->cardno = qsa_playback_device[device].cardno;
|
||||
break;
|
||||
}
|
||||
device++;
|
||||
if (device >= qsa_playback_devices) {
|
||||
QSA_CloseDevice(this);
|
||||
SDL_SetError("No such playback device");
|
||||
return 0;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* Find deviceid and cardid by device name for capture */
|
||||
if ((this->hidden->iscapture) && (devname != NULL)) {
|
||||
/* Search in the capture devices */
|
||||
uint32_t device;
|
||||
int32_t status;
|
||||
|
||||
/* Searching in the playback devices */
|
||||
device = 0;
|
||||
do {
|
||||
status = SDL_strcmp(qsa_capture_device[device].name, devname);
|
||||
if (status == 0) {
|
||||
/* Found requested device */
|
||||
this->hidden->deviceno = qsa_capture_device[device].deviceno;
|
||||
this->hidden->cardno = qsa_capture_device[device].cardno;
|
||||
break;
|
||||
}
|
||||
device++;
|
||||
if (device >= qsa_capture_devices) {
|
||||
QSA_CloseDevice(this);
|
||||
SDL_SetError("No such capture device");
|
||||
return 0;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/* Check if SDL requested default audio device */
|
||||
if (devname == NULL) {
|
||||
/* Open system default audio device */
|
||||
if (!this->hidden->iscapture) {
|
||||
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
|
||||
&this->hidden->cardno,
|
||||
&this->hidden->deviceno,
|
||||
SND_PCM_OPEN_PLAYBACK);
|
||||
} else {
|
||||
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
|
||||
&this->hidden->cardno,
|
||||
&this->hidden->deviceno,
|
||||
SND_PCM_OPEN_CAPTURE);
|
||||
}
|
||||
} else {
|
||||
/* Open requested audio device */
|
||||
if (!this->hidden->iscapture) {
|
||||
status =
|
||||
snd_pcm_open(&this->hidden->audio_handle,
|
||||
this->hidden->cardno, this->hidden->deviceno,
|
||||
SND_PCM_OPEN_PLAYBACK);
|
||||
} else {
|
||||
status =
|
||||
snd_pcm_open(&this->hidden->audio_handle,
|
||||
this->hidden->cardno, this->hidden->deviceno,
|
||||
SND_PCM_OPEN_CAPTURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if requested device is opened */
|
||||
if (status < 0) {
|
||||
this->hidden->audio_handle = NULL;
|
||||
QSA_CloseDevice(this);
|
||||
QSA_SetError("snd_pcm_open", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
|
||||
/* Disable QSA MMAP plugin for buggy audio drivers */
|
||||
status =
|
||||
snd_pcm_plugin_set_disable(this->hidden->audio_handle,
|
||||
PLUGIN_DISABLE_MMAP);
|
||||
if (status < 0) {
|
||||
QSA_CloseDevice(this);
|
||||
QSA_SetError("snd_pcm_plugin_set_disable", status);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try for a closest match on audio format */
|
||||
format = 0;
|
||||
/* can't use format as SND_PCM_SFMT_U8 = 0 in qsa */
|
||||
found = 0;
|
||||
|
||||
for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) {
|
||||
/* if match found set format to equivalent QSA format */
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
{
|
||||
format = SND_PCM_SFMT_U8;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
{
|
||||
format = SND_PCM_SFMT_S8;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_S16_LE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_S16_BE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_U16_LE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_U16_BE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S32LSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_S32_LE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_S32MSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_S32_BE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_F32LSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_FLOAT_LE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
case AUDIO_F32MSB:
|
||||
{
|
||||
format = SND_PCM_SFMT_FLOAT_BE;
|
||||
found = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
}
|
||||
|
||||
/* assumes test_format not 0 on success */
|
||||
if (test_format == 0) {
|
||||
QSA_CloseDevice(this);
|
||||
SDL_SetError("QSA: Couldn't find any hardware audio formats");
|
||||
return 0;
|
||||
}
|
||||
|
||||
this->spec.format = test_format;
|
||||
|
||||
/* Set the audio format */
|
||||
cparams.format.format = format;
|
||||
|
||||
/* Set mono/stereo/4ch/6ch/8ch audio */
|
||||
cparams.format.voices = this->spec.channels;
|
||||
|
||||
/* Set rate */
|
||||
cparams.format.rate = this->spec.freq;
|
||||
|
||||
/* Setup the transfer parameters according to cparams */
|
||||
status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
|
||||
if (status < 0) {
|
||||
QSA_CloseDevice(this);
|
||||
QSA_SetError("snd_pcm_channel_params", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure channel is setup right one last time */
|
||||
SDL_memset(&csetup, '\0', sizeof(csetup));
|
||||
if (!this->hidden->iscapture) {
|
||||
csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
} else {
|
||||
csetup.channel = SND_PCM_CHANNEL_CAPTURE;
|
||||
}
|
||||
|
||||
/* Setup an audio channel */
|
||||
if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
|
||||
QSA_CloseDevice(this);
|
||||
SDL_SetError("QSA: Unable to setup channel\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the final parameters for this audio specification */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
this->hidden->pcm_len = this->spec.size;
|
||||
|
||||
if (this->hidden->pcm_len == 0) {
|
||||
this->hidden->pcm_len =
|
||||
csetup.buf.block.frag_size * this->spec.channels *
|
||||
(snd_pcm_format_width(format) / 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory to the audio buffer and initialize with silence
|
||||
* (Note that buffer size must be a multiple of fragment size, so find
|
||||
* closest multiple)
|
||||
*/
|
||||
this->hidden->pcm_buf =
|
||||
(Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
|
||||
if (this->hidden->pcm_buf == NULL) {
|
||||
QSA_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden->pcm_buf, this->spec.silence,
|
||||
this->hidden->pcm_len);
|
||||
|
||||
/* get the file descriptor */
|
||||
if (!this->hidden->iscapture) {
|
||||
this->hidden->audio_fd =
|
||||
snd_pcm_file_descriptor(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
} else {
|
||||
this->hidden->audio_fd =
|
||||
snd_pcm_file_descriptor(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
}
|
||||
|
||||
if (this->hidden->audio_fd < 0) {
|
||||
QSA_CloseDevice(this);
|
||||
QSA_SetError("snd_pcm_file_descriptor", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prepare an audio channel */
|
||||
if (!this->hidden->iscapture) {
|
||||
/* Prepare audio playback */
|
||||
status =
|
||||
snd_pcm_plugin_prepare(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
} else {
|
||||
/* Prepare audio capture */
|
||||
status =
|
||||
snd_pcm_plugin_prepare(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
}
|
||||
|
||||
if (status < 0) {
|
||||
QSA_CloseDevice(this);
|
||||
QSA_SetError("snd_pcm_plugin_prepare", status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're really ready to rock and roll. :-) */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
QSA_DetectDevices(int iscapture)
|
||||
{
|
||||
uint32_t it;
|
||||
uint32_t cards;
|
||||
uint32_t devices;
|
||||
int32_t status;
|
||||
|
||||
/* Detect amount of available devices */
|
||||
/* this value can be changed in the runtime */
|
||||
cards = snd_cards();
|
||||
|
||||
/* If io-audio manager is not running we will get 0 as number */
|
||||
/* of available audio devices */
|
||||
if (cards == 0) {
|
||||
/* We have no any available audio devices */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find requested devices by type */
|
||||
if (!iscapture) {
|
||||
/* Playback devices enumeration requested */
|
||||
for (it = 0; it < cards; it++) {
|
||||
devices = 0;
|
||||
do {
|
||||
status =
|
||||
snd_card_get_longname(it,
|
||||
qsa_playback_device
|
||||
[qsa_playback_devices].name,
|
||||
QSA_MAX_NAME_LENGTH);
|
||||
if (status == EOK) {
|
||||
snd_pcm_t *handle;
|
||||
|
||||
/* Add device number to device name */
|
||||
sprintf(qsa_playback_device[qsa_playback_devices].name +
|
||||
SDL_strlen(qsa_playback_device
|
||||
[qsa_playback_devices].name), " d%d",
|
||||
devices);
|
||||
|
||||
/* Store associated card number id */
|
||||
qsa_playback_device[qsa_playback_devices].cardno = it;
|
||||
|
||||
/* Check if this device id could play anything */
|
||||
status =
|
||||
snd_pcm_open(&handle, it, devices,
|
||||
SND_PCM_OPEN_PLAYBACK);
|
||||
if (status == EOK) {
|
||||
qsa_playback_device[qsa_playback_devices].deviceno =
|
||||
devices;
|
||||
status = snd_pcm_close(handle);
|
||||
if (status == EOK) {
|
||||
qsa_playback_devices++;
|
||||
}
|
||||
} else {
|
||||
/* Check if we got end of devices list */
|
||||
if (status == -ENOENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if we reached maximum devices count */
|
||||
if (qsa_playback_devices >= QSA_MAX_DEVICES) {
|
||||
break;
|
||||
}
|
||||
devices++;
|
||||
} while (1);
|
||||
|
||||
/* Check if we reached maximum devices count */
|
||||
if (qsa_playback_devices >= QSA_MAX_DEVICES) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Capture devices enumeration requested */
|
||||
for (it = 0; it < cards; it++) {
|
||||
devices = 0;
|
||||
do {
|
||||
status =
|
||||
snd_card_get_longname(it,
|
||||
qsa_capture_device
|
||||
[qsa_capture_devices].name,
|
||||
QSA_MAX_NAME_LENGTH);
|
||||
if (status == EOK) {
|
||||
snd_pcm_t *handle;
|
||||
|
||||
/* Add device number to device name */
|
||||
sprintf(qsa_capture_device[qsa_capture_devices].name +
|
||||
SDL_strlen(qsa_capture_device
|
||||
[qsa_capture_devices].name), " d%d",
|
||||
devices);
|
||||
|
||||
/* Store associated card number id */
|
||||
qsa_capture_device[qsa_capture_devices].cardno = it;
|
||||
|
||||
/* Check if this device id could play anything */
|
||||
status =
|
||||
snd_pcm_open(&handle, it, devices,
|
||||
SND_PCM_OPEN_CAPTURE);
|
||||
if (status == EOK) {
|
||||
qsa_capture_device[qsa_capture_devices].deviceno =
|
||||
devices;
|
||||
status = snd_pcm_close(handle);
|
||||
if (status == EOK) {
|
||||
qsa_capture_devices++;
|
||||
}
|
||||
} else {
|
||||
/* Check if we got end of devices list */
|
||||
if (status == -ENOENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we reached maximum devices count */
|
||||
if (qsa_capture_devices >= QSA_MAX_DEVICES) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
devices++;
|
||||
} while (1);
|
||||
|
||||
/* Check if we reached maximum devices count */
|
||||
if (qsa_capture_devices >= QSA_MAX_DEVICES) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return amount of available playback or capture devices */
|
||||
if (!iscapture) {
|
||||
return qsa_playback_devices;
|
||||
} else {
|
||||
return qsa_capture_devices;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
QSA_GetDeviceName(int index, int iscapture)
|
||||
{
|
||||
if (!iscapture) {
|
||||
if (index >= qsa_playback_devices) {
|
||||
return "No such playback device";
|
||||
}
|
||||
|
||||
return qsa_playback_device[index].name;
|
||||
} else {
|
||||
if (index >= qsa_capture_devices) {
|
||||
return "No such capture device";
|
||||
}
|
||||
|
||||
return qsa_capture_device[index].name;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QSA_WaitDone(_THIS)
|
||||
{
|
||||
if (!this->hidden->iscapture) {
|
||||
if (this->hidden->audio_handle != NULL) {
|
||||
/* Wait till last fragment is played and stop channel */
|
||||
snd_pcm_plugin_flush(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_PLAYBACK);
|
||||
}
|
||||
} else {
|
||||
if (this->hidden->audio_handle != NULL) {
|
||||
/* Discard all unread data and stop channel */
|
||||
snd_pcm_plugin_flush(this->hidden->audio_handle,
|
||||
SND_PCM_CHANNEL_CAPTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QSA_Deinitialize(void)
|
||||
{
|
||||
/* Clear devices array on shutdown */
|
||||
SDL_memset(qsa_playback_device, 0x00,
|
||||
sizeof(QSA_Device) * QSA_MAX_DEVICES);
|
||||
SDL_memset(qsa_capture_device, 0x00,
|
||||
sizeof(QSA_Device) * QSA_MAX_DEVICES);
|
||||
qsa_playback_devices = 0;
|
||||
qsa_capture_devices = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
QSA_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
snd_pcm_t *handle = NULL;
|
||||
int32_t status = 0;
|
||||
|
||||
/* Clear devices array */
|
||||
SDL_memset(qsa_playback_device, 0x00,
|
||||
sizeof(QSA_Device) * QSA_MAX_DEVICES);
|
||||
SDL_memset(qsa_capture_device, 0x00,
|
||||
sizeof(QSA_Device) * QSA_MAX_DEVICES);
|
||||
qsa_playback_devices = 0;
|
||||
qsa_capture_devices = 0;
|
||||
|
||||
/* Set function pointers */
|
||||
/* DeviceLock and DeviceUnlock functions are used default, */
|
||||
/* provided by SDL, which uses pthread_mutex for lock/unlock */
|
||||
impl->DetectDevices = QSA_DetectDevices;
|
||||
impl->GetDeviceName = QSA_GetDeviceName;
|
||||
impl->OpenDevice = QSA_OpenDevice;
|
||||
impl->ThreadInit = QSA_ThreadInit;
|
||||
impl->WaitDevice = QSA_WaitDevice;
|
||||
impl->PlayDevice = QSA_PlayDevice;
|
||||
impl->GetDeviceBuf = QSA_GetDeviceBuf;
|
||||
impl->CloseDevice = QSA_CloseDevice;
|
||||
impl->WaitDone = QSA_WaitDone;
|
||||
impl->Deinitialize = QSA_Deinitialize;
|
||||
impl->LockDevice = NULL;
|
||||
impl->UnlockDevice = NULL;
|
||||
|
||||
impl->OnlyHasDefaultOutputDevice = 0;
|
||||
impl->ProvidesOwnCallbackThread = 0;
|
||||
impl->SkipMixerLock = 0;
|
||||
impl->HasCaptureSupport = 1;
|
||||
impl->OnlyHasDefaultOutputDevice = 0;
|
||||
impl->OnlyHasDefaultInputDevice = 0;
|
||||
|
||||
/* Check if io-audio manager is running or not */
|
||||
status = snd_cards();
|
||||
if (status == 0) {
|
||||
/* if no, return immediately */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap QSAAUDIO_bootstrap = {
|
||||
DRIVER_NAME, "QNX QSA Audio", QSA_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
57
thirdparty/SDL/src/audio/qsa/SDL_qsa_audio.h
vendored
Normal file
57
thirdparty/SDL/src/audio/qsa/SDL_qsa_audio.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef __SDL_QSA_AUDIO_H__
|
||||
#define __SDL_QSA_AUDIO_H__
|
||||
|
||||
#include <sys/asoundlib.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice* this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* SDL capture state */
|
||||
int iscapture;
|
||||
|
||||
/* The audio device handle */
|
||||
int cardno;
|
||||
int deviceno;
|
||||
snd_pcm_t *audio_handle;
|
||||
|
||||
/* The audio file descriptor */
|
||||
int audio_fd;
|
||||
|
||||
/* Select timeout status */
|
||||
uint32_t timeout_on_wait;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
Uint8 *pcm_buf;
|
||||
Uint32 pcm_len;
|
||||
};
|
||||
|
||||
#endif /* __SDL_QSA_AUDIO_H__ */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
761
thirdparty/SDL/src/audio/sdlgenaudiocvt.pl
vendored
Executable file
761
thirdparty/SDL/src/audio/sdlgenaudiocvt.pl
vendored
Executable file
@@ -0,0 +1,761 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
my @audiotypes = qw(
|
||||
U8
|
||||
S8
|
||||
U16LSB
|
||||
S16LSB
|
||||
U16MSB
|
||||
S16MSB
|
||||
S32LSB
|
||||
S32MSB
|
||||
F32LSB
|
||||
F32MSB
|
||||
);
|
||||
|
||||
my @channels = ( 1, 2, 4, 6, 8 );
|
||||
my %funcs;
|
||||
my $custom_converters = 0;
|
||||
|
||||
|
||||
sub getTypeConvertHashId {
|
||||
my ($from, $to) = @_;
|
||||
return "TYPECONVERTER $from/$to";
|
||||
}
|
||||
|
||||
|
||||
sub getResamplerHashId {
|
||||
my ($from, $channels, $upsample, $multiple) = @_;
|
||||
return "RESAMPLER $from/$channels/$upsample/$multiple";
|
||||
}
|
||||
|
||||
|
||||
sub outputHeader {
|
||||
print <<EOF;
|
||||
/* DO NOT EDIT! This file is generated by sdlgenaudiocvt.pl */
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "SDL_audio_c.h"
|
||||
|
||||
#ifndef DEBUG_CONVERT
|
||||
#define DEBUG_CONVERT 0
|
||||
#endif
|
||||
|
||||
|
||||
/* If you can guarantee your data and need space, you can eliminate code... */
|
||||
|
||||
/* Just build the arbitrary resamplers if you're saving code space. */
|
||||
#ifndef LESS_RESAMPLERS
|
||||
#define LESS_RESAMPLERS 0
|
||||
#endif
|
||||
|
||||
/* Don't build any resamplers if you're REALLY saving code space. */
|
||||
#ifndef NO_RESAMPLERS
|
||||
#define NO_RESAMPLERS 0
|
||||
#endif
|
||||
|
||||
/* Don't build any type converters if you're saving code space. */
|
||||
#ifndef NO_CONVERTERS
|
||||
#define NO_CONVERTERS 0
|
||||
#endif
|
||||
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
||||
EOF
|
||||
|
||||
my @vals = ( 127, 32767, 2147483647 );
|
||||
foreach (@vals) {
|
||||
my $val = $_;
|
||||
my $fval = 1.0 / $val;
|
||||
print("#define DIVBY${val} ${fval}f\n");
|
||||
}
|
||||
|
||||
print("\n");
|
||||
}
|
||||
|
||||
sub outputFooter {
|
||||
print <<EOF;
|
||||
/* $custom_converters converters generated. */
|
||||
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
EOF
|
||||
}
|
||||
|
||||
sub splittype {
|
||||
my $t = shift;
|
||||
my ($signed, $size, $endian) = $t =~ /([USF])(\d+)([LM]SB|)/;
|
||||
my $float = ($signed eq 'F') ? 1 : 0;
|
||||
$signed = (($float) or ($signed eq 'S')) ? 1 : 0;
|
||||
$endian = 'NONE' if ($endian eq '');
|
||||
|
||||
my $ctype = '';
|
||||
if ($float) {
|
||||
$ctype = (($size == 32) ? 'float' : 'double');
|
||||
} else {
|
||||
$ctype = (($signed) ? 'S' : 'U') . "int${size}";
|
||||
}
|
||||
|
||||
return ($signed, $float, $size, $endian, $ctype);
|
||||
}
|
||||
|
||||
sub getSwapFunc {
|
||||
my ($size, $signed, $float, $endian, $val) = @_;
|
||||
my $BEorLE = (($endian eq 'MSB') ? 'BE' : 'LE');
|
||||
my $code = '';
|
||||
|
||||
if ($float) {
|
||||
$code = "SDL_SwapFloat${BEorLE}($val)";
|
||||
} else {
|
||||
if ($size > 8) {
|
||||
$code = "SDL_Swap${BEorLE}${size}($val)";
|
||||
} else {
|
||||
$code = $val;
|
||||
}
|
||||
|
||||
if (($signed) and (!$float)) {
|
||||
$code = "((Sint${size}) $code)";
|
||||
}
|
||||
}
|
||||
|
||||
return "${code}";
|
||||
}
|
||||
|
||||
|
||||
sub maxIntVal {
|
||||
my $size = shift;
|
||||
if ($size == 8) {
|
||||
return 0x7F;
|
||||
} elsif ($size == 16) {
|
||||
return 0x7FFF;
|
||||
} elsif ($size == 32) {
|
||||
return 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
die("bug in script.\n");
|
||||
}
|
||||
|
||||
sub getFloatToIntMult {
|
||||
my $size = shift;
|
||||
my $val = maxIntVal($size) . '.0';
|
||||
$val .= 'f' if ($size < 32);
|
||||
return $val;
|
||||
}
|
||||
|
||||
sub getIntToFloatDivBy {
|
||||
my $size = shift;
|
||||
return 'DIVBY' . maxIntVal($size);
|
||||
}
|
||||
|
||||
sub getSignFlipVal {
|
||||
my $size = shift;
|
||||
if ($size == 8) {
|
||||
return '0x80';
|
||||
} elsif ($size == 16) {
|
||||
return '0x8000';
|
||||
} elsif ($size == 32) {
|
||||
return '0x80000000';
|
||||
}
|
||||
|
||||
die("bug in script.\n");
|
||||
}
|
||||
|
||||
sub buildCvtFunc {
|
||||
my ($from, $to) = @_;
|
||||
my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
|
||||
my ($tsigned, $tfloat, $tsize, $tendian, $tctype) = splittype($to);
|
||||
my $diffs = 0;
|
||||
$diffs++ if ($fsize != $tsize);
|
||||
$diffs++ if ($fsigned != $tsigned);
|
||||
$diffs++ if ($ffloat != $tfloat);
|
||||
$diffs++ if ($fendian ne $tendian);
|
||||
|
||||
return if ($diffs == 0);
|
||||
|
||||
my $hashid = getTypeConvertHashId($from, $to);
|
||||
if (1) { # !!! FIXME: if ($diffs > 1) {
|
||||
my $sym = "SDL_Convert_${from}_to_${to}";
|
||||
$funcs{$hashid} = $sym;
|
||||
$custom_converters++;
|
||||
|
||||
# Always unsigned for ints, for possible byteswaps.
|
||||
my $srctype = (($ffloat) ? 'float' : "Uint${fsize}");
|
||||
|
||||
print <<EOF;
|
||||
static void SDLCALL
|
||||
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
{
|
||||
int i;
|
||||
const $srctype *src;
|
||||
$tctype *dst;
|
||||
|
||||
#if DEBUG_CONVERT
|
||||
fprintf(stderr, "Converting AUDIO_${from} to AUDIO_${to}.\\n");
|
||||
#endif
|
||||
|
||||
EOF
|
||||
|
||||
if ($fsize < $tsize) {
|
||||
my $mult = $tsize / $fsize;
|
||||
print <<EOF;
|
||||
src = ((const $srctype *) (cvt->buf + cvt->len_cvt)) - 1;
|
||||
dst = (($tctype *) (cvt->buf + cvt->len_cvt * $mult)) - 1;
|
||||
for (i = cvt->len_cvt / sizeof ($srctype); i; --i, --src, --dst) {
|
||||
EOF
|
||||
} else {
|
||||
print <<EOF;
|
||||
src = (const $srctype *) cvt->buf;
|
||||
dst = ($tctype *) cvt->buf;
|
||||
for (i = cvt->len_cvt / sizeof ($srctype); i; --i, ++src, ++dst) {
|
||||
EOF
|
||||
}
|
||||
|
||||
# Have to convert to/from float/int.
|
||||
# !!! FIXME: cast through double for int32<->float?
|
||||
my $code = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, '*src');
|
||||
if ($ffloat != $tfloat) {
|
||||
if ($ffloat) {
|
||||
my $mult = getFloatToIntMult($tsize);
|
||||
if (!$tsigned) { # bump from -1.0f/1.0f to 0.0f/2.0f
|
||||
$code = "($code + 1.0f)";
|
||||
}
|
||||
$code = "(($tctype) ($code * $mult))";
|
||||
} else {
|
||||
# $divby will be the reciprocal, to avoid pipeline stalls
|
||||
# from floating point division...so multiply it.
|
||||
my $divby = getIntToFloatDivBy($fsize);
|
||||
$code = "(((float) $code) * $divby)";
|
||||
if (!$fsigned) { # bump from 0.0f/2.0f to -1.0f/1.0f.
|
||||
$code = "($code - 1.0f)";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# All integer conversions here.
|
||||
if ($fsigned != $tsigned) {
|
||||
my $signflipval = getSignFlipVal($fsize);
|
||||
$code = "(($code) ^ $signflipval)";
|
||||
}
|
||||
|
||||
my $shiftval = abs($fsize - $tsize);
|
||||
if ($fsize < $tsize) {
|
||||
$code = "((($tctype) $code) << $shiftval)";
|
||||
} elsif ($fsize > $tsize) {
|
||||
$code = "(($tctype) ($code >> $shiftval))";
|
||||
}
|
||||
}
|
||||
|
||||
my $swap = getSwapFunc($tsize, $tsigned, $tfloat, $tendian, 'val');
|
||||
|
||||
print <<EOF;
|
||||
const $tctype val = $code;
|
||||
*dst = ${swap};
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
if ($fsize > $tsize) {
|
||||
my $divby = $fsize / $tsize;
|
||||
print(" cvt->len_cvt /= $divby;\n");
|
||||
} elsif ($fsize < $tsize) {
|
||||
my $mult = $tsize / $fsize;
|
||||
print(" cvt->len_cvt *= $mult;\n");
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index] (cvt, AUDIO_$to);
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
} else {
|
||||
if ($fsigned != $tsigned) {
|
||||
$funcs{$hashid} = 'SDL_ConvertSigned';
|
||||
} elsif ($ffloat != $tfloat) {
|
||||
$funcs{$hashid} = 'SDL_ConvertFloat';
|
||||
} elsif ($fsize != $tsize) {
|
||||
$funcs{$hashid} = 'SDL_ConvertSize';
|
||||
} elsif ($fendian ne $tendian) {
|
||||
$funcs{$hashid} = 'SDL_ConvertEndian';
|
||||
} else {
|
||||
die("error in script.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub buildTypeConverters {
|
||||
print "#if !NO_CONVERTERS\n\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@audiotypes) {
|
||||
my $to = $_;
|
||||
buildCvtFunc($from, $to);
|
||||
}
|
||||
}
|
||||
print "#endif /* !NO_CONVERTERS */\n\n\n";
|
||||
|
||||
print "const SDL_AudioTypeFilters sdl_audio_type_filters[] =\n{\n";
|
||||
print "#if !NO_CONVERTERS\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@audiotypes) {
|
||||
my $to = $_;
|
||||
if ($from ne $to) {
|
||||
my $hashid = getTypeConvertHashId($from, $to);
|
||||
my $sym = $funcs{$hashid};
|
||||
print(" { AUDIO_$from, AUDIO_$to, $sym },\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
print "#endif /* !NO_CONVERTERS */\n";
|
||||
|
||||
print(" { 0, 0, NULL }\n");
|
||||
print "};\n\n\n";
|
||||
}
|
||||
|
||||
sub getBiggerCtype {
|
||||
my ($isfloat, $size) = @_;
|
||||
|
||||
if ($isfloat) {
|
||||
if ($size == 32) {
|
||||
return 'double';
|
||||
}
|
||||
die("bug in script.\n");
|
||||
}
|
||||
|
||||
if ($size == 8) {
|
||||
return 'Sint16';
|
||||
} elsif ($size == 16) {
|
||||
return 'Sint32'
|
||||
} elsif ($size == 32) {
|
||||
return 'Sint64'
|
||||
}
|
||||
|
||||
die("bug in script.\n");
|
||||
}
|
||||
|
||||
|
||||
# These handle arbitrary resamples...44100Hz to 48000Hz, for example.
|
||||
# Man, this code is skanky.
|
||||
sub buildArbitraryResampleFunc {
|
||||
# !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
|
||||
my ($from, $channels, $upsample) = @_;
|
||||
my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
|
||||
|
||||
my $bigger = getBiggerCtype($ffloat, $fsize);
|
||||
my $interp = ($ffloat) ? '* 0.5' : '>> 1';
|
||||
|
||||
my $resample = ($upsample) ? 'Upsample' : 'Downsample';
|
||||
my $hashid = getResamplerHashId($from, $channels, $upsample, 0);
|
||||
my $sym = "SDL_${resample}_${from}_${channels}c";
|
||||
$funcs{$hashid} = $sym;
|
||||
$custom_converters++;
|
||||
|
||||
my $fudge = $fsize * $channels * 2; # !!! FIXME
|
||||
my $eps_adjust = ($upsample) ? 'dstsize' : 'srcsize';
|
||||
my $incr = '';
|
||||
my $incr2 = '';
|
||||
|
||||
|
||||
# !!! FIXME: DEBUG_CONVERT should report frequencies.
|
||||
print <<EOF;
|
||||
static void SDLCALL
|
||||
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
{
|
||||
#if DEBUG_CONVERT
|
||||
fprintf(stderr, "$resample arbitrary (x%f) AUDIO_${from}, ${channels} channels.\\n", cvt->rate_incr);
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt - $fudge;
|
||||
const int dstsize = (int) (((double)cvt->len_cvt) * cvt->rate_incr);
|
||||
register int eps = 0;
|
||||
EOF
|
||||
|
||||
my $endcomparison = '!=';
|
||||
|
||||
# Upsampling (growing the buffer) needs to work backwards, since we
|
||||
# overwrite the buffer as we go.
|
||||
if ($upsample) {
|
||||
$endcomparison = '>'; # dst > target
|
||||
print <<EOF;
|
||||
$fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels;
|
||||
const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
|
||||
const $fctype *target = ((const $fctype *) cvt->buf) - $channels;
|
||||
EOF
|
||||
} else {
|
||||
$endcomparison = '<'; # dst < target
|
||||
print <<EOF;
|
||||
$fctype *dst = ($fctype *) cvt->buf;
|
||||
const $fctype *src = ($fctype *) cvt->buf;
|
||||
const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
|
||||
print <<EOF;
|
||||
$fctype sample${idx} = $val;
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
print <<EOF;
|
||||
$fctype last_sample${idx} = sample${idx};
|
||||
EOF
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
while (dst $endcomparison target) {
|
||||
EOF
|
||||
|
||||
if ($upsample) {
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
# !!! FIXME: don't do this swap every write, just when the samples change.
|
||||
my $idx = (($channels - $i) - 1);
|
||||
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${idx}");
|
||||
print <<EOF;
|
||||
dst[$idx] = $val;
|
||||
EOF
|
||||
}
|
||||
|
||||
$incr = ($channels == 1) ? 'dst--' : "dst -= $channels";
|
||||
$incr2 = ($channels == 1) ? 'src--' : "src -= $channels";
|
||||
|
||||
print <<EOF;
|
||||
$incr;
|
||||
eps += srcsize;
|
||||
if ((eps << 1) >= dstsize) {
|
||||
$incr2;
|
||||
EOF
|
||||
} else { # downsample.
|
||||
$incr = ($channels == 1) ? 'src++' : "src += $channels";
|
||||
print <<EOF;
|
||||
$incr;
|
||||
eps += dstsize;
|
||||
if ((eps << 1) >= srcsize) {
|
||||
EOF
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "sample${i}");
|
||||
print <<EOF;
|
||||
dst[$i] = $val;
|
||||
EOF
|
||||
}
|
||||
|
||||
$incr = ($channels == 1) ? 'dst++' : "dst += $channels";
|
||||
print <<EOF;
|
||||
$incr;
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
my $swapped = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
|
||||
print <<EOF;
|
||||
sample${idx} = ($fctype) (((($bigger) $swapped) + (($bigger) last_sample${idx})) $interp);
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
print <<EOF;
|
||||
last_sample${idx} = sample${idx};
|
||||
EOF
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
eps -= $eps_adjust;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
print <<EOF;
|
||||
cvt->len_cvt = dstsize;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index] (cvt, format);
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
# These handle clean resamples...doubling and quadrupling the sample rate, etc.
|
||||
sub buildMultipleResampleFunc {
|
||||
# !!! FIXME: we do a lot of unnecessary and ugly casting in here, due to getSwapFunc().
|
||||
my ($from, $channels, $upsample, $multiple) = @_;
|
||||
my ($fsigned, $ffloat, $fsize, $fendian, $fctype) = splittype($from);
|
||||
|
||||
my $bigger = getBiggerCtype($ffloat, $fsize);
|
||||
my $interp = ($ffloat) ? '* 0.5' : '>> 1';
|
||||
my $interp2 = ($ffloat) ? '* 0.25' : '>> 2';
|
||||
my $mult3 = ($ffloat) ? '3.0' : '3';
|
||||
my $lencvtop = ($upsample) ? '*' : '/';
|
||||
|
||||
my $resample = ($upsample) ? 'Upsample' : 'Downsample';
|
||||
my $hashid = getResamplerHashId($from, $channels, $upsample, $multiple);
|
||||
my $sym = "SDL_${resample}_${from}_${channels}c_x${multiple}";
|
||||
$funcs{$hashid} = $sym;
|
||||
$custom_converters++;
|
||||
|
||||
# !!! FIXME: DEBUG_CONVERT should report frequencies.
|
||||
print <<EOF;
|
||||
static void SDLCALL
|
||||
${sym}(SDL_AudioCVT * cvt, SDL_AudioFormat format)
|
||||
{
|
||||
#if DEBUG_CONVERT
|
||||
fprintf(stderr, "$resample (x${multiple}) AUDIO_${from}, ${channels} channels.\\n");
|
||||
#endif
|
||||
|
||||
const int srcsize = cvt->len_cvt;
|
||||
const int dstsize = cvt->len_cvt $lencvtop $multiple;
|
||||
EOF
|
||||
|
||||
my $endcomparison = '!=';
|
||||
|
||||
# Upsampling (growing the buffer) needs to work backwards, since we
|
||||
# overwrite the buffer as we go.
|
||||
if ($upsample) {
|
||||
$endcomparison = '>'; # dst > target
|
||||
print <<EOF;
|
||||
$fctype *dst = (($fctype *) (cvt->buf + dstsize)) - $channels;
|
||||
const $fctype *src = (($fctype *) (cvt->buf + cvt->len_cvt)) - $channels;
|
||||
const $fctype *target = ((const $fctype *) cvt->buf) - $channels;
|
||||
EOF
|
||||
} else {
|
||||
$endcomparison = '<'; # dst < target
|
||||
print <<EOF;
|
||||
$fctype *dst = ($fctype *) cvt->buf;
|
||||
const $fctype *src = ($fctype *) cvt->buf;
|
||||
const $fctype *target = (const $fctype *) (cvt->buf + dstsize);
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
|
||||
print <<EOF;
|
||||
$bigger last_sample${idx} = ($bigger) $val;
|
||||
EOF
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
while (dst $endcomparison target) {
|
||||
EOF
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
my $val = getSwapFunc($fsize, $fsigned, $ffloat, $fendian, "src[$idx]");
|
||||
print <<EOF;
|
||||
const $bigger sample${idx} = ($bigger) $val;
|
||||
EOF
|
||||
}
|
||||
|
||||
my $incr = '';
|
||||
if ($upsample) {
|
||||
$incr = ($channels == 1) ? 'src--' : "src -= $channels";
|
||||
} else {
|
||||
my $amount = $channels * $multiple;
|
||||
$incr = "src += $amount"; # can't ever be 1, so no "++" version.
|
||||
}
|
||||
|
||||
|
||||
print <<EOF;
|
||||
$incr;
|
||||
EOF
|
||||
|
||||
# !!! FIXME: This really begs for some Altivec or SSE, etc.
|
||||
if ($upsample) {
|
||||
if ($multiple == 2) {
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i + $channels;
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
||||
EOF
|
||||
}
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i;
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) sample${i};
|
||||
EOF
|
||||
}
|
||||
} elsif ($multiple == 4) {
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i + ($channels * 3);
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) sample${i};
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i + ($channels * 2);
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) ((($mult3 * sample${i}) + last_sample${i}) $interp2);
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i + ($channels * 1);
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
||||
EOF
|
||||
}
|
||||
|
||||
for (my $i = $channels-1; $i >= 0; $i--) {
|
||||
my $dsti = $i + ($channels * 0);
|
||||
print <<EOF;
|
||||
dst[$dsti] = ($fctype) ((sample${i} + ($mult3 * last_sample${i})) $interp2);
|
||||
EOF
|
||||
}
|
||||
} else {
|
||||
die('bug in program.'); # we only handle x2 and x4.
|
||||
}
|
||||
} else { # downsample.
|
||||
if ($multiple == 2) {
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
print <<EOF;
|
||||
dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
||||
EOF
|
||||
}
|
||||
} elsif ($multiple == 4) {
|
||||
# !!! FIXME: interpolate all 4 samples?
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
print <<EOF;
|
||||
dst[$i] = ($fctype) ((sample${i} + last_sample${i}) $interp);
|
||||
EOF
|
||||
}
|
||||
} else {
|
||||
die('bug in program.'); # we only handle x2 and x4.
|
||||
}
|
||||
}
|
||||
|
||||
for (my $i = 0; $i < $channels; $i++) {
|
||||
my $idx = ($upsample) ? (($channels - $i) - 1) : $i;
|
||||
print <<EOF;
|
||||
last_sample${idx} = sample${idx};
|
||||
EOF
|
||||
}
|
||||
|
||||
if ($upsample) {
|
||||
my $amount = $channels * $multiple;
|
||||
$incr = "dst -= $amount"; # can't ever be 1, so no "--" version.
|
||||
} else {
|
||||
$incr = ($channels == 1) ? 'dst++' : "dst += $channels";
|
||||
}
|
||||
|
||||
print <<EOF;
|
||||
$incr;
|
||||
}
|
||||
|
||||
cvt->len_cvt = dstsize;
|
||||
if (cvt->filters[++cvt->filter_index]) {
|
||||
cvt->filters[cvt->filter_index] (cvt, format);
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
}
|
||||
|
||||
sub buildResamplers {
|
||||
print "#if !NO_RESAMPLERS\n\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@channels) {
|
||||
my $channel = $_;
|
||||
buildArbitraryResampleFunc($from, $channel, 1);
|
||||
buildArbitraryResampleFunc($from, $channel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
print "\n#if !LESS_RESAMPLERS\n\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@channels) {
|
||||
my $channel = $_;
|
||||
for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
|
||||
buildMultipleResampleFunc($from, $channel, 1, $multiple);
|
||||
buildMultipleResampleFunc($from, $channel, 0, $multiple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "#endif /* !LESS_RESAMPLERS */\n";
|
||||
print "#endif /* !NO_RESAMPLERS */\n\n\n";
|
||||
|
||||
print "const SDL_AudioRateFilters sdl_audio_rate_filters[] =\n{\n";
|
||||
print "#if !NO_RESAMPLERS\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@channels) {
|
||||
my $channel = $_;
|
||||
for (my $upsample = 0; $upsample <= 1; $upsample++) {
|
||||
my $hashid = getResamplerHashId($from, $channel, $upsample, 0);
|
||||
my $sym = $funcs{$hashid};
|
||||
print(" { AUDIO_$from, $channel, $upsample, 0, $sym },\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "#if !LESS_RESAMPLERS\n";
|
||||
foreach (@audiotypes) {
|
||||
my $from = $_;
|
||||
foreach (@channels) {
|
||||
my $channel = $_;
|
||||
for (my $multiple = 2; $multiple <= 4; $multiple += 2) {
|
||||
for (my $upsample = 0; $upsample <= 1; $upsample++) {
|
||||
my $hashid = getResamplerHashId($from, $channel, $upsample, $multiple);
|
||||
my $sym = $funcs{$hashid};
|
||||
print(" { AUDIO_$from, $channel, $upsample, $multiple, $sym },\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print "#endif /* !LESS_RESAMPLERS */\n";
|
||||
print "#endif /* !NO_RESAMPLERS */\n";
|
||||
print(" { 0, 0, 0, 0, NULL }\n");
|
||||
print "};\n\n";
|
||||
}
|
||||
|
||||
|
||||
# mainline ...
|
||||
|
||||
outputHeader();
|
||||
buildTypeConverters();
|
||||
buildResamplers();
|
||||
outputFooter();
|
||||
|
||||
exit 0;
|
||||
|
||||
# end of sdlgenaudiocvt.pl ...
|
||||
|
||||
453
thirdparty/SDL/src/audio/sun/SDL_sunaudio.c
vendored
Normal file
453
thirdparty/SDL/src/audio/sun/SDL_sunaudio.c
vendored
Normal file
@@ -0,0 +1,453 @@
|
||||
/* I'm gambling no one uses this audio backend...we'll see who emails. :) */
|
||||
#error this code has not been updated for SDL 1.3.
|
||||
#error if no one emails icculus at icculus.org and tells him that this
|
||||
#error code is needed, this audio backend will eventually be removed from SDL.
|
||||
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifdef __NETBSD__
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/audioio.h>
|
||||
#endif
|
||||
#ifdef __SVR4
|
||||
#include <sys/audioio.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <unistd.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audiomem.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "../SDL_audiodev_c.h"
|
||||
#include "SDL_sunaudio.h"
|
||||
|
||||
/* Open the audio device for playback, and don't block if busy */
|
||||
#define OPEN_FLAGS (O_WRONLY|O_NONBLOCK)
|
||||
|
||||
/* Audio driver functions */
|
||||
static int DSP_OpenAudio(_THIS, SDL_AudioSpec * spec);
|
||||
static void DSP_WaitAudio(_THIS);
|
||||
static void DSP_PlayAudio(_THIS);
|
||||
static Uint8 *DSP_GetAudioBuf(_THIS);
|
||||
static void DSP_CloseAudio(_THIS);
|
||||
|
||||
static Uint8 snd2au(int sample);
|
||||
|
||||
/* Audio driver bootstrap functions */
|
||||
|
||||
static int
|
||||
Audio_Available(void)
|
||||
{
|
||||
int fd;
|
||||
int available;
|
||||
|
||||
available = 0;
|
||||
fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 1);
|
||||
if (fd >= 0) {
|
||||
available = 1;
|
||||
close(fd);
|
||||
}
|
||||
return (available);
|
||||
}
|
||||
|
||||
static void
|
||||
Audio_DeleteDevice(SDL_AudioDevice * device)
|
||||
{
|
||||
SDL_free(device->hidden);
|
||||
SDL_free(device);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *
|
||||
Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
|
||||
if (this) {
|
||||
SDL_memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ((this == NULL) || (this->hidden == NULL)) {
|
||||
SDL_OutOfMemory();
|
||||
if (this) {
|
||||
SDL_free(this);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
audio_fd = -1;
|
||||
|
||||
/* Set the function pointers */
|
||||
this->OpenAudio = DSP_OpenAudio;
|
||||
this->WaitAudio = DSP_WaitAudio;
|
||||
this->PlayAudio = DSP_PlayAudio;
|
||||
this->GetAudioBuf = DSP_GetAudioBuf;
|
||||
this->CloseAudio = DSP_CloseAudio;
|
||||
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap SUNAUDIO_bootstrap = {
|
||||
"audio", "UNIX /dev/audio interface",
|
||||
Audio_Available, Audio_CreateDevice, 0
|
||||
};
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
void
|
||||
CheckUnderflow(_THIS)
|
||||
{
|
||||
#ifdef AUDIO_GETINFO
|
||||
audio_info_t info;
|
||||
int left;
|
||||
|
||||
ioctl(audio_fd, AUDIO_GETINFO, &info);
|
||||
left = (written - info.play.samples);
|
||||
if (written && (left == 0)) {
|
||||
fprintf(stderr, "audio underflow!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
DSP_WaitAudio(_THIS)
|
||||
{
|
||||
#ifdef AUDIO_GETINFO
|
||||
#define SLEEP_FUDGE 10 /* 10 ms scheduling fudge factor */
|
||||
audio_info_t info;
|
||||
Sint32 left;
|
||||
|
||||
ioctl(audio_fd, AUDIO_GETINFO, &info);
|
||||
left = (written - info.play.samples);
|
||||
if (left > fragsize) {
|
||||
Sint32 sleepy;
|
||||
|
||||
sleepy = ((left - fragsize) / frequency);
|
||||
sleepy -= SLEEP_FUDGE;
|
||||
if (sleepy > 0) {
|
||||
SDL_Delay(sleepy);
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd_set fdset;
|
||||
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(audio_fd, &fdset);
|
||||
select(audio_fd + 1, NULL, &fdset, NULL, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
DSP_PlayAudio(_THIS)
|
||||
{
|
||||
/* Write the audio data */
|
||||
if (ulaw_only) {
|
||||
/* Assuming that this->spec.freq >= 8000 Hz */
|
||||
int accum, incr, pos;
|
||||
Uint8 *aubuf;
|
||||
|
||||
accum = 0;
|
||||
incr = this->spec.freq / 8;
|
||||
aubuf = ulaw_buf;
|
||||
switch (audio_fmt & 0xFF) {
|
||||
case 8:
|
||||
{
|
||||
Uint8 *sndbuf;
|
||||
|
||||
sndbuf = mixbuf;
|
||||
for (pos = 0; pos < fragsize; ++pos) {
|
||||
*aubuf = snd2au((0x80 - *sndbuf) * 64);
|
||||
accum += incr;
|
||||
while (accum > 0) {
|
||||
accum -= 1000;
|
||||
sndbuf += 1;
|
||||
}
|
||||
aubuf += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
{
|
||||
Sint16 *sndbuf;
|
||||
|
||||
sndbuf = (Sint16 *) mixbuf;
|
||||
for (pos = 0; pos < fragsize; ++pos) {
|
||||
*aubuf = snd2au(*sndbuf / 4);
|
||||
accum += incr;
|
||||
while (accum > 0) {
|
||||
accum -= 1000;
|
||||
sndbuf += 1;
|
||||
}
|
||||
aubuf += 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
CheckUnderflow(this);
|
||||
#endif
|
||||
if (write(audio_fd, ulaw_buf, fragsize) < 0) {
|
||||
/* Assume fatal error, for now */
|
||||
this->enabled = 0;
|
||||
}
|
||||
written += fragsize;
|
||||
} else {
|
||||
#ifdef DEBUG_AUDIO
|
||||
CheckUnderflow(this);
|
||||
#endif
|
||||
if (write(audio_fd, mixbuf, this->spec.size) < 0) {
|
||||
/* Assume fatal error, for now */
|
||||
this->enabled = 0;
|
||||
}
|
||||
written += fragsize;
|
||||
}
|
||||
}
|
||||
|
||||
Uint8 *
|
||||
DSP_GetAudioBuf(_THIS)
|
||||
{
|
||||
return (mixbuf);
|
||||
}
|
||||
|
||||
void
|
||||
DSP_CloseAudio(_THIS)
|
||||
{
|
||||
if (mixbuf != NULL) {
|
||||
SDL_FreeAudioMem(mixbuf);
|
||||
mixbuf = NULL;
|
||||
}
|
||||
if (ulaw_buf != NULL) {
|
||||
SDL_free(ulaw_buf);
|
||||
ulaw_buf = NULL;
|
||||
}
|
||||
close(audio_fd);
|
||||
}
|
||||
|
||||
int
|
||||
DSP_OpenAudio(_THIS, SDL_AudioSpec * spec)
|
||||
{
|
||||
char audiodev[1024];
|
||||
#ifdef AUDIO_SETINFO
|
||||
int enc;
|
||||
#endif
|
||||
int desired_freq = spec->freq;
|
||||
|
||||
/* Initialize our freeable variables, in case we fail */
|
||||
audio_fd = -1;
|
||||
mixbuf = NULL;
|
||||
ulaw_buf = NULL;
|
||||
|
||||
/* Determine the audio parameters from the AudioSpec */
|
||||
switch (SDL_AUDIO_BITSIZE(spec->format)) {
|
||||
|
||||
case 8:
|
||||
{ /* Unsigned 8 bit audio data */
|
||||
spec->format = AUDIO_U8;
|
||||
#ifdef AUDIO_SETINFO
|
||||
enc = AUDIO_ENCODING_LINEAR8;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
{ /* Signed 16 bit audio data */
|
||||
spec->format = AUDIO_S16SYS;
|
||||
#ifdef AUDIO_SETINFO
|
||||
enc = AUDIO_ENCODING_LINEAR;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
/* !!! FIXME: fallback to conversion on unsupported types! */
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
audio_fmt = spec->format;
|
||||
|
||||
/* Open the audio device */
|
||||
audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 1);
|
||||
if (audio_fd < 0) {
|
||||
SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ulaw_only = 0; /* modern Suns do support linear audio */
|
||||
#ifdef AUDIO_SETINFO
|
||||
for (;;) {
|
||||
audio_info_t info;
|
||||
AUDIO_INITINFO(&info); /* init all fields to "no change" */
|
||||
|
||||
/* Try to set the requested settings */
|
||||
info.play.sample_rate = spec->freq;
|
||||
info.play.channels = spec->channels;
|
||||
info.play.precision = (enc == AUDIO_ENCODING_ULAW)
|
||||
? 8 : spec->format & 0xff;
|
||||
info.play.encoding = enc;
|
||||
if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) {
|
||||
|
||||
/* Check to be sure we got what we wanted */
|
||||
if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
|
||||
SDL_SetError("Error getting audio parameters: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (info.play.encoding == enc
|
||||
&& info.play.precision == (spec->format & 0xff)
|
||||
&& info.play.channels == spec->channels) {
|
||||
/* Yow! All seems to be well! */
|
||||
spec->freq = info.play.sample_rate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (enc) {
|
||||
case AUDIO_ENCODING_LINEAR8:
|
||||
/* unsigned 8bit apparently not supported here */
|
||||
enc = AUDIO_ENCODING_LINEAR;
|
||||
spec->format = AUDIO_S16SYS;
|
||||
break; /* try again */
|
||||
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
/* linear 16bit didn't work either, resort to µ-law */
|
||||
enc = AUDIO_ENCODING_ULAW;
|
||||
spec->channels = 1;
|
||||
spec->freq = 8000;
|
||||
spec->format = AUDIO_U8;
|
||||
ulaw_only = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* oh well... */
|
||||
SDL_SetError("Error setting audio parameters: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif /* AUDIO_SETINFO */
|
||||
written = 0;
|
||||
|
||||
/* We can actually convert on-the-fly to U-Law */
|
||||
if (ulaw_only) {
|
||||
spec->freq = desired_freq;
|
||||
fragsize = (spec->samples * 1000) / (spec->freq / 8);
|
||||
frequency = 8;
|
||||
ulaw_buf = (Uint8 *) SDL_malloc(fragsize);
|
||||
if (ulaw_buf == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (-1);
|
||||
}
|
||||
spec->channels = 1;
|
||||
} else {
|
||||
fragsize = spec->samples;
|
||||
frequency = spec->freq / 1000;
|
||||
}
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Audio device %s U-Law only\n",
|
||||
ulaw_only ? "is" : "is not");
|
||||
fprintf(stderr, "format=0x%x chan=%d freq=%d\n",
|
||||
spec->format, spec->channels, spec->freq);
|
||||
#endif
|
||||
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(spec);
|
||||
|
||||
/* Allocate mixing buffer */
|
||||
mixbuf = (Uint8 *) SDL_AllocAudioMem(spec->size);
|
||||
if (mixbuf == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return (-1);
|
||||
}
|
||||
SDL_memset(mixbuf, spec->silence, spec->size);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* This function (snd2au()) copyrighted: */
|
||||
/************************************************************************/
|
||||
/* Copyright 1989 by Rich Gopstein and Harris Corporation */
|
||||
/* */
|
||||
/* Permission to use, copy, modify, and distribute this software */
|
||||
/* and its documentation for any purpose and without fee is */
|
||||
/* hereby granted, provided that the above copyright notice */
|
||||
/* appears in all copies and that both that copyright notice and */
|
||||
/* this permission notice appear in supporting documentation, and */
|
||||
/* that the name of Rich Gopstein and Harris Corporation not be */
|
||||
/* used in advertising or publicity pertaining to distribution */
|
||||
/* of the software without specific, written prior permission. */
|
||||
/* Rich Gopstein and Harris Corporation make no representations */
|
||||
/* about the suitability of this software for any purpose. It */
|
||||
/* provided "as is" without express or implied warranty. */
|
||||
/************************************************************************/
|
||||
|
||||
static Uint8
|
||||
snd2au(int sample)
|
||||
{
|
||||
|
||||
int mask;
|
||||
|
||||
if (sample < 0) {
|
||||
sample = -sample;
|
||||
mask = 0x7f;
|
||||
} else {
|
||||
mask = 0xff;
|
||||
}
|
||||
|
||||
if (sample < 32) {
|
||||
sample = 0xF0 | (15 - sample / 2);
|
||||
} else if (sample < 96) {
|
||||
sample = 0xE0 | (15 - (sample - 32) / 4);
|
||||
} else if (sample < 224) {
|
||||
sample = 0xD0 | (15 - (sample - 96) / 8);
|
||||
} else if (sample < 480) {
|
||||
sample = 0xC0 | (15 - (sample - 224) / 16);
|
||||
} else if (sample < 992) {
|
||||
sample = 0xB0 | (15 - (sample - 480) / 32);
|
||||
} else if (sample < 2016) {
|
||||
sample = 0xA0 | (15 - (sample - 992) / 64);
|
||||
} else if (sample < 4064) {
|
||||
sample = 0x90 | (15 - (sample - 2016) / 128);
|
||||
} else if (sample < 8160) {
|
||||
sample = 0x80 | (15 - (sample - 4064) / 256);
|
||||
} else {
|
||||
sample = 0x80;
|
||||
}
|
||||
return (mask & sample);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
57
thirdparty/SDL/src/audio/sun/SDL_sunaudio.h
vendored
Normal file
57
thirdparty/SDL/src/audio/sun/SDL_sunaudio.h
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_sunaudio_h
|
||||
#define _SDL_sunaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* The file descriptor for the audio device */
|
||||
int audio_fd;
|
||||
|
||||
SDL_AudioFormat audio_fmt; /* The app audio format */
|
||||
Uint8 *mixbuf; /* The app mixing buffer */
|
||||
int ulaw_only; /* Flag -- does hardware only output U-law? */
|
||||
Uint8 *ulaw_buf; /* The U-law mixing buffer */
|
||||
Sint32 written; /* The number of samples written */
|
||||
int fragsize; /* The audio fragment size in samples */
|
||||
int frequency; /* The audio frequency in KHz */
|
||||
};
|
||||
|
||||
/* Old variable names */
|
||||
#define audio_fd (this->hidden->audio_fd)
|
||||
#define audio_fmt (this->hidden->audio_fmt)
|
||||
#define mixbuf (this->hidden->mixbuf)
|
||||
#define ulaw_only (this->hidden->ulaw_only)
|
||||
#define ulaw_buf (this->hidden->ulaw_buf)
|
||||
#define written (this->hidden->written)
|
||||
#define fragsize (this->hidden->fragsize)
|
||||
#define frequency (this->hidden->frequency)
|
||||
|
||||
#endif /* _SDL_sunaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
560
thirdparty/SDL/src/audio/ums/SDL_umsaudio.c
vendored
Normal file
560
thirdparty/SDL/src/audio/ums/SDL_umsaudio.c
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
/* I'm gambling no one uses this audio backend...we'll see who emails. :) */
|
||||
#error this code has not been updated for SDL 1.3.
|
||||
#error if no one emails icculus at icculus.org and tells him that this
|
||||
#error code is needed, this audio backend will eventually be removed from SDL.
|
||||
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_umsaudio.h"
|
||||
|
||||
/* The tag name used by UMS audio */
|
||||
#define UMS_DRIVER_NAME "ums"
|
||||
|
||||
#define DEBUG_AUDIO 1
|
||||
|
||||
/* Audio driver functions */
|
||||
static int UMS_OpenAudio(_THIS, SDL_AudioSpec * spec);
|
||||
static void UMS_PlayAudio(_THIS);
|
||||
static Uint8 *UMS_GetAudioBuf(_THIS);
|
||||
static void UMS_CloseAudio(_THIS);
|
||||
|
||||
static UMSAudioDevice_ReturnCode UADOpen(_THIS, string device, string mode,
|
||||
long flags);
|
||||
static UMSAudioDevice_ReturnCode UADClose(_THIS);
|
||||
static UMSAudioDevice_ReturnCode UADGetBitsPerSample(_THIS, long *bits);
|
||||
static UMSAudioDevice_ReturnCode UADSetBitsPerSample(_THIS, long bits);
|
||||
static UMSAudioDevice_ReturnCode UADSetSampleRate(_THIS, long rate,
|
||||
long *set_rate);
|
||||
static UMSAudioDevice_ReturnCode UADSetByteOrder(_THIS, string byte_order);
|
||||
static UMSAudioDevice_ReturnCode UADSetAudioFormatType(_THIS, string fmt);
|
||||
static UMSAudioDevice_ReturnCode UADSetNumberFormat(_THIS, string fmt);
|
||||
static UMSAudioDevice_ReturnCode UADInitialize(_THIS);
|
||||
static UMSAudioDevice_ReturnCode UADStart(_THIS);
|
||||
static UMSAudioDevice_ReturnCode UADStop(_THIS);
|
||||
static UMSAudioDevice_ReturnCode UADSetTimeFormat(_THIS,
|
||||
UMSAudioTypes_TimeFormat
|
||||
fmt);
|
||||
static UMSAudioDevice_ReturnCode UADWriteBuffSize(_THIS, long *buff_size);
|
||||
static UMSAudioDevice_ReturnCode UADWriteBuffRemain(_THIS, long *buff_size);
|
||||
static UMSAudioDevice_ReturnCode UADWriteBuffUsed(_THIS, long *buff_size);
|
||||
static UMSAudioDevice_ReturnCode UADSetDMABufferSize(_THIS, long bytes,
|
||||
long *bytes_ret);
|
||||
static UMSAudioDevice_ReturnCode UADSetVolume(_THIS, long volume);
|
||||
static UMSAudioDevice_ReturnCode UADSetBalance(_THIS, long balance);
|
||||
static UMSAudioDevice_ReturnCode UADSetChannels(_THIS, long channels);
|
||||
static UMSAudioDevice_ReturnCode UADPlayRemainingData(_THIS, boolean block);
|
||||
static UMSAudioDevice_ReturnCode UADEnableOutput(_THIS, string output,
|
||||
long *left_gain,
|
||||
long *right_gain);
|
||||
static UMSAudioDevice_ReturnCode UADWrite(_THIS, UMSAudioTypes_Buffer * buff,
|
||||
long samples,
|
||||
long *samples_written);
|
||||
|
||||
/* Audio driver bootstrap functions */
|
||||
static int
|
||||
Audio_Available(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
Audio_DeleteDevice(_THIS)
|
||||
{
|
||||
if (this->hidden->playbuf._buffer)
|
||||
SDL_free(this->hidden->playbuf._buffer);
|
||||
if (this->hidden->fillbuf._buffer)
|
||||
SDL_free(this->hidden->fillbuf._buffer);
|
||||
_somFree(this->hidden->umsdev);
|
||||
SDL_free(this->hidden);
|
||||
SDL_free(this);
|
||||
}
|
||||
|
||||
static SDL_AudioDevice *
|
||||
Audio_CreateDevice(int devindex)
|
||||
{
|
||||
SDL_AudioDevice *this;
|
||||
|
||||
/*
|
||||
* Allocate and initialize management storage and private management
|
||||
* storage for this SDL-using library.
|
||||
*/
|
||||
this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
|
||||
if (this) {
|
||||
SDL_memset(this, 0, (sizeof *this));
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
}
|
||||
if ((this == NULL) || (this->hidden == NULL)) {
|
||||
SDL_OutOfMemory();
|
||||
if (this) {
|
||||
SDL_free(this);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Creating UMS Audio device\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Calls for UMS env initialization and audio object construction.
|
||||
*/
|
||||
this->hidden->ev = somGetGlobalEnvironment();
|
||||
this->hidden->umsdev = UMSAudioDeviceNew();
|
||||
|
||||
/*
|
||||
* Set the function pointers.
|
||||
*/
|
||||
this->OpenAudio = UMS_OpenAudio;
|
||||
this->WaitAudio = NULL; /* we do blocking output */
|
||||
this->PlayAudio = UMS_PlayAudio;
|
||||
this->GetAudioBuf = UMS_GetAudioBuf;
|
||||
this->CloseAudio = UMS_CloseAudio;
|
||||
this->free = Audio_DeleteDevice;
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "done\n");
|
||||
#endif
|
||||
return this;
|
||||
}
|
||||
|
||||
AudioBootStrap UMS_bootstrap = {
|
||||
UMS_DRIVER_NAME, "AIX UMS audio",
|
||||
Audio_Available, Audio_CreateDevice, 0
|
||||
};
|
||||
|
||||
static Uint8 *
|
||||
UMS_GetAudioBuf(_THIS)
|
||||
{
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "enter UMS_GetAudioBuf\n");
|
||||
#endif
|
||||
return this->hidden->fillbuf._buffer;
|
||||
/*
|
||||
long bufSize;
|
||||
UMSAudioDevice_ReturnCode rc;
|
||||
|
||||
rc = UADSetTimeFormat(this, UMSAudioTypes_Bytes );
|
||||
rc = UADWriteBuffSize(this, bufSize );
|
||||
*/
|
||||
}
|
||||
|
||||
static void
|
||||
UMS_CloseAudio(_THIS)
|
||||
{
|
||||
UMSAudioDevice_ReturnCode rc;
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "enter UMS_CloseAudio\n");
|
||||
#endif
|
||||
rc = UADPlayRemainingData(this, TRUE);
|
||||
rc = UADStop(this);
|
||||
rc = UADClose(this);
|
||||
}
|
||||
|
||||
static void
|
||||
UMS_PlayAudio(_THIS)
|
||||
{
|
||||
UMSAudioDevice_ReturnCode rc;
|
||||
long samplesToWrite;
|
||||
long samplesWritten;
|
||||
UMSAudioTypes_Buffer swpbuf;
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "enter UMS_PlayAudio\n");
|
||||
#endif
|
||||
samplesToWrite =
|
||||
this->hidden->playbuf._length / this->hidden->bytesPerSample;
|
||||
do {
|
||||
rc = UADWrite(this, &this->hidden->playbuf,
|
||||
samplesToWrite, &samplesWritten);
|
||||
samplesToWrite -= samplesWritten;
|
||||
|
||||
/* rc values: UMSAudioDevice_Success
|
||||
* UMSAudioDevice_Failure
|
||||
* UMSAudioDevice_Preempted
|
||||
* UMSAudioDevice_Interrupted
|
||||
* UMSAudioDevice_DeviceError
|
||||
*/
|
||||
if (rc == UMSAudioDevice_DeviceError) {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Returning from PlayAudio with devices error\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
} while (samplesToWrite > 0);
|
||||
|
||||
SDL_LockAudio();
|
||||
SDL_memcpy(&swpbuf, &this->hidden->playbuf, sizeof(UMSAudioTypes_Buffer));
|
||||
SDL_memcpy(&this->hidden->playbuf, &this->hidden->fillbuf,
|
||||
sizeof(UMSAudioTypes_Buffer));
|
||||
SDL_memcpy(&this->hidden->fillbuf, &swpbuf, sizeof(UMSAudioTypes_Buffer));
|
||||
SDL_UnlockAudio();
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Wrote audio data and swapped buffer\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
// /* Set the DSP frequency */
|
||||
// value = spec->freq;
|
||||
// if ( ioctl(this->hidden->audio_fd, SOUND_PCM_WRITE_RATE, &value) < 0 ) {
|
||||
// SDL_SetError("Couldn't set audio frequency");
|
||||
// return(-1);
|
||||
// }
|
||||
// spec->freq = value;
|
||||
#endif
|
||||
|
||||
static int
|
||||
UMS_OpenAudio(_THIS, SDL_AudioSpec * spec)
|
||||
{
|
||||
char *audiodev = "/dev/paud0";
|
||||
long lgain;
|
||||
long rgain;
|
||||
long outRate;
|
||||
long outBufSize;
|
||||
long bitsPerSample;
|
||||
long samplesPerSec;
|
||||
long success;
|
||||
SDL_AudioFormat test_format;
|
||||
int frag_spec;
|
||||
UMSAudioDevice_ReturnCode rc;
|
||||
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "enter UMS_OpenAudio\n");
|
||||
#endif
|
||||
rc = UADOpen(this, audiodev, "PLAY", UMSAudioDevice_BlockingIO);
|
||||
if (rc != UMSAudioDevice_Success) {
|
||||
SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = UADSetAudioFormatType(this, "PCM");
|
||||
|
||||
success = 0;
|
||||
test_format = SDL_FirstAudioFormat(spec->format);
|
||||
do {
|
||||
#ifdef DEBUG_AUDIO
|
||||
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
|
||||
#endif
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
/* from the mac code: better ? */
|
||||
/* sample_bits = spec->size / spec->samples / spec->channels * 8; */
|
||||
success = 1;
|
||||
bitsPerSample = 8;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
|
||||
rc = UADSetNumberFormat(this, "UNSIGNED");
|
||||
break;
|
||||
case AUDIO_S8:
|
||||
success = 1;
|
||||
bitsPerSample = 8;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "MSB"); /* irrelevant */
|
||||
rc = UADSetNumberFormat(this, "SIGNED");
|
||||
break;
|
||||
case AUDIO_S16LSB:
|
||||
success = 1;
|
||||
bitsPerSample = 16;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "LSB");
|
||||
rc = UADSetNumberFormat(this, "SIGNED");
|
||||
break;
|
||||
case AUDIO_S16MSB:
|
||||
success = 1;
|
||||
bitsPerSample = 16;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "MSB");
|
||||
rc = UADSetNumberFormat(this, "SIGNED");
|
||||
break;
|
||||
case AUDIO_U16LSB:
|
||||
success = 1;
|
||||
bitsPerSample = 16;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "LSB");
|
||||
rc = UADSetNumberFormat(this, "UNSIGNED");
|
||||
break;
|
||||
case AUDIO_U16MSB:
|
||||
success = 1;
|
||||
bitsPerSample = 16;
|
||||
rc = UADSetSampleRate(this, spec->freq << 16, &outRate);
|
||||
rc = UADSetByteOrder(this, "MSB");
|
||||
rc = UADSetNumberFormat(this, "UNSIGNED");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!success) {
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
} while (!success && test_format);
|
||||
|
||||
if (success == 0) {
|
||||
SDL_SetError("Couldn't find any hardware audio formats");
|
||||
return -1;
|
||||
}
|
||||
|
||||
spec->format = test_format;
|
||||
|
||||
for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
|
||||
if ((0x01 << frag_spec) != spec->size) {
|
||||
SDL_SetError("Fragment size must be a power of two");
|
||||
return -1;
|
||||
}
|
||||
if (frag_spec > 2048)
|
||||
frag_spec = 2048;
|
||||
|
||||
this->hidden->bytesPerSample = (bitsPerSample / 8) * spec->channels;
|
||||
samplesPerSec = this->hidden->bytesPerSample * outRate;
|
||||
|
||||
this->hidden->playbuf._length = 0;
|
||||
this->hidden->playbuf._maximum = spec->size;
|
||||
this->hidden->playbuf._buffer = (unsigned char *) SDL_malloc(spec->size);
|
||||
this->hidden->fillbuf._length = 0;
|
||||
this->hidden->fillbuf._maximum = spec->size;
|
||||
this->hidden->fillbuf._buffer = (unsigned char *) SDL_malloc(spec->size);
|
||||
|
||||
rc = UADSetBitsPerSample(this, bitsPerSample);
|
||||
rc = UADSetDMABufferSize(this, frag_spec, &outBufSize);
|
||||
rc = UADSetChannels(this, spec->channels); /* functions reduces to mono or stereo */
|
||||
|
||||
lgain = 100; /*maximum left input gain */
|
||||
rgain = 100; /*maimum right input gain */
|
||||
rc = UADEnableOutput(this, "LINE_OUT", &lgain, &rgain);
|
||||
rc = UADInitialize(this);
|
||||
rc = UADStart(this);
|
||||
rc = UADSetVolume(this, 100);
|
||||
rc = UADSetBalance(this, 0);
|
||||
|
||||
/* We're ready to rock and roll. :-) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADGetBitsPerSample(_THIS, long *bits)
|
||||
{
|
||||
return UMSAudioDevice_get_bits_per_sample(this->hidden->umsdev,
|
||||
this->hidden->ev, bits);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetBitsPerSample(_THIS, long bits)
|
||||
{
|
||||
return UMSAudioDevice_set_bits_per_sample(this->hidden->umsdev,
|
||||
this->hidden->ev, bits);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetSampleRate(_THIS, long rate, long *set_rate)
|
||||
{
|
||||
/* from the mac code: sample rate = spec->freq << 16; */
|
||||
return UMSAudioDevice_set_sample_rate(this->hidden->umsdev,
|
||||
this->hidden->ev, rate, set_rate);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetByteOrder(_THIS, string byte_order)
|
||||
{
|
||||
return UMSAudioDevice_set_byte_order(this->hidden->umsdev,
|
||||
this->hidden->ev, byte_order);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetAudioFormatType(_THIS, string fmt)
|
||||
{
|
||||
/* possible PCM, A_LAW or MU_LAW */
|
||||
return UMSAudioDevice_set_audio_format_type(this->hidden->umsdev,
|
||||
this->hidden->ev, fmt);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetNumberFormat(_THIS, string fmt)
|
||||
{
|
||||
/* possible SIGNED, UNSIGNED, or TWOS_COMPLEMENT */
|
||||
return UMSAudioDevice_set_number_format(this->hidden->umsdev,
|
||||
this->hidden->ev, fmt);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADInitialize(_THIS)
|
||||
{
|
||||
return UMSAudioDevice_initialize(this->hidden->umsdev, this->hidden->ev);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADStart(_THIS)
|
||||
{
|
||||
return UMSAudioDevice_start(this->hidden->umsdev, this->hidden->ev);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetTimeFormat(_THIS, UMSAudioTypes_TimeFormat fmt)
|
||||
{
|
||||
/*
|
||||
* Switches the time format to the new format, immediately.
|
||||
* possible UMSAudioTypes_Msecs, UMSAudioTypes_Bytes or UMSAudioTypes_Samples
|
||||
*/
|
||||
return UMSAudioDevice_set_time_format(this->hidden->umsdev,
|
||||
this->hidden->ev, fmt);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADWriteBuffSize(_THIS, long *buff_size)
|
||||
{
|
||||
/*
|
||||
* returns write buffer size in the current time format
|
||||
*/
|
||||
return UMSAudioDevice_write_buff_size(this->hidden->umsdev,
|
||||
this->hidden->ev, buff_size);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADWriteBuffRemain(_THIS, long *buff_size)
|
||||
{
|
||||
/*
|
||||
* returns amount of available space in the write buffer
|
||||
* in the current time format
|
||||
*/
|
||||
return UMSAudioDevice_write_buff_remain(this->hidden->umsdev,
|
||||
this->hidden->ev, buff_size);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADWriteBuffUsed(_THIS, long *buff_size)
|
||||
{
|
||||
/*
|
||||
* returns amount of filled space in the write buffer
|
||||
* in the current time format
|
||||
*/
|
||||
return UMSAudioDevice_write_buff_used(this->hidden->umsdev,
|
||||
this->hidden->ev, buff_size);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetDMABufferSize(_THIS, long bytes, long *bytes_ret)
|
||||
{
|
||||
/*
|
||||
* Request a new DMA buffer size, maximum requested size 2048.
|
||||
* Takes effect with next initialize() call.
|
||||
* Devices may or may not support DMA.
|
||||
*/
|
||||
return UMSAudioDevice_set_DMA_buffer_size(this->hidden->umsdev,
|
||||
this->hidden->ev,
|
||||
bytes, bytes_ret);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetVolume(_THIS, long volume)
|
||||
{
|
||||
/*
|
||||
* Set the volume.
|
||||
* Takes effect immediately.
|
||||
*/
|
||||
return UMSAudioDevice_set_volume(this->hidden->umsdev,
|
||||
this->hidden->ev, volume);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetBalance(_THIS, long balance)
|
||||
{
|
||||
/*
|
||||
* Set the balance.
|
||||
* Takes effect immediately.
|
||||
*/
|
||||
return UMSAudioDevice_set_balance(this->hidden->umsdev,
|
||||
this->hidden->ev, balance);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADSetChannels(_THIS, long channels)
|
||||
{
|
||||
/*
|
||||
* Set mono or stereo.
|
||||
* Takes effect with next initialize() call.
|
||||
*/
|
||||
if (channels != 1)
|
||||
channels = 2;
|
||||
return UMSAudioDevice_set_number_of_channels(this->hidden->umsdev,
|
||||
this->hidden->ev, channels);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADOpen(_THIS, string device, string mode, long flags)
|
||||
{
|
||||
return UMSAudioDevice_open(this->hidden->umsdev,
|
||||
this->hidden->ev, device, mode, flags);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADWrite(_THIS, UMSAudioTypes_Buffer * buff,
|
||||
long samples, long *samples_written)
|
||||
{
|
||||
return UMSAudioDevice_write(this->hidden->umsdev,
|
||||
this->hidden->ev,
|
||||
buff, samples, samples_written);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADPlayRemainingData(_THIS, boolean block)
|
||||
{
|
||||
return UMSAudioDevice_play_remaining_data(this->hidden->umsdev,
|
||||
this->hidden->ev, block);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADStop(_THIS)
|
||||
{
|
||||
return UMSAudioDevice_stop(this->hidden->umsdev, this->hidden->ev);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADClose(_THIS)
|
||||
{
|
||||
return UMSAudioDevice_close(this->hidden->umsdev, this->hidden->ev);
|
||||
}
|
||||
|
||||
static UMSAudioDevice_ReturnCode
|
||||
UADEnableOutput(_THIS, string output, long *left_gain, long *right_gain)
|
||||
{
|
||||
return UMSAudioDevice_enable_output(this->hidden->umsdev,
|
||||
this->hidden->ev,
|
||||
output, left_gain, right_gain);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
47
thirdparty/SDL/src/audio/ums/SDL_umsaudio.h
vendored
Normal file
47
thirdparty/SDL/src/audio/ums/SDL_umsaudio.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_UMSaudio_h
|
||||
#define _SDL_UMSaudio_h
|
||||
|
||||
#include <UMS/UMSAudioDevice.h>
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
/* Pointer to the (open) UMS audio device */
|
||||
Environment *ev;
|
||||
UMSAudioDevice umsdev;
|
||||
|
||||
/* Raw mixing buffer */
|
||||
UMSAudioTypes_Buffer playbuf;
|
||||
UMSAudioTypes_Buffer fillbuf;
|
||||
|
||||
long bytesPerSample;
|
||||
};
|
||||
|
||||
#endif /* _SDL_UMSaudio_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
328
thirdparty/SDL/src/audio/windib/SDL_dibaudio.c
vendored
Normal file
328
thirdparty/SDL/src/audio/windib/SDL_dibaudio.c
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_dibaudio.h"
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
#include "win_ce_semaphore.h"
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32_WCE)
|
||||
#define WINDOWS_OS_NAME "Windows CE/PocketPC"
|
||||
#elif defined(WIN64)
|
||||
#define WINDOWS_OS_NAME "Win64"
|
||||
#else
|
||||
#define WINDOWS_OS_NAME "Win32"
|
||||
#endif
|
||||
|
||||
/* The Win32 callback for filling the WAVE device */
|
||||
static void CALLBACK
|
||||
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
|
||||
DWORD dwParam1, DWORD dwParam2)
|
||||
{
|
||||
SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
|
||||
|
||||
/* Only service "buffer done playing" messages */
|
||||
if (uMsg != WOM_DONE)
|
||||
return;
|
||||
|
||||
/* Signal that we are done playing a buffer */
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
|
||||
#else
|
||||
ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
SetMMerror(char *function, MMRESULT code)
|
||||
{
|
||||
size_t len;
|
||||
char errbuf[MAXERRORLENGTH];
|
||||
wchar_t werrbuf[MAXERRORLENGTH];
|
||||
|
||||
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
|
||||
len = SDL_strlen(errbuf);
|
||||
|
||||
waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
|
||||
WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
|
||||
MAXERRORLENGTH - len, NULL, NULL);
|
||||
|
||||
SDL_SetError("%s", errbuf);
|
||||
}
|
||||
|
||||
/* Set high priority for the audio thread */
|
||||
static void
|
||||
WINWAVEOUT_ThreadInit(_THIS)
|
||||
{
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
void
|
||||
WINWAVEOUT_WaitDevice(_THIS)
|
||||
{
|
||||
/* Wait for an audio chunk to finish */
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
|
||||
#else
|
||||
WaitForSingleObject(this->hidden->audio_sem, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint8 *
|
||||
WINWAVEOUT_GetDeviceBuf(_THIS)
|
||||
{
|
||||
return (Uint8 *) (this->hidden->
|
||||
wavebuf[this->hidden->next_buffer].lpData);
|
||||
}
|
||||
|
||||
void
|
||||
WINWAVEOUT_PlayDevice(_THIS)
|
||||
{
|
||||
/* Queue it up */
|
||||
waveOutWrite(this->hidden->sound,
|
||||
&this->hidden->wavebuf[this->hidden->next_buffer],
|
||||
sizeof(this->hidden->wavebuf[0]));
|
||||
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
|
||||
}
|
||||
|
||||
void
|
||||
WINWAVEOUT_WaitDone(_THIS)
|
||||
{
|
||||
int i, left;
|
||||
|
||||
do {
|
||||
left = NUM_BUFFERS;
|
||||
for (i = 0; i < NUM_BUFFERS; ++i) {
|
||||
if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
|
||||
--left;
|
||||
}
|
||||
}
|
||||
if (left > 0) {
|
||||
SDL_Delay(100);
|
||||
}
|
||||
} while (left > 0);
|
||||
}
|
||||
|
||||
void
|
||||
WINWAVEOUT_CloseDevice(_THIS)
|
||||
{
|
||||
/* Close up audio */
|
||||
if (this->hidden != NULL) {
|
||||
int i;
|
||||
|
||||
if (this->hidden->audio_sem) {
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
CloseSynchHandle(this->hidden->audio_sem);
|
||||
#else
|
||||
CloseHandle(this->hidden->audio_sem);
|
||||
#endif
|
||||
this->hidden->audio_sem = 0;
|
||||
}
|
||||
|
||||
if (this->hidden->sound) {
|
||||
waveOutClose(this->hidden->sound);
|
||||
this->hidden->sound = 0;
|
||||
}
|
||||
|
||||
/* Clean up mixing buffers */
|
||||
for (i = 0; i < NUM_BUFFERS; ++i) {
|
||||
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
|
||||
waveOutUnprepareHeader(this->hidden->sound,
|
||||
&this->hidden->wavebuf[i],
|
||||
sizeof(this->hidden->wavebuf[i]));
|
||||
this->hidden->wavebuf[i].dwUser = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
/* Free raw mixing buffer */
|
||||
SDL_free(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
int valid_datatype = 0;
|
||||
MMRESULT result;
|
||||
WAVEFORMATEX waveformat;
|
||||
int i;
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
/* Initialize the wavebuf structures for closing */
|
||||
for (i = 0; i < NUM_BUFFERS; ++i)
|
||||
this->hidden->wavebuf[i].dwUser = 0xFFFF;
|
||||
|
||||
while ((!valid_datatype) && (test_format)) {
|
||||
valid_datatype = 1;
|
||||
this->spec.format = test_format;
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S16:
|
||||
case AUDIO_S32:
|
||||
break; /* valid. */
|
||||
|
||||
default:
|
||||
valid_datatype = 0;
|
||||
test_format = SDL_NextAudioFormat();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid_datatype) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SDL_SetError("Unsupported audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set basic WAVE format parameters */
|
||||
SDL_memset(&waveformat, '\0', sizeof(waveformat));
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
|
||||
if (this->spec.channels > 2)
|
||||
this->spec.channels = 2; /* !!! FIXME: is this right? */
|
||||
|
||||
waveformat.nChannels = this->spec.channels;
|
||||
waveformat.nSamplesPerSec = this->spec.freq;
|
||||
waveformat.nBlockAlign =
|
||||
waveformat.nChannels * (waveformat.wBitsPerSample / 8);
|
||||
waveformat.nAvgBytesPerSec =
|
||||
waveformat.nSamplesPerSec * waveformat.nBlockAlign;
|
||||
|
||||
/* Check the buffer size -- minimum of 1/4 second (word aligned) */
|
||||
if (this->spec.samples < (this->spec.freq / 4))
|
||||
this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
|
||||
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Open the audio device */
|
||||
result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
|
||||
(DWORD_PTR) FillSound, (DWORD_PTR) this,
|
||||
CALLBACK_FUNCTION);
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SetMMerror("waveOutOpen()", result);
|
||||
return 0;
|
||||
}
|
||||
#ifdef SOUND_DEBUG
|
||||
/* Check the sound device we retrieved */
|
||||
{
|
||||
WAVEOUTCAPS caps;
|
||||
|
||||
result = waveOutGetDevCaps((UINT) this->hidden->sound,
|
||||
&caps, sizeof(caps));
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SetMMerror("waveOutGetDevCaps()", result);
|
||||
return 0;
|
||||
}
|
||||
printf("Audio device: %s\n", caps.szPname);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create the audio buffer semaphore */
|
||||
this->hidden->audio_sem =
|
||||
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
|
||||
CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
#else
|
||||
CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
|
||||
#endif
|
||||
if (this->hidden->audio_sem == NULL) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SDL_SetError("Couldn't create semaphore");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the sound buffers */
|
||||
this->hidden->mixbuf =
|
||||
(Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
|
||||
if (this->hidden->mixbuf == NULL) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < NUM_BUFFERS; ++i) {
|
||||
SDL_memset(&this->hidden->wavebuf[i], '\0',
|
||||
sizeof(this->hidden->wavebuf[i]));
|
||||
this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
|
||||
this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
|
||||
this->hidden->wavebuf[i].lpData =
|
||||
(LPSTR) & this->hidden->mixbuf[i * this->spec.size];
|
||||
result = waveOutPrepareHeader(this->hidden->sound,
|
||||
&this->hidden->wavebuf[i],
|
||||
sizeof(this->hidden->wavebuf[i]));
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
WINWAVEOUT_CloseDevice(this);
|
||||
SetMMerror("waveOutPrepareHeader()", result);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1; /* Ready to go! */
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
WINWAVEOUT_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = WINWAVEOUT_OpenDevice;
|
||||
impl->ThreadInit = WINWAVEOUT_ThreadInit;
|
||||
impl->PlayDevice = WINWAVEOUT_PlayDevice;
|
||||
impl->WaitDevice = WINWAVEOUT_WaitDevice;
|
||||
impl->WaitDone = WINWAVEOUT_WaitDone;
|
||||
impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
|
||||
impl->CloseDevice = WINWAVEOUT_CloseDevice;
|
||||
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Is this true? */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap WINWAVEOUT_bootstrap = {
|
||||
"waveout", WINDOWS_OS_NAME " WaveOut", WINWAVEOUT_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
44
thirdparty/SDL/src/audio/windib/SDL_dibaudio.h
vendored
Normal file
44
thirdparty/SDL/src/audio/windib/SDL_dibaudio.h
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_dibaudio_h
|
||||
#define _SDL_dibaudio_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 2 /* -- Don't lower this! */
|
||||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
HWAVEOUT sound;
|
||||
HANDLE audio_sem;
|
||||
Uint8 *mixbuf; /* The raw allocated mixing buffer */
|
||||
WAVEHDR wavebuf[NUM_BUFFERS]; /* Wave audio fragments */
|
||||
int next_buffer;
|
||||
};
|
||||
|
||||
#endif /* _SDL_dibaudio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
517
thirdparty/SDL/src/audio/windx5/SDL_dx5audio.c
vendored
Normal file
517
thirdparty/SDL/src/audio/windx5/SDL_dx5audio.c
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_loadso.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_dx5audio.h"
|
||||
|
||||
/* !!! FIXME: move this somewhere that other drivers can use it... */
|
||||
#if defined(_WIN32_WCE)
|
||||
#define WINDOWS_OS_NAME "Windows CE/PocketPC"
|
||||
#elif defined(WIN64)
|
||||
#define WINDOWS_OS_NAME "Win64"
|
||||
#else
|
||||
#define WINDOWS_OS_NAME "Win32"
|
||||
#endif
|
||||
|
||||
/* DirectX function pointers for audio */
|
||||
static void* DSoundDLL = NULL;
|
||||
static HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN) =
|
||||
NULL;
|
||||
|
||||
static void
|
||||
DSOUND_Unload(void)
|
||||
{
|
||||
DSoundCreate = NULL;
|
||||
|
||||
if (DSoundDLL != NULL) {
|
||||
SDL_UnloadObject(DSoundDLL);
|
||||
DSoundDLL = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DSOUND_Load(void)
|
||||
{
|
||||
int loaded = 0;
|
||||
|
||||
DSOUND_Unload();
|
||||
|
||||
DSoundDLL = SDL_LoadObject("DSOUND.DLL");
|
||||
if (DSoundDLL == NULL) {
|
||||
SDL_SetError("DirectSound: failed to load DSOUND.DLL");
|
||||
} else {
|
||||
/* Now make sure we have DirectX 5 or better... */
|
||||
/* (DirectSoundCaptureCreate was added in DX5) */
|
||||
if (!SDL_LoadFunction(DSoundDLL, "DirectSoundCaptureCreate")) {
|
||||
SDL_SetError("DirectSound: System doesn't appear to have DX5.");
|
||||
} else {
|
||||
DSoundCreate = SDL_LoadFunction(DSoundDLL, "DirectSoundCreate");
|
||||
}
|
||||
|
||||
if (!DSoundCreate) {
|
||||
SDL_SetError("DirectSound: Failed to find DirectSoundCreate");
|
||||
} else {
|
||||
loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
DSOUND_Unload();
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
SetDSerror(const char *function, int code)
|
||||
{
|
||||
static const char *error;
|
||||
static char errbuf[1024];
|
||||
|
||||
errbuf[0] = 0;
|
||||
switch (code) {
|
||||
case E_NOINTERFACE:
|
||||
error = "Unsupported interface -- Is DirectX 5.0 or later installed?";
|
||||
break;
|
||||
case DSERR_ALLOCATED:
|
||||
error = "Audio device in use";
|
||||
break;
|
||||
case DSERR_BADFORMAT:
|
||||
error = "Unsupported audio format";
|
||||
break;
|
||||
case DSERR_BUFFERLOST:
|
||||
error = "Mixing buffer was lost";
|
||||
break;
|
||||
case DSERR_CONTROLUNAVAIL:
|
||||
error = "Control requested is not available";
|
||||
break;
|
||||
case DSERR_INVALIDCALL:
|
||||
error = "Invalid call for the current state";
|
||||
break;
|
||||
case DSERR_INVALIDPARAM:
|
||||
error = "Invalid parameter";
|
||||
break;
|
||||
case DSERR_NODRIVER:
|
||||
error = "No audio device found";
|
||||
break;
|
||||
case DSERR_OUTOFMEMORY:
|
||||
error = "Out of memory";
|
||||
break;
|
||||
case DSERR_PRIOLEVELNEEDED:
|
||||
error = "Caller doesn't have priority";
|
||||
break;
|
||||
case DSERR_UNSUPPORTED:
|
||||
error = "Function not supported";
|
||||
break;
|
||||
default:
|
||||
SDL_snprintf(errbuf, SDL_arraysize(errbuf),
|
||||
"%s: Unknown DirectSound error: 0x%x", function, code);
|
||||
break;
|
||||
}
|
||||
if (!errbuf[0]) {
|
||||
SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
|
||||
error);
|
||||
}
|
||||
SDL_SetError("%s", errbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* DirectSound needs to be associated with a window */
|
||||
static HWND mainwin = NULL;
|
||||
/* */
|
||||
|
||||
void
|
||||
DSOUND_SoundFocus(HWND hwnd)
|
||||
{
|
||||
/* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */
|
||||
mainwin = hwnd;
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_ThreadInit(_THIS)
|
||||
{
|
||||
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_WaitDevice(_THIS)
|
||||
{
|
||||
DWORD status = 0;
|
||||
DWORD cursor = 0;
|
||||
DWORD junk = 0;
|
||||
HRESULT result = DS_OK;
|
||||
|
||||
/* Semi-busy wait, since we have no way of getting play notification
|
||||
on a primary mixing buffer located in hardware (DirectX 5.0)
|
||||
*/
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
if (result != DS_OK) {
|
||||
if (result == DSERR_BUFFERLOST) {
|
||||
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
||||
}
|
||||
#ifdef DEBUG_SOUND
|
||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
|
||||
/* FIXME: find out how much time is left and sleep that long */
|
||||
SDL_Delay(1);
|
||||
|
||||
/* Try to restore a lost sound buffer */
|
||||
IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
|
||||
if ((status & DSBSTATUS_BUFFERLOST)) {
|
||||
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
||||
IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
|
||||
if ((status & DSBSTATUS_BUFFERLOST)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(status & DSBSTATUS_PLAYING)) {
|
||||
result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
|
||||
DSBPLAY_LOOPING);
|
||||
if (result == DS_OK) {
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_SOUND
|
||||
SetDSerror("DirectSound Play", result);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find out where we are playing */
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_PlayDevice(_THIS)
|
||||
{
|
||||
/* Unlock the buffer, allowing it to play */
|
||||
if (this->hidden->locked_buf) {
|
||||
IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
|
||||
this->hidden->locked_buf,
|
||||
this->hidden->mixlen, NULL, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static Uint8 *
|
||||
DSOUND_GetDeviceBuf(_THIS)
|
||||
{
|
||||
DWORD cursor = 0;
|
||||
DWORD junk = 0;
|
||||
HRESULT result = DS_OK;
|
||||
DWORD rawlen = 0;
|
||||
|
||||
/* Figure out which blocks to fill next */
|
||||
this->hidden->locked_buf = NULL;
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
if (result == DSERR_BUFFERLOST) {
|
||||
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
||||
result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
|
||||
&junk, &cursor);
|
||||
}
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound GetCurrentPosition", result);
|
||||
return (NULL);
|
||||
}
|
||||
cursor /= this->hidden->mixlen;
|
||||
#ifdef DEBUG_SOUND
|
||||
/* Detect audio dropouts */
|
||||
{
|
||||
DWORD spot = cursor;
|
||||
if (spot < this->hidden->lastchunk) {
|
||||
spot += this->hidden->num_buffers;
|
||||
}
|
||||
if (spot > this->hidden->lastchunk + 1) {
|
||||
fprintf(stderr, "Audio dropout, missed %d fragments\n",
|
||||
(spot - (this->hidden->lastchunk + 1)));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
this->hidden->lastchunk = cursor;
|
||||
cursor = (cursor + 1) % this->hidden->num_buffers;
|
||||
cursor *= this->hidden->mixlen;
|
||||
|
||||
/* Lock the audio buffer */
|
||||
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
||||
this->hidden->mixlen,
|
||||
(LPVOID *) & this->hidden->locked_buf,
|
||||
&rawlen, NULL, &junk, 0);
|
||||
if (result == DSERR_BUFFERLOST) {
|
||||
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
|
||||
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
|
||||
this->hidden->mixlen,
|
||||
(LPVOID *) & this->
|
||||
hidden->locked_buf, &rawlen, NULL,
|
||||
&junk, 0);
|
||||
}
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound Lock", result);
|
||||
return (NULL);
|
||||
}
|
||||
return (this->hidden->locked_buf);
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_WaitDone(_THIS)
|
||||
{
|
||||
Uint8 *stream = DSOUND_GetDeviceBuf(this);
|
||||
|
||||
/* Wait for the playing chunk to finish */
|
||||
if (stream != NULL) {
|
||||
SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
|
||||
DSOUND_PlayDevice(this);
|
||||
}
|
||||
DSOUND_WaitDevice(this);
|
||||
|
||||
/* Stop the looping sound buffer */
|
||||
IDirectSoundBuffer_Stop(this->hidden->mixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
DSOUND_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden != NULL) {
|
||||
if (this->hidden->sound != NULL) {
|
||||
if (this->hidden->mixbuf != NULL) {
|
||||
/* Clean up the audio buffer */
|
||||
IDirectSoundBuffer_Release(this->hidden->mixbuf);
|
||||
this->hidden->mixbuf = NULL;
|
||||
}
|
||||
IDirectSound_Release(this->hidden->sound);
|
||||
this->hidden->sound = NULL;
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
this->hidden = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function tries to create a secondary audio buffer, and returns the
|
||||
number of audio chunks available in the created buffer.
|
||||
*/
|
||||
static int
|
||||
CreateSecondary(_THIS, HWND focus, WAVEFORMATEX * wavefmt)
|
||||
{
|
||||
LPDIRECTSOUND sndObj = this->hidden->sound;
|
||||
LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
|
||||
Uint32 chunksize = this->spec.size;
|
||||
const int numchunks = 8;
|
||||
HRESULT result = DS_OK;
|
||||
DSBUFFERDESC format;
|
||||
LPVOID pvAudioPtr1, pvAudioPtr2;
|
||||
DWORD dwAudioBytes1, dwAudioBytes2;
|
||||
|
||||
/* Try to set primary mixing privileges */
|
||||
if (focus) {
|
||||
result = IDirectSound_SetCooperativeLevel(sndObj,
|
||||
focus, DSSCL_PRIORITY);
|
||||
} else {
|
||||
result = IDirectSound_SetCooperativeLevel(sndObj,
|
||||
GetDesktopWindow(),
|
||||
DSSCL_NORMAL);
|
||||
}
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound SetCooperativeLevel", result);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Try to create the secondary buffer */
|
||||
SDL_memset(&format, 0, sizeof(format));
|
||||
format.dwSize = sizeof(format);
|
||||
format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
|
||||
if (!focus) {
|
||||
format.dwFlags |= DSBCAPS_GLOBALFOCUS;
|
||||
} else {
|
||||
format.dwFlags |= DSBCAPS_STICKYFOCUS;
|
||||
}
|
||||
format.dwBufferBytes = numchunks * chunksize;
|
||||
if ((format.dwBufferBytes < DSBSIZE_MIN) ||
|
||||
(format.dwBufferBytes > DSBSIZE_MAX)) {
|
||||
SDL_SetError("Sound buffer size must be between %d and %d",
|
||||
DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
|
||||
return (-1);
|
||||
}
|
||||
format.dwReserved = 0;
|
||||
format.lpwfxFormat = wavefmt;
|
||||
result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
|
||||
if (result != DS_OK) {
|
||||
SetDSerror("DirectSound CreateSoundBuffer", result);
|
||||
return (-1);
|
||||
}
|
||||
IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
|
||||
|
||||
/* Silence the initial audio buffer */
|
||||
result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
|
||||
(LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
|
||||
(LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
|
||||
DSBLOCK_ENTIREBUFFER);
|
||||
if (result == DS_OK) {
|
||||
SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
|
||||
IDirectSoundBuffer_Unlock(*sndbuf,
|
||||
(LPVOID) pvAudioPtr1, dwAudioBytes1,
|
||||
(LPVOID) pvAudioPtr2, dwAudioBytes2);
|
||||
}
|
||||
|
||||
/* We're ready to go */
|
||||
return (numchunks);
|
||||
}
|
||||
|
||||
static int
|
||||
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
|
||||
{
|
||||
HRESULT result;
|
||||
WAVEFORMATEX waveformat;
|
||||
int valid_format = 0;
|
||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||
|
||||
/* !!! FIXME: handle devname */
|
||||
/* !!! FIXME: handle iscapture */
|
||||
|
||||
/* Initialize all variables that we clean on shutdown */
|
||||
this->hidden = (struct SDL_PrivateAudioData *)
|
||||
SDL_malloc((sizeof *this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
return 0;
|
||||
}
|
||||
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
|
||||
|
||||
while ((!valid_format) && (test_format)) {
|
||||
switch (test_format) {
|
||||
case AUDIO_U8:
|
||||
case AUDIO_S16:
|
||||
case AUDIO_S32:
|
||||
this->spec.format = test_format;
|
||||
valid_format = 1;
|
||||
break;
|
||||
}
|
||||
test_format = SDL_NextAudioFormat();
|
||||
}
|
||||
|
||||
if (!valid_format) {
|
||||
DSOUND_CloseDevice(this);
|
||||
SDL_SetError("DirectSound: Unsupported audio format");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_memset(&waveformat, 0, sizeof(waveformat));
|
||||
waveformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
|
||||
waveformat.nChannels = this->spec.channels;
|
||||
waveformat.nSamplesPerSec = this->spec.freq;
|
||||
waveformat.nBlockAlign =
|
||||
waveformat.nChannels * (waveformat.wBitsPerSample / 8);
|
||||
waveformat.nAvgBytesPerSec =
|
||||
waveformat.nSamplesPerSec * waveformat.nBlockAlign;
|
||||
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec(&this->spec);
|
||||
|
||||
/* Open the audio device */
|
||||
result = DSoundCreate(NULL, &this->hidden->sound, NULL);
|
||||
if (result != DS_OK) {
|
||||
DSOUND_CloseDevice(this);
|
||||
SetDSerror("DirectSoundCreate", result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create the audio buffer to which we write */
|
||||
this->hidden->num_buffers = CreateSecondary(this, mainwin, &waveformat);
|
||||
if (this->hidden->num_buffers < 0) {
|
||||
DSOUND_CloseDevice(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The buffer will auto-start playing in DSOUND_WaitDevice() */
|
||||
this->hidden->mixlen = this->spec.size;
|
||||
|
||||
return 1; /* good to go. */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
DSOUND_Deinitialize(void)
|
||||
{
|
||||
DSOUND_Unload();
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
DSOUND_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
OSVERSIONINFO ver;
|
||||
|
||||
/*
|
||||
* Unfortunately, the sound drivers on NT have higher latencies than the
|
||||
* audio buffers used by many SDL applications, so there are gaps in the
|
||||
* audio - it sounds terrible. Punt for now.
|
||||
*/
|
||||
SDL_memset(&ver, '\0', sizeof(OSVERSIONINFO));
|
||||
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&ver);
|
||||
if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
||||
if (ver.dwMajorVersion <= 4) {
|
||||
return 0; /* NT4.0 or earlier. Disable dsound support. */
|
||||
}
|
||||
}
|
||||
|
||||
if (!DSOUND_Load()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the function pointers */
|
||||
impl->OpenDevice = DSOUND_OpenDevice;
|
||||
impl->PlayDevice = DSOUND_PlayDevice;
|
||||
impl->WaitDevice = DSOUND_WaitDevice;
|
||||
impl->WaitDone = DSOUND_WaitDone;
|
||||
impl->ThreadInit = DSOUND_ThreadInit;
|
||||
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
|
||||
impl->CloseDevice = DSOUND_CloseDevice;
|
||||
impl->Deinitialize = DSOUND_Deinitialize;
|
||||
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME */
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
AudioBootStrap DSOUND_bootstrap = {
|
||||
"dsound", WINDOWS_OS_NAME "DirectSound", DSOUND_Init, 0
|
||||
};
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
46
thirdparty/SDL/src/audio/windx5/SDL_dx5audio.h
vendored
Normal file
46
thirdparty/SDL/src/audio/windx5/SDL_dx5audio.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_dx5audio_h
|
||||
#define _SDL_dx5audio_h
|
||||
|
||||
#include "directx.h"
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
/* The DirectSound objects */
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
LPDIRECTSOUND sound;
|
||||
LPDIRECTSOUNDBUFFER mixbuf;
|
||||
int num_buffers;
|
||||
int mixlen;
|
||||
DWORD lastchunk;
|
||||
Uint8 *locked_buf;
|
||||
};
|
||||
|
||||
#endif /* _SDL_dx5audio_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
81
thirdparty/SDL/src/audio/windx5/directx.h
vendored
Normal file
81
thirdparty/SDL/src/audio/windx5/directx.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
#ifndef _directx_h
|
||||
#define _directx_h
|
||||
|
||||
/* Include all of the DirectX 5.0 headers and adds any necessary tweaks */
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <mmsystem.h>
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
#endif
|
||||
#undef WINNT
|
||||
|
||||
/* Far pointers don't exist in 32-bit code */
|
||||
#ifndef FAR
|
||||
#define FAR
|
||||
#endif
|
||||
|
||||
/* Error codes not yet included in Win32 API header files */
|
||||
#ifndef MAKE_HRESULT
|
||||
#define MAKE_HRESULT(sev,fac,code) \
|
||||
((HRESULT)(((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))))
|
||||
#endif
|
||||
|
||||
#ifndef S_OK
|
||||
#define S_OK (HRESULT)0x00000000L
|
||||
#endif
|
||||
|
||||
#ifndef SUCCEEDED
|
||||
#define SUCCEEDED(x) ((HRESULT)(x) >= 0)
|
||||
#endif
|
||||
#ifndef FAILED
|
||||
#define FAILED(x) ((HRESULT)(x)<0)
|
||||
#endif
|
||||
|
||||
#ifndef E_FAIL
|
||||
#define E_FAIL (HRESULT)0x80000008L
|
||||
#endif
|
||||
#ifndef E_NOINTERFACE
|
||||
#define E_NOINTERFACE (HRESULT)0x80004002L
|
||||
#endif
|
||||
#ifndef E_OUTOFMEMORY
|
||||
#define E_OUTOFMEMORY (HRESULT)0x8007000EL
|
||||
#endif
|
||||
#ifndef E_INVALIDARG
|
||||
#define E_INVALIDARG (HRESULT)0x80070057L
|
||||
#endif
|
||||
#ifndef E_NOTIMPL
|
||||
#define E_NOTIMPL (HRESULT)0x80004001L
|
||||
#endif
|
||||
#ifndef REGDB_E_CLASSNOTREG
|
||||
#define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L
|
||||
#endif
|
||||
|
||||
/* Severity codes */
|
||||
#ifndef SEVERITY_ERROR
|
||||
#define SEVERITY_ERROR 1
|
||||
#endif
|
||||
|
||||
/* Error facility codes */
|
||||
#ifndef FACILITY_WIN32
|
||||
#define FACILITY_WIN32 7
|
||||
#endif
|
||||
|
||||
#ifndef FIELD_OFFSET
|
||||
#define FIELD_OFFSET(type, field) ((LONG)&(((type *)0)->field))
|
||||
#endif
|
||||
|
||||
/* DirectX headers (if it isn't included, I haven't tested it yet)
|
||||
*/
|
||||
/* We need these defines to mark what version of DirectX API we use */
|
||||
#define DIRECTDRAW_VERSION 0x0700
|
||||
#define DIRECTSOUND_VERSION 0x0500
|
||||
#define DIRECTINPUT_VERSION 0x0500
|
||||
|
||||
#include <ddraw.h>
|
||||
#include <dsound.h>
|
||||
#include <dinput.h>
|
||||
|
||||
#endif /* _directx_h */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
269
thirdparty/SDL/src/core/android/SDL_android.cpp
vendored
Normal file
269
thirdparty/SDL/src/core/android/SDL_android.cpp
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
#include "SDL_stdinc.h"
|
||||
|
||||
#include "SDL_android.h"
|
||||
|
||||
extern "C" {
|
||||
#include "../../events/SDL_events_c.h"
|
||||
#include "../../video/android/SDL_androidkeyboard.h"
|
||||
#include "../../video/android/SDL_androidtouch.h"
|
||||
#include "../../video/android/SDL_androidvideo.h"
|
||||
|
||||
/* Impelemented in audio/android/SDL_androidaudio.c */
|
||||
extern void Android_RunAudioThread();
|
||||
} // C
|
||||
|
||||
/*******************************************************************************
|
||||
This file links the Java side of Android with libsdl
|
||||
*******************************************************************************/
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Globals
|
||||
*******************************************************************************/
|
||||
static JNIEnv* mEnv = NULL;
|
||||
static JNIEnv* mAudioEnv = NULL;
|
||||
|
||||
// Main activity
|
||||
static jclass mActivityClass;
|
||||
|
||||
// method signatures
|
||||
static jmethodID midCreateGLContext;
|
||||
static jmethodID midFlipBuffers;
|
||||
static jmethodID midAudioInit;
|
||||
static jmethodID midAudioWriteShortBuffer;
|
||||
static jmethodID midAudioWriteByteBuffer;
|
||||
static jmethodID midAudioQuit;
|
||||
|
||||
// Accelerometer data storage
|
||||
static float fLastAccelerometer[3];
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Functions called by JNI
|
||||
*******************************************************************************/
|
||||
|
||||
// Library init
|
||||
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
// Called before SDL_main() to initialize JNI bindings
|
||||
extern "C" void SDL_Android_Init(JNIEnv* env, jclass cls)
|
||||
{
|
||||
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
|
||||
|
||||
mEnv = env;
|
||||
mActivityClass = cls;
|
||||
|
||||
midCreateGLContext = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"createGLContext","(II)Z");
|
||||
midFlipBuffers = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"flipBuffers","()V");
|
||||
midAudioInit = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"audioInit", "(IZZI)Ljava/lang/Object;");
|
||||
midAudioWriteShortBuffer = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"audioWriteShortBuffer", "([S)V");
|
||||
midAudioWriteByteBuffer = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"audioWriteByteBuffer", "([B)V");
|
||||
midAudioQuit = mEnv->GetStaticMethodID(mActivityClass,
|
||||
"audioQuit", "()V");
|
||||
|
||||
if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
|
||||
!midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
|
||||
}
|
||||
}
|
||||
|
||||
// Resize
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint width, jint height, jint format)
|
||||
{
|
||||
Android_SetScreenResolution(width, height, format);
|
||||
}
|
||||
|
||||
// Keydown
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
|
||||
JNIEnv* env, jclass jcls, jint keycode)
|
||||
{
|
||||
Android_OnKeyDown(keycode);
|
||||
}
|
||||
|
||||
// Keyup
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
|
||||
JNIEnv* env, jclass jcls, jint keycode)
|
||||
{
|
||||
Android_OnKeyUp(keycode);
|
||||
}
|
||||
|
||||
// Touch
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jint index, jint action, jfloat x, jfloat y, jfloat p)
|
||||
{
|
||||
Android_OnTouch(index, action, x, y, p);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeFlickGesture(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jfloat xVelocity, jfloat yVelocity)
|
||||
{
|
||||
Android_OnFlickGesture(xVelocity, yVelocity);
|
||||
}
|
||||
|
||||
// Accelerometer
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
|
||||
JNIEnv* env, jclass jcls,
|
||||
jfloat x, jfloat y, jfloat z)
|
||||
{
|
||||
fLastAccelerometer[0] = x;
|
||||
fLastAccelerometer[1] = y;
|
||||
fLastAccelerometer[2] = z;
|
||||
}
|
||||
|
||||
// Quit
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
// Inject a SDL_QUIT event
|
||||
SDL_SendQuit();
|
||||
}
|
||||
|
||||
extern "C" void Java_org_libsdl_app_SDLActivity_nativeRunAudioThread(
|
||||
JNIEnv* env, jclass cls)
|
||||
{
|
||||
/* This is the audio thread, with a different environment */
|
||||
mAudioEnv = env;
|
||||
|
||||
Android_RunAudioThread();
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Functions called by SDL into Java
|
||||
*******************************************************************************/
|
||||
extern "C" SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion)
|
||||
{
|
||||
if (mEnv->CallStaticBooleanMethod(mActivityClass, midCreateGLContext, majorVersion, minorVersion)) {
|
||||
return SDL_TRUE;
|
||||
} else {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Android_JNI_SwapWindow()
|
||||
{
|
||||
mEnv->CallStaticVoidMethod(mActivityClass, midFlipBuffers);
|
||||
}
|
||||
|
||||
extern "C" void Android_JNI_SetActivityTitle(const char *title)
|
||||
{
|
||||
jmethodID mid;
|
||||
|
||||
mid = mEnv->GetStaticMethodID(mActivityClass,"setActivityTitle","(Ljava/lang/String;)V");
|
||||
if (mid) {
|
||||
mEnv->CallStaticVoidMethod(mActivityClass, mid, mEnv->NewStringUTF(title));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void Android_JNI_GetAccelerometerValues(float values[3])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
values[i] = fLastAccelerometer[i];
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Audio support
|
||||
//
|
||||
static jboolean audioBuffer16Bit = JNI_FALSE;
|
||||
static jboolean audioBufferStereo = JNI_FALSE;
|
||||
static jobject audioBuffer = NULL;
|
||||
static void* audioBufferPinned = NULL;
|
||||
|
||||
extern "C" int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
|
||||
{
|
||||
int audioBufferFrames;
|
||||
|
||||
__android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
|
||||
audioBuffer16Bit = is16Bit;
|
||||
audioBufferStereo = channelCount > 1;
|
||||
|
||||
audioBuffer = mEnv->CallStaticObjectMethod(mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames);
|
||||
|
||||
if (audioBuffer == NULL) {
|
||||
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: didn't get back a good audio buffer!");
|
||||
return 0;
|
||||
}
|
||||
audioBuffer = mEnv->NewGlobalRef(audioBuffer);
|
||||
|
||||
jboolean isCopy = JNI_FALSE;
|
||||
if (audioBuffer16Bit) {
|
||||
audioBufferPinned = mEnv->GetShortArrayElements((jshortArray)audioBuffer, &isCopy);
|
||||
audioBufferFrames = mEnv->GetArrayLength((jshortArray)audioBuffer);
|
||||
} else {
|
||||
audioBufferPinned = mEnv->GetByteArrayElements((jbyteArray)audioBuffer, &isCopy);
|
||||
audioBufferFrames = mEnv->GetArrayLength((jbyteArray)audioBuffer);
|
||||
}
|
||||
if (audioBufferStereo) {
|
||||
audioBufferFrames /= 2;
|
||||
}
|
||||
|
||||
return audioBufferFrames;
|
||||
}
|
||||
|
||||
extern "C" void * Android_JNI_GetAudioBuffer()
|
||||
{
|
||||
return audioBufferPinned;
|
||||
}
|
||||
|
||||
extern "C" void Android_JNI_WriteAudioBuffer()
|
||||
{
|
||||
if (audioBuffer16Bit) {
|
||||
mAudioEnv->ReleaseShortArrayElements((jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
|
||||
mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
|
||||
} else {
|
||||
mAudioEnv->ReleaseByteArrayElements((jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
|
||||
mAudioEnv->CallStaticVoidMethod(mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
|
||||
}
|
||||
|
||||
/* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
|
||||
}
|
||||
|
||||
extern "C" void Android_JNI_CloseAudioDevice()
|
||||
{
|
||||
mEnv->CallStaticVoidMethod(mActivityClass, midAudioQuit);
|
||||
|
||||
if (audioBuffer) {
|
||||
mEnv->DeleteGlobalRef(audioBuffer);
|
||||
audioBuffer = NULL;
|
||||
audioBufferPinned = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
49
thirdparty/SDL/src/core/android/SDL_android.h
vendored
Normal file
49
thirdparty/SDL/src/core/android/SDL_android.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
extern "C" {
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* Interface from the SDL library into the Android Java activity */
|
||||
extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion);
|
||||
extern void Android_JNI_SwapWindow();
|
||||
extern void Android_JNI_SetActivityTitle(const char *title);
|
||||
extern void Android_JNI_GetAccelerometerValues(float values[3]);
|
||||
|
||||
// Audio support
|
||||
extern int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
|
||||
extern void* Android_JNI_GetAudioBuffer();
|
||||
extern void Android_JNI_WriteAudioBuffer();
|
||||
extern void Android_JNI_CloseAudioDevice();
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
/* *INDENT-OFF* */
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
40
thirdparty/SDL/src/core/windows/SDL_windows.c
vendored
Normal file
40
thirdparty/SDL/src/core/windows/SDL_windows.c
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_windows.h"
|
||||
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
void
|
||||
WIN_SetError(const char *prefix)
|
||||
{
|
||||
TCHAR buffer[1024];
|
||||
char *message;
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||||
buffer, SDL_arraysize(buffer), NULL);
|
||||
message = WIN_StringToUTF8(buffer);
|
||||
SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message);
|
||||
SDL_free(message);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
52
thirdparty/SDL/src/core/windows/SDL_windows.h
vendored
Normal file
52
thirdparty/SDL/src/core/windows/SDL_windows.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* This is an include file for windows.h with the SDL build settings */
|
||||
|
||||
#ifndef _INCLUDED_WINDOWS_H
|
||||
#define _INCLUDED_WINDOWS_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define STRICT
|
||||
#ifndef UNICODE
|
||||
#define UNICODE 1
|
||||
#endif
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x500 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices() */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
/* Routines to convert from UTF8 to native Windows text */
|
||||
#if UNICODE
|
||||
#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR))
|
||||
#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#else
|
||||
#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)(S), (SDL_strlen(S)+1))
|
||||
#define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
|
||||
#endif
|
||||
|
||||
/* Sets an error message based on GetLastError() */
|
||||
extern void WIN_SetError(const char *prefix);
|
||||
|
||||
#endif /* _INCLUDED_WINDOWS_H */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
624
thirdparty/SDL/src/cpuinfo/SDL_cpuinfo.c
vendored
Normal file
624
thirdparty/SDL/src/cpuinfo/SDL_cpuinfo.c
vendored
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* CPU feature detection for SDL */
|
||||
|
||||
#include "SDL_cpuinfo.h"
|
||||
|
||||
#ifdef HAVE_SYSCONF
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYSCTLBYNAME
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
|
||||
#include <sys/sysctl.h> /* For AltiVec check */
|
||||
#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
#ifdef __WIN32__
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
#endif
|
||||
|
||||
#define CPU_HAS_RDTSC 0x00000001
|
||||
#define CPU_HAS_ALTIVEC 0x00000002
|
||||
#define CPU_HAS_MMX 0x00000004
|
||||
#define CPU_HAS_3DNOW 0x00000008
|
||||
#define CPU_HAS_SSE 0x00000010
|
||||
#define CPU_HAS_SSE2 0x00000020
|
||||
#define CPU_HAS_SSE3 0x00000040
|
||||
#define CPU_HAS_SSE41 0x00000100
|
||||
#define CPU_HAS_SSE42 0x00000200
|
||||
|
||||
#if SDL_ALTIVEC_BLITTERS && HAVE_SETJMP && !__MACOSX__
|
||||
/* This is the brute force way of detecting instruction sets...
|
||||
the idea is borrowed from the libmpeg2 library - thanks!
|
||||
*/
|
||||
static jmp_buf jmpbuf;
|
||||
static void
|
||||
illegal_instruction(int sig)
|
||||
{
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
#endif /* HAVE_SETJMP */
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveCPUID(void)
|
||||
{
|
||||
int has_CPUID = 0;
|
||||
/* *INDENT-OFF* */
|
||||
#if defined(__GNUC__) && defined(i386)
|
||||
__asm__ (
|
||||
" pushfl # Get original EFLAGS \n"
|
||||
" popl %%eax \n"
|
||||
" movl %%eax,%%ecx \n"
|
||||
" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
|
||||
" pushl %%eax # Save new EFLAGS value on stack \n"
|
||||
" popfl # Replace current EFLAGS value \n"
|
||||
" pushfl # Get new EFLAGS \n"
|
||||
" popl %%eax # Store new EFLAGS in EAX \n"
|
||||
" xorl %%ecx,%%eax # Can not toggle ID bit, \n"
|
||||
" jz 1f # Processor=80486 \n"
|
||||
" movl $1,%0 # We have CPUID support \n"
|
||||
"1: \n"
|
||||
: "=m" (has_CPUID)
|
||||
:
|
||||
: "%eax", "%ecx"
|
||||
);
|
||||
#elif defined(__GNUC__) && defined(__x86_64__)
|
||||
/* Technically, if this is being compiled under __x86_64__ then it has
|
||||
CPUid by definition. But it's nice to be able to prove it. :) */
|
||||
__asm__ (
|
||||
" pushfq # Get original EFLAGS \n"
|
||||
" popq %%rax \n"
|
||||
" movq %%rax,%%rcx \n"
|
||||
" xorl $0x200000,%%eax # Flip ID bit in EFLAGS \n"
|
||||
" pushq %%rax # Save new EFLAGS value on stack \n"
|
||||
" popfq # Replace current EFLAGS value \n"
|
||||
" pushfq # Get new EFLAGS \n"
|
||||
" popq %%rax # Store new EFLAGS in EAX \n"
|
||||
" xorl %%ecx,%%eax # Can not toggle ID bit, \n"
|
||||
" jz 1f # Processor=80486 \n"
|
||||
" movl $1,%0 # We have CPUID support \n"
|
||||
"1: \n"
|
||||
: "=m" (has_CPUID)
|
||||
:
|
||||
: "%rax", "%rcx"
|
||||
);
|
||||
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
||||
__asm {
|
||||
pushfd ; Get original EFLAGS
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 200000h ; Flip ID bit in EFLAGS
|
||||
push eax ; Save new EFLAGS value on stack
|
||||
popfd ; Replace current EFLAGS value
|
||||
pushfd ; Get new EFLAGS
|
||||
pop eax ; Store new EFLAGS in EAX
|
||||
xor eax, ecx ; Can not toggle ID bit,
|
||||
jz done ; Processor=80486
|
||||
mov has_CPUID,1 ; We have CPUID support
|
||||
done:
|
||||
}
|
||||
#elif defined(__sun) && defined(__i386)
|
||||
__asm (
|
||||
" pushfl \n"
|
||||
" popl %eax \n"
|
||||
" movl %eax,%ecx \n"
|
||||
" xorl $0x200000,%eax \n"
|
||||
" pushl %eax \n"
|
||||
" popfl \n"
|
||||
" pushfl \n"
|
||||
" popl %eax \n"
|
||||
" xorl %ecx,%eax \n"
|
||||
" jz 1f \n"
|
||||
" movl $1,-8(%ebp) \n"
|
||||
"1: \n"
|
||||
);
|
||||
#elif defined(__sun) && defined(__amd64)
|
||||
__asm (
|
||||
" pushfq \n"
|
||||
" popq %rax \n"
|
||||
" movq %rax,%rcx \n"
|
||||
" xorl $0x200000,%eax \n"
|
||||
" pushq %rax \n"
|
||||
" popfq \n"
|
||||
" pushfq \n"
|
||||
" popq %rax \n"
|
||||
" xorl %ecx,%eax \n"
|
||||
" jz 1f \n"
|
||||
" movl $1,-8(%rbp) \n"
|
||||
"1: \n"
|
||||
);
|
||||
#endif
|
||||
/* *INDENT-ON* */
|
||||
return has_CPUID;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined(i386)
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm__ __volatile__ ( \
|
||||
" pushl %%ebx \n" \
|
||||
" cpuid \n" \
|
||||
" movl %%ebx, %%esi \n" \
|
||||
" popl %%ebx \n" : \
|
||||
"=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
|
||||
#elif defined(__GNUC__) && defined(__x86_64__)
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm__ __volatile__ ( \
|
||||
" pushq %%rbx \n" \
|
||||
" cpuid \n" \
|
||||
" movq %%rbx, %%rsi \n" \
|
||||
" popq %%rbx \n" : \
|
||||
"=a" (a), "=S" (b), "=c" (c), "=d" (d) : "a" (func))
|
||||
#elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
__asm { \
|
||||
__asm mov eax, func \
|
||||
__asm cpuid \
|
||||
__asm mov a, eax \
|
||||
__asm mov b, ebx \
|
||||
__asm mov c, ecx \
|
||||
__asm mov d, edx \
|
||||
}
|
||||
#else
|
||||
#define cpuid(func, a, b, c, d) \
|
||||
a = b = c = d = 0
|
||||
#endif
|
||||
|
||||
static __inline__ int
|
||||
CPU_getCPUIDFeatures(void)
|
||||
{
|
||||
int features = 0;
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
features = d;
|
||||
}
|
||||
return features;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveRDTSC(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
return (CPU_getCPUIDFeatures() & 0x00000010);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveAltiVec(void)
|
||||
{
|
||||
volatile int altivec = 0;
|
||||
#if defined(__MACOSX__) && (defined(__ppc__) || defined(__ppc64__))
|
||||
int selectors[2] = { CTL_HW, HW_VECTORUNIT };
|
||||
int hasVectorUnit = 0;
|
||||
size_t length = sizeof(hasVectorUnit);
|
||||
int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
|
||||
if (0 == error)
|
||||
altivec = (hasVectorUnit != 0);
|
||||
#elif SDL_ALTIVEC_BLITTERS && HAVE_SETJMP
|
||||
void (*handler) (int sig);
|
||||
handler = signal(SIGILL, illegal_instruction);
|
||||
if (setjmp(jmpbuf) == 0) {
|
||||
asm volatile ("mtspr 256, %0\n\t" "vand %%v0, %%v0, %%v0"::"r" (-1));
|
||||
altivec = 1;
|
||||
}
|
||||
signal(SIGILL, handler);
|
||||
#endif
|
||||
return altivec;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveMMX(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
return (CPU_getCPUIDFeatures() & 0x00800000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_have3DNow(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0x80000000, a, b, c, d);
|
||||
if (a >= 0x80000001) {
|
||||
cpuid(0x80000001, a, b, c, d);
|
||||
return (d & 0x80000000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveSSE(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
return (CPU_getCPUIDFeatures() & 0x02000000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveSSE2(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
return (CPU_getCPUIDFeatures() & 0x04000000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveSSE3(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x00000001);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveSSE41(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(1, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x00080000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
CPU_haveSSE42(void)
|
||||
{
|
||||
if (CPU_haveCPUID()) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(1, a, b, c, d);
|
||||
if (a >= 1) {
|
||||
cpuid(1, a, b, c, d);
|
||||
return (c & 0x00100000);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SDL_CPUCount = 0;
|
||||
|
||||
int
|
||||
SDL_GetCPUCount(void)
|
||||
{
|
||||
if (!SDL_CPUCount) {
|
||||
#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN)
|
||||
if (SDL_CPUCount <= 0) {
|
||||
SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SYSCTLBYNAME
|
||||
if (SDL_CPUCount <= 0) {
|
||||
size_t size = sizeof(SDL_CPUCount);
|
||||
sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef __WIN32__
|
||||
if (SDL_CPUCount <= 0) {
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
SDL_CPUCount = info.dwNumberOfProcessors;
|
||||
}
|
||||
#endif
|
||||
/* There has to be at least 1, right? :) */
|
||||
if (SDL_CPUCount <= 0) {
|
||||
SDL_CPUCount = 1;
|
||||
}
|
||||
}
|
||||
return SDL_CPUCount;
|
||||
}
|
||||
|
||||
/* Oh, such a sweet sweet trick, just not very useful. :) */
|
||||
static const char *
|
||||
SDL_GetCPUType(void)
|
||||
{
|
||||
static char SDL_CPUType[13];
|
||||
|
||||
if (!SDL_CPUType[0]) {
|
||||
int i = 0;
|
||||
int a, b, c, d;
|
||||
|
||||
if (CPU_haveCPUID()) {
|
||||
cpuid(0x00000000, a, b, c, d);
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
|
||||
}
|
||||
if (!SDL_CPUType[0]) {
|
||||
SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
|
||||
}
|
||||
}
|
||||
return SDL_CPUType;
|
||||
}
|
||||
|
||||
static const char *
|
||||
SDL_GetCPUName(void)
|
||||
{
|
||||
static char SDL_CPUName[48];
|
||||
|
||||
if (!SDL_CPUName[0]) {
|
||||
int i = 0;
|
||||
int a, b, c, d;
|
||||
|
||||
if (CPU_haveCPUID()) {
|
||||
cpuid(0x80000000, a, b, c, d);
|
||||
if (a >= 0x80000004) {
|
||||
cpuid(0x80000002, a, b, c, d);
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
cpuid(0x80000003, a, b, c, d);
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
cpuid(0x80000004, a, b, c, d);
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
|
||||
}
|
||||
}
|
||||
if (!SDL_CPUName[0]) {
|
||||
SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
|
||||
}
|
||||
}
|
||||
return SDL_CPUName;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_GetCPUCacheLineSize(void)
|
||||
{
|
||||
const char *cpuType = SDL_GetCPUType();
|
||||
|
||||
if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0x00000001, a, b, c, d);
|
||||
return (((b >> 8) & 0xff) * 8);
|
||||
} else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
|
||||
int a, b, c, d;
|
||||
|
||||
cpuid(0x80000005, a, b, c, d);
|
||||
return (c & 0xff);
|
||||
} else {
|
||||
/* Just make a guess here... */
|
||||
return SDL_CACHELINE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
|
||||
|
||||
static Uint32
|
||||
SDL_GetCPUFeatures(void)
|
||||
{
|
||||
if (SDL_CPUFeatures == 0xFFFFFFFF) {
|
||||
SDL_CPUFeatures = 0;
|
||||
if (CPU_haveRDTSC()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_RDTSC;
|
||||
}
|
||||
if (CPU_haveAltiVec()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_ALTIVEC;
|
||||
}
|
||||
if (CPU_haveMMX()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_MMX;
|
||||
}
|
||||
if (CPU_have3DNow()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_3DNOW;
|
||||
}
|
||||
if (CPU_haveSSE()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_SSE;
|
||||
}
|
||||
if (CPU_haveSSE2()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_SSE2;
|
||||
}
|
||||
if (CPU_haveSSE3()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_SSE3;
|
||||
}
|
||||
if (CPU_haveSSE41()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_SSE41;
|
||||
}
|
||||
if (CPU_haveSSE42()) {
|
||||
SDL_CPUFeatures |= CPU_HAS_SSE42;
|
||||
}
|
||||
}
|
||||
return SDL_CPUFeatures;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasRDTSC(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_RDTSC) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasAltiVec(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_ALTIVEC) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasMMX(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_MMX) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_Has3DNow(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_3DNOW) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasSSE(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_SSE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasSSE2(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_SSE2) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasSSE3(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_SSE3) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasSSE41(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_SSE41) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasSSE42(void)
|
||||
{
|
||||
if (SDL_GetCPUFeatures() & CPU_HAS_SSE42) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
#ifdef TEST_MAIN
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
printf("CPU count: %d\n", SDL_GetCPUCount());
|
||||
printf("CPU type: %s\n", SDL_GetCPUType());
|
||||
printf("CPU name: %s\n", SDL_GetCPUName());
|
||||
printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
|
||||
printf("RDTSC: %d\n", SDL_HasRDTSC());
|
||||
printf("Altivec: %d\n", SDL_HasAltiVec());
|
||||
printf("MMX: %d\n", SDL_HasMMX());
|
||||
printf("3DNow: %d\n", SDL_Has3DNow());
|
||||
printf("SSE: %d\n", SDL_HasSSE());
|
||||
printf("SSE2: %d\n", SDL_HasSSE2());
|
||||
printf("SSE3: %d\n", SDL_HasSSE3());
|
||||
printf("SSE4.1: %d\n", SDL_HasSSE41());
|
||||
printf("SSE4.2: %d\n", SDL_HasSSE42());
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_MAIN */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
46
thirdparty/SDL/src/events/SDL_clipboardevents.c
vendored
Normal file
46
thirdparty/SDL/src/events/SDL_clipboardevents.c
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Clipboard event handling code for SDL */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_clipboardevents_c.h"
|
||||
|
||||
|
||||
int
|
||||
SDL_SendClipboardUpdate(void)
|
||||
{
|
||||
int posted;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_CLIPBOARDUPDATE) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_CLIPBOARDUPDATE;
|
||||
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
30
thirdparty/SDL/src/events/SDL_clipboardevents_c.h
vendored
Normal file
30
thirdparty/SDL/src/events/SDL_clipboardevents_c.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_clipboardevents_c_h
|
||||
#define _SDL_clipboardevents_c_h
|
||||
|
||||
extern int SDL_SendClipboardUpdate(void);
|
||||
|
||||
#endif /* _SDL_clipboardevents_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
531
thirdparty/SDL/src/events/SDL_events.c
vendored
Normal file
531
thirdparty/SDL/src/events/SDL_events.c
vendored
Normal file
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General event handling code for SDL */
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_syswm.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "../timer/SDL_timer_c.h"
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
#include "../joystick/SDL_joystick_c.h"
|
||||
#endif
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
/* Public data -- the event filter */
|
||||
SDL_EventFilter SDL_EventOK = NULL;
|
||||
void *SDL_EventOKParam;
|
||||
|
||||
typedef struct SDL_EventWatcher {
|
||||
SDL_EventFilter callback;
|
||||
void *userdata;
|
||||
struct SDL_EventWatcher *next;
|
||||
} SDL_EventWatcher;
|
||||
|
||||
static SDL_EventWatcher *SDL_event_watchers = NULL;
|
||||
|
||||
typedef struct {
|
||||
Uint32 bits[8];
|
||||
} SDL_DisabledEventBlock;
|
||||
|
||||
static SDL_DisabledEventBlock *SDL_disabled_events[256];
|
||||
static Uint32 SDL_userevents = SDL_USEREVENT;
|
||||
|
||||
/* Private data -- event queue */
|
||||
#define MAXEVENTS 128
|
||||
static struct
|
||||
{
|
||||
SDL_mutex *lock;
|
||||
int active;
|
||||
int head;
|
||||
int tail;
|
||||
SDL_Event event[MAXEVENTS];
|
||||
int wmmsg_next;
|
||||
struct SDL_SysWMmsg wmmsg[MAXEVENTS];
|
||||
} SDL_EventQ;
|
||||
|
||||
|
||||
static __inline__ SDL_bool
|
||||
SDL_ShouldPollJoystick()
|
||||
{
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
if (SDL_numjoysticks &&
|
||||
(!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] ||
|
||||
SDL_JoystickEventState(SDL_QUERY))) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
#endif
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Public functions */
|
||||
|
||||
void
|
||||
SDL_StopEventLoop(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (SDL_EventQ.lock) {
|
||||
SDL_DestroyMutex(SDL_EventQ.lock);
|
||||
SDL_EventQ.lock = NULL;
|
||||
}
|
||||
|
||||
/* Clean out EventQ */
|
||||
SDL_EventQ.head = 0;
|
||||
SDL_EventQ.tail = 0;
|
||||
SDL_EventQ.wmmsg_next = 0;
|
||||
|
||||
/* Clear disabled event state */
|
||||
for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
|
||||
if (SDL_disabled_events[i]) {
|
||||
SDL_free(SDL_disabled_events[i]);
|
||||
SDL_disabled_events[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
while (SDL_event_watchers) {
|
||||
SDL_EventWatcher *tmp = SDL_event_watchers;
|
||||
SDL_event_watchers = tmp->next;
|
||||
SDL_free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function (and associated calls) may be called more than once */
|
||||
int
|
||||
SDL_StartEventLoop(void)
|
||||
{
|
||||
/* Clean out the event queue */
|
||||
SDL_EventQ.lock = NULL;
|
||||
SDL_StopEventLoop();
|
||||
|
||||
/* No filter to start with, process most event types */
|
||||
SDL_EventOK = NULL;
|
||||
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
|
||||
|
||||
/* Create the lock and set ourselves active */
|
||||
#if !SDL_THREADS_DISABLED
|
||||
SDL_EventQ.lock = SDL_CreateMutex();
|
||||
if (SDL_EventQ.lock == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
#endif /* !SDL_THREADS_DISABLED */
|
||||
SDL_EventQ.active = 1;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Add an event to the event queue -- called with the queue locked */
|
||||
static int
|
||||
SDL_AddEvent(SDL_Event * event)
|
||||
{
|
||||
int tail, added;
|
||||
|
||||
tail = (SDL_EventQ.tail + 1) % MAXEVENTS;
|
||||
if (tail == SDL_EventQ.head) {
|
||||
/* Overflow, drop event */
|
||||
added = 0;
|
||||
} else {
|
||||
SDL_EventQ.event[SDL_EventQ.tail] = *event;
|
||||
if (event->type == SDL_SYSWMEVENT) {
|
||||
/* Note that it's possible to lose an event */
|
||||
int next = SDL_EventQ.wmmsg_next;
|
||||
SDL_EventQ.wmmsg[next] = *event->syswm.msg;
|
||||
SDL_EventQ.event[SDL_EventQ.tail].syswm.msg =
|
||||
&SDL_EventQ.wmmsg[next];
|
||||
SDL_EventQ.wmmsg_next = (next + 1) % MAXEVENTS;
|
||||
}
|
||||
SDL_EventQ.tail = tail;
|
||||
added = 1;
|
||||
}
|
||||
return (added);
|
||||
}
|
||||
|
||||
/* Cut an event, and return the next valid spot, or the tail */
|
||||
/* -- called with the queue locked */
|
||||
static int
|
||||
SDL_CutEvent(int spot)
|
||||
{
|
||||
if (spot == SDL_EventQ.head) {
|
||||
SDL_EventQ.head = (SDL_EventQ.head + 1) % MAXEVENTS;
|
||||
return (SDL_EventQ.head);
|
||||
} else if ((spot + 1) % MAXEVENTS == SDL_EventQ.tail) {
|
||||
SDL_EventQ.tail = spot;
|
||||
return (SDL_EventQ.tail);
|
||||
} else
|
||||
/* We cut the middle -- shift everything over */
|
||||
{
|
||||
int here, next;
|
||||
|
||||
/* This can probably be optimized with SDL_memcpy() -- careful! */
|
||||
if (--SDL_EventQ.tail < 0) {
|
||||
SDL_EventQ.tail = MAXEVENTS - 1;
|
||||
}
|
||||
for (here = spot; here != SDL_EventQ.tail; here = next) {
|
||||
next = (here + 1) % MAXEVENTS;
|
||||
SDL_EventQ.event[here] = SDL_EventQ.event[next];
|
||||
}
|
||||
return (spot);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* Lock the event queue, take a peep at it, and unlock it */
|
||||
int
|
||||
SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
|
||||
Uint32 minType, Uint32 maxType)
|
||||
{
|
||||
int i, used;
|
||||
|
||||
/* Don't look after we've quit */
|
||||
if (!SDL_EventQ.active) {
|
||||
return (-1);
|
||||
}
|
||||
/* Lock the event queue */
|
||||
used = 0;
|
||||
if (SDL_mutexP(SDL_EventQ.lock) == 0) {
|
||||
if (action == SDL_ADDEVENT) {
|
||||
for (i = 0; i < numevents; ++i) {
|
||||
used += SDL_AddEvent(&events[i]);
|
||||
}
|
||||
} else {
|
||||
SDL_Event tmpevent;
|
||||
int spot;
|
||||
|
||||
/* If 'events' is NULL, just see if they exist */
|
||||
if (events == NULL) {
|
||||
action = SDL_PEEKEVENT;
|
||||
numevents = 1;
|
||||
events = &tmpevent;
|
||||
}
|
||||
spot = SDL_EventQ.head;
|
||||
while ((used < numevents) && (spot != SDL_EventQ.tail)) {
|
||||
Uint32 type = SDL_EventQ.event[spot].type;
|
||||
if (minType <= type && type <= maxType) {
|
||||
events[used++] = SDL_EventQ.event[spot];
|
||||
if (action == SDL_GETEVENT) {
|
||||
spot = SDL_CutEvent(spot);
|
||||
} else {
|
||||
spot = (spot + 1) % MAXEVENTS;
|
||||
}
|
||||
} else {
|
||||
spot = (spot + 1) % MAXEVENTS;
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_mutexV(SDL_EventQ.lock);
|
||||
} else {
|
||||
SDL_SetError("Couldn't lock event queue");
|
||||
used = -1;
|
||||
}
|
||||
return (used);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasEvent(Uint32 type)
|
||||
{
|
||||
return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_HasEvents(Uint32 minType, Uint32 maxType)
|
||||
{
|
||||
return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FlushEvent(Uint32 type)
|
||||
{
|
||||
SDL_FlushEvents(type, type);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FlushEvents(Uint32 minType, Uint32 maxType)
|
||||
{
|
||||
/* Don't look after we've quit */
|
||||
if (!SDL_EventQ.active) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure the events are current */
|
||||
#if 0
|
||||
/* Actually, we can't do this since we might be flushing while processing
|
||||
a resize event, and calling this might trigger further resize events.
|
||||
*/
|
||||
SDL_PumpEvents();
|
||||
#endif
|
||||
|
||||
/* Lock the event queue */
|
||||
if (SDL_mutexP(SDL_EventQ.lock) == 0) {
|
||||
int spot = SDL_EventQ.head;
|
||||
while (spot != SDL_EventQ.tail) {
|
||||
Uint32 type = SDL_EventQ.event[spot].type;
|
||||
if (minType <= type && type <= maxType) {
|
||||
spot = SDL_CutEvent(spot);
|
||||
} else {
|
||||
spot = (spot + 1) % MAXEVENTS;
|
||||
}
|
||||
}
|
||||
SDL_mutexV(SDL_EventQ.lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run the system dependent event loops */
|
||||
void
|
||||
SDL_PumpEvents(void)
|
||||
{
|
||||
SDL_VideoDevice *_this = SDL_GetVideoDevice();
|
||||
|
||||
/* Get events from the video subsystem */
|
||||
if (_this) {
|
||||
_this->PumpEvents(_this);
|
||||
}
|
||||
#if !SDL_JOYSTICK_DISABLED
|
||||
/* Check for joystick state change */
|
||||
if (SDL_ShouldPollJoystick()) {
|
||||
SDL_JoystickUpdate();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Public functions */
|
||||
|
||||
int
|
||||
SDL_PollEvent(SDL_Event * event)
|
||||
{
|
||||
return SDL_WaitEventTimeout(event, 0);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_WaitEvent(SDL_Event * event)
|
||||
{
|
||||
return SDL_WaitEventTimeout(event, -1);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_WaitEventTimeout(SDL_Event * event, int timeout)
|
||||
{
|
||||
Uint32 expiration = 0;
|
||||
|
||||
if (timeout > 0)
|
||||
expiration = SDL_GetTicks() + timeout;
|
||||
|
||||
for (;;) {
|
||||
SDL_PumpEvents();
|
||||
switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
|
||||
case -1:
|
||||
return 0;
|
||||
case 1:
|
||||
return 1;
|
||||
case 0:
|
||||
if (timeout == 0) {
|
||||
/* Polling and no events, just return */
|
||||
return 0;
|
||||
}
|
||||
if (timeout > 0 && ((int) (SDL_GetTicks() - expiration) >= 0)) {
|
||||
/* Timeout expired and no events */
|
||||
return 0;
|
||||
}
|
||||
SDL_Delay(10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_PushEvent(SDL_Event * event)
|
||||
{
|
||||
SDL_EventWatcher *curr;
|
||||
|
||||
if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (curr = SDL_event_watchers; curr; curr = curr->next) {
|
||||
curr->callback(curr->userdata, event);
|
||||
}
|
||||
|
||||
if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_GestureProcessEvent(event);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_Event bitbucket;
|
||||
|
||||
/* Set filter and discard pending events */
|
||||
SDL_EventOK = filter;
|
||||
SDL_EventOKParam = userdata;
|
||||
while (SDL_PollEvent(&bitbucket) > 0);
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata)
|
||||
{
|
||||
if (filter) {
|
||||
*filter = SDL_EventOK;
|
||||
}
|
||||
if (userdata) {
|
||||
*userdata = SDL_EventOKParam;
|
||||
}
|
||||
return SDL_EventOK ? SDL_TRUE : SDL_FALSE;
|
||||
}
|
||||
|
||||
/* FIXME: This is not thread-safe yet */
|
||||
void
|
||||
SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_EventWatcher *watcher;
|
||||
|
||||
watcher = (SDL_EventWatcher *)SDL_malloc(sizeof(*watcher));
|
||||
if (!watcher) {
|
||||
/* Uh oh... */
|
||||
return;
|
||||
}
|
||||
watcher->callback = filter;
|
||||
watcher->userdata = userdata;
|
||||
watcher->next = SDL_event_watchers;
|
||||
SDL_event_watchers = watcher;
|
||||
}
|
||||
|
||||
/* FIXME: This is not thread-safe yet */
|
||||
void
|
||||
SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
SDL_EventWatcher *prev = NULL;
|
||||
SDL_EventWatcher *curr;
|
||||
|
||||
for (curr = SDL_event_watchers; curr; prev = curr, curr = curr->next) {
|
||||
if (curr->callback == filter && curr->userdata == userdata) {
|
||||
if (prev) {
|
||||
prev->next = curr->next;
|
||||
} else {
|
||||
SDL_event_watchers = curr->next;
|
||||
}
|
||||
SDL_free(curr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
|
||||
{
|
||||
if (SDL_mutexP(SDL_EventQ.lock) == 0) {
|
||||
int spot;
|
||||
|
||||
spot = SDL_EventQ.head;
|
||||
while (spot != SDL_EventQ.tail) {
|
||||
if (filter(userdata, &SDL_EventQ.event[spot])) {
|
||||
spot = (spot + 1) % MAXEVENTS;
|
||||
} else {
|
||||
spot = SDL_CutEvent(spot);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_mutexV(SDL_EventQ.lock);
|
||||
}
|
||||
|
||||
Uint8
|
||||
SDL_EventState(Uint32 type, int state)
|
||||
{
|
||||
Uint8 current_state;
|
||||
Uint8 hi = ((type >> 8) & 0xff);
|
||||
Uint8 lo = (type & 0xff);
|
||||
|
||||
if (SDL_disabled_events[hi] &&
|
||||
(SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
|
||||
current_state = SDL_DISABLE;
|
||||
} else {
|
||||
current_state = SDL_ENABLE;
|
||||
}
|
||||
|
||||
if (state != current_state)
|
||||
{
|
||||
switch (state) {
|
||||
case SDL_DISABLE:
|
||||
/* Disable this event type and discard pending events */
|
||||
if (!SDL_disabled_events[hi]) {
|
||||
SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
|
||||
if (!SDL_disabled_events[hi]) {
|
||||
/* Out of memory, nothing we can do... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
|
||||
SDL_FlushEvent(type);
|
||||
break;
|
||||
case SDL_ENABLE:
|
||||
SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
|
||||
break;
|
||||
default:
|
||||
/* Querying state... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return current_state;
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_RegisterEvents(int numevents)
|
||||
{
|
||||
Uint32 event_base;
|
||||
|
||||
if (SDL_userevents+numevents <= SDL_LASTEVENT) {
|
||||
event_base = SDL_userevents;
|
||||
SDL_userevents += numevents;
|
||||
} else {
|
||||
event_base = (Uint32)-1;
|
||||
}
|
||||
return event_base;
|
||||
}
|
||||
|
||||
/* This is a generic event handler.
|
||||
*/
|
||||
int
|
||||
SDL_SendSysWMEvent(SDL_SysWMmsg * message)
|
||||
{
|
||||
int posted;
|
||||
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
SDL_memset(&event, 0, sizeof(event));
|
||||
event.type = SDL_SYSWMEVENT;
|
||||
event.syswm.msg = message;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
/* Update internal event state */
|
||||
return (posted);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
47
thirdparty/SDL/src/events/SDL_events_c.h
vendored
Normal file
47
thirdparty/SDL/src/events/SDL_events_c.h
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Useful functions and variables from SDL_events.c */
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
#include "SDL_keyboard_c.h"
|
||||
#include "SDL_touch_c.h"
|
||||
#include "SDL_windowevents_c.h"
|
||||
#include "SDL_gesture_c.h"
|
||||
|
||||
/* Start and stop the event processing loop */
|
||||
extern int SDL_StartEventLoop(void);
|
||||
extern void SDL_StopEventLoop(void);
|
||||
extern void SDL_QuitInterrupt(void);
|
||||
|
||||
extern int SDL_SendSysWMEvent(SDL_SysWMmsg * message);
|
||||
|
||||
extern int SDL_QuitInit(void);
|
||||
extern int SDL_SendQuit(void);
|
||||
extern void SDL_QuitQuit(void);
|
||||
|
||||
/* The event filter function */
|
||||
extern SDL_EventFilter SDL_EventOK;
|
||||
extern void *SDL_EventOKParam;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
664
thirdparty/SDL/src/events/SDL_gesture.c
vendored
Normal file
664
thirdparty/SDL/src/events/SDL_gesture.c
vendored
Normal file
@@ -0,0 +1,664 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General mouse handling code for SDL */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_gesture_c.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
//TODO: Replace with malloc
|
||||
|
||||
#define MAXPATHSIZE 1024
|
||||
|
||||
|
||||
|
||||
|
||||
#define DOLLARNPOINTS 64
|
||||
#define DOLLARSIZE 256
|
||||
|
||||
#define ENABLE_DOLLAR
|
||||
|
||||
#define PHI 0.618033989
|
||||
|
||||
typedef struct {
|
||||
float x,y;
|
||||
} SDL_FloatPoint;
|
||||
|
||||
typedef struct {
|
||||
float length;
|
||||
|
||||
int numPoints;
|
||||
SDL_FloatPoint p[MAXPATHSIZE];
|
||||
} SDL_DollarPath;
|
||||
|
||||
typedef struct {
|
||||
SDL_FloatPoint path[DOLLARNPOINTS];
|
||||
unsigned long hash;
|
||||
} SDL_DollarTemplate;
|
||||
|
||||
typedef struct {
|
||||
SDL_GestureID id;
|
||||
SDL_FloatPoint res;
|
||||
SDL_FloatPoint centroid;
|
||||
SDL_DollarPath dollarPath;
|
||||
Uint16 numDownFingers;
|
||||
|
||||
int numDollarTemplates;
|
||||
SDL_DollarTemplate *dollarTemplate;
|
||||
|
||||
SDL_bool recording;
|
||||
} SDL_GestureTouch;
|
||||
|
||||
SDL_GestureTouch *SDL_gestureTouch;
|
||||
int SDL_numGestureTouches = 0;
|
||||
SDL_bool recordAll;
|
||||
|
||||
#if 0
|
||||
static void PrintPath(SDL_FloatPoint *path) {
|
||||
int i;
|
||||
printf("Path:");
|
||||
for(i=0;i<DOLLARNPOINTS;i++) {
|
||||
printf(" (%f,%f)",path[i].x,path[i].y);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
int SDL_RecordGesture(SDL_TouchID touchId) {
|
||||
int i;
|
||||
if(touchId < 0) recordAll = SDL_TRUE;
|
||||
for(i = 0;i < SDL_numGestureTouches; i++) {
|
||||
if((touchId < 0) || (SDL_gestureTouch[i].id == touchId)) {
|
||||
SDL_gestureTouch[i].recording = SDL_TRUE;
|
||||
if(touchId >= 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return (touchId < 0);
|
||||
}
|
||||
|
||||
unsigned long SDL_HashDollar(SDL_FloatPoint* points) {
|
||||
unsigned long hash = 5381;
|
||||
int i;
|
||||
for(i = 0;i < DOLLARNPOINTS; i++) {
|
||||
hash = ((hash<<5) + hash) + (unsigned long)points[i].x;
|
||||
hash = ((hash<<5) + hash) + (unsigned long)points[i].y;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src) {
|
||||
if(src == NULL) return 0;
|
||||
|
||||
|
||||
//No Longer storing the Hash, rehash on load
|
||||
//if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
|
||||
|
||||
if(SDL_RWwrite(src,templ->path,
|
||||
sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int SDL_SaveAllDollarTemplates(SDL_RWops *src) {
|
||||
int i,j,rtrn = 0;
|
||||
for(i = 0; i < SDL_numGestureTouches; i++) {
|
||||
SDL_GestureTouch* touch = &SDL_gestureTouch[i];
|
||||
for(j = 0;j < touch->numDollarTemplates; j++) {
|
||||
rtrn += SaveTemplate(&touch->dollarTemplate[i],src);
|
||||
}
|
||||
}
|
||||
return rtrn;
|
||||
}
|
||||
|
||||
int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src) {
|
||||
int i,j;
|
||||
for(i = 0; i < SDL_numGestureTouches; i++) {
|
||||
SDL_GestureTouch* touch = &SDL_gestureTouch[i];
|
||||
for(j = 0;j < touch->numDollarTemplates; j++) {
|
||||
if(touch->dollarTemplate[i].hash == gestureId) {
|
||||
return SaveTemplate(&touch->dollarTemplate[i],src);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_SetError("Unknown gestureId");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//path is an already sampled set of points
|
||||
//Returns the index of the gesture on success, or -1
|
||||
static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch,SDL_FloatPoint* path) {
|
||||
SDL_DollarTemplate* dollarTemplate;
|
||||
SDL_DollarTemplate *templ;
|
||||
int i = 0;
|
||||
if(inTouch == NULL) {
|
||||
if(SDL_numGestureTouches == 0) return -1;
|
||||
for(i = 0;i < SDL_numGestureTouches; i++) {
|
||||
inTouch = &SDL_gestureTouch[i];
|
||||
|
||||
dollarTemplate =
|
||||
(SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
|
||||
(inTouch->numDollarTemplates + 1) *
|
||||
sizeof(SDL_DollarTemplate));
|
||||
if(!dollarTemplate) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
inTouch->dollarTemplate = dollarTemplate;
|
||||
|
||||
templ =
|
||||
&inTouch->dollarTemplate[inTouch->numDollarTemplates];
|
||||
SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
|
||||
templ->hash = SDL_HashDollar(templ->path);
|
||||
inTouch->numDollarTemplates++;
|
||||
}
|
||||
return inTouch->numDollarTemplates - 1;
|
||||
} else {
|
||||
SDL_DollarTemplate* dollarTemplate =
|
||||
( SDL_DollarTemplate *)SDL_realloc(inTouch->dollarTemplate,
|
||||
(inTouch->numDollarTemplates + 1) *
|
||||
sizeof(SDL_DollarTemplate));
|
||||
if(!dollarTemplate) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
inTouch->dollarTemplate = dollarTemplate;
|
||||
|
||||
templ =
|
||||
&inTouch->dollarTemplate[inTouch->numDollarTemplates];
|
||||
SDL_memcpy(templ->path,path,DOLLARNPOINTS*sizeof(SDL_FloatPoint));
|
||||
templ->hash = SDL_HashDollar(templ->path);
|
||||
inTouch->numDollarTemplates++;
|
||||
return inTouch->numDollarTemplates - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) {
|
||||
int i,loaded = 0;
|
||||
SDL_GestureTouch *touch = NULL;
|
||||
if(src == NULL) return 0;
|
||||
if(touchId >= 0) {
|
||||
for(i = 0;i < SDL_numGestureTouches; i++)
|
||||
if(SDL_gestureTouch[i].id == touchId)
|
||||
touch = &SDL_gestureTouch[i];
|
||||
if(touch == NULL) return -1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
SDL_DollarTemplate templ;
|
||||
|
||||
if(SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) <
|
||||
DOLLARNPOINTS) break;
|
||||
|
||||
if(touchId >= 0) {
|
||||
//printf("Adding loaded gesture to 1 touch\n");
|
||||
if(SDL_AddDollarGesture(touch,templ.path)) loaded++;
|
||||
}
|
||||
else {
|
||||
//printf("Adding to: %i touches\n",SDL_numGestureTouches);
|
||||
for(i = 0;i < SDL_numGestureTouches; i++) {
|
||||
touch = &SDL_gestureTouch[i];
|
||||
//printf("Adding loaded gesture to + touches\n");
|
||||
//TODO: What if this fails?
|
||||
SDL_AddDollarGesture(touch,templ.path);
|
||||
}
|
||||
loaded++;
|
||||
}
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
|
||||
float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang) {
|
||||
// SDL_FloatPoint p[DOLLARNPOINTS];
|
||||
float dist = 0;
|
||||
SDL_FloatPoint p;
|
||||
int i;
|
||||
for(i = 0; i < DOLLARNPOINTS; i++) {
|
||||
p.x = (float)(points[i].x * SDL_cos(ang) - points[i].y * SDL_sin(ang));
|
||||
p.y = (float)(points[i].x * SDL_sin(ang) + points[i].y * SDL_cos(ang));
|
||||
dist += (float)(SDL_sqrt((p.x-templ[i].x)*(p.x-templ[i].x)+
|
||||
(p.y-templ[i].y)*(p.y-templ[i].y)));
|
||||
}
|
||||
return dist/DOLLARNPOINTS;
|
||||
|
||||
}
|
||||
|
||||
float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ) {
|
||||
//------------BEGIN DOLLAR BLACKBOX----------------//
|
||||
//-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
|
||||
//-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
|
||||
double ta = -M_PI/4;
|
||||
double tb = M_PI/4;
|
||||
double dt = M_PI/90;
|
||||
float x1 = (float)(PHI*ta + (1-PHI)*tb);
|
||||
float f1 = dollarDifference(points,templ,x1);
|
||||
float x2 = (float)((1-PHI)*ta + PHI*tb);
|
||||
float f2 = dollarDifference(points,templ,x2);
|
||||
while(SDL_fabs(ta-tb) > dt) {
|
||||
if(f1 < f2) {
|
||||
tb = x2;
|
||||
x2 = x1;
|
||||
f2 = f1;
|
||||
x1 = (float)(PHI*ta + (1-PHI)*tb);
|
||||
f1 = dollarDifference(points,templ,x1);
|
||||
}
|
||||
else {
|
||||
ta = x1;
|
||||
x1 = x2;
|
||||
f1 = f2;
|
||||
x2 = (float)((1-PHI)*ta + PHI*tb);
|
||||
f2 = dollarDifference(points,templ,x2);
|
||||
}
|
||||
}
|
||||
/*
|
||||
if(f1 <= f2)
|
||||
printf("Min angle (x1): %f\n",x1);
|
||||
else if(f1 > f2)
|
||||
printf("Min angle (x2): %f\n",x2);
|
||||
*/
|
||||
return SDL_min(f1,f2);
|
||||
}
|
||||
|
||||
//DollarPath contains raw points, plus (possibly) the calculated length
|
||||
int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points) {
|
||||
int i;
|
||||
float interval;
|
||||
float dist;
|
||||
int numPoints = 0;
|
||||
SDL_FloatPoint centroid;
|
||||
float xmin,xmax,ymin,ymax;
|
||||
float ang;
|
||||
float w,h;
|
||||
float length = path->length;
|
||||
|
||||
//Calculate length if it hasn't already been done
|
||||
if(length <= 0) {
|
||||
for(i=1;i<path->numPoints;i++) {
|
||||
float dx = path->p[i ].x -
|
||||
path->p[i-1].x;
|
||||
float dy = path->p[i ].y -
|
||||
path->p[i-1].y;
|
||||
length += (float)(SDL_sqrt(dx*dx+dy*dy));
|
||||
}
|
||||
}
|
||||
|
||||
//Resample
|
||||
interval = length/(DOLLARNPOINTS - 1);
|
||||
dist = interval;
|
||||
|
||||
centroid.x = 0;centroid.y = 0;
|
||||
|
||||
//printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
|
||||
for(i = 1;i < path->numPoints;i++) {
|
||||
float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
|
||||
(path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
|
||||
//printf("d = %f dist = %f/%f\n",d,dist,interval);
|
||||
while(dist + d > interval) {
|
||||
points[numPoints].x = path->p[i-1].x +
|
||||
((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
|
||||
points[numPoints].y = path->p[i-1].y +
|
||||
((interval-dist)/d)*(path->p[i].y-path->p[i-1].y);
|
||||
centroid.x += points[numPoints].x;
|
||||
centroid.y += points[numPoints].y;
|
||||
numPoints++;
|
||||
|
||||
dist -= interval;
|
||||
}
|
||||
dist += d;
|
||||
}
|
||||
if(numPoints < DOLLARNPOINTS-1) {
|
||||
SDL_SetError("ERROR: NumPoints = %i\n",numPoints);
|
||||
return 0;
|
||||
}
|
||||
//copy the last point
|
||||
points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
|
||||
numPoints = DOLLARNPOINTS;
|
||||
|
||||
centroid.x /= numPoints;
|
||||
centroid.y /= numPoints;
|
||||
|
||||
//printf("Centroid (%f,%f)",centroid.x,centroid.y);
|
||||
//Rotate Points so point 0 is left of centroid and solve for the bounding box
|
||||
xmin = centroid.x;
|
||||
xmax = centroid.x;
|
||||
ymin = centroid.y;
|
||||
ymax = centroid.y;
|
||||
|
||||
ang = (float)(SDL_atan2(centroid.y - points[0].y,
|
||||
centroid.x - points[0].x));
|
||||
|
||||
for(i = 0;i<numPoints;i++) {
|
||||
float px = points[i].x;
|
||||
float py = points[i].y;
|
||||
points[i].x = (float)((px - centroid.x)*SDL_cos(ang) -
|
||||
(py - centroid.y)*SDL_sin(ang) + centroid.x);
|
||||
points[i].y = (float)((px - centroid.x)*SDL_sin(ang) +
|
||||
(py - centroid.y)*SDL_cos(ang) + centroid.y);
|
||||
|
||||
|
||||
if(points[i].x < xmin) xmin = points[i].x;
|
||||
if(points[i].x > xmax) xmax = points[i].x;
|
||||
if(points[i].y < ymin) ymin = points[i].y;
|
||||
if(points[i].y > ymax) ymax = points[i].y;
|
||||
}
|
||||
|
||||
//Scale points to DOLLARSIZE, and translate to the origin
|
||||
w = xmax-xmin;
|
||||
h = ymax-ymin;
|
||||
|
||||
for(i=0;i<numPoints;i++) {
|
||||
points[i].x = (points[i].x - centroid.x)*DOLLARSIZE/w;
|
||||
points[i].y = (points[i].y - centroid.y)*DOLLARSIZE/h;
|
||||
}
|
||||
return numPoints;
|
||||
}
|
||||
|
||||
float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_GestureTouch* touch) {
|
||||
|
||||
SDL_FloatPoint points[DOLLARNPOINTS];
|
||||
int numPoints = dollarNormalize(path,points);
|
||||
int i;
|
||||
float bestDiff = 10000;
|
||||
|
||||
//PrintPath(points);
|
||||
*bestTempl = -1;
|
||||
for(i = 0;i < touch->numDollarTemplates;i++) {
|
||||
float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
|
||||
if(diff < bestDiff) {bestDiff = diff; *bestTempl = i;}
|
||||
}
|
||||
return bestDiff;
|
||||
}
|
||||
|
||||
int SDL_GestureAddTouch(SDL_Touch* touch) {
|
||||
SDL_GestureTouch *gestureTouch = (SDL_GestureTouch *)SDL_realloc(SDL_gestureTouch,
|
||||
(SDL_numGestureTouches + 1) *
|
||||
sizeof(SDL_GestureTouch));
|
||||
|
||||
if(!gestureTouch) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_gestureTouch = gestureTouch;
|
||||
|
||||
SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
|
||||
SDL_gestureTouch[SDL_numGestureTouches].res.y = touch->yres;
|
||||
SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0;
|
||||
|
||||
SDL_gestureTouch[SDL_numGestureTouches].res.x = touch->xres;
|
||||
SDL_gestureTouch[SDL_numGestureTouches].id = touch->id;
|
||||
|
||||
SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0;
|
||||
|
||||
SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE;
|
||||
|
||||
SDL_numGestureTouches++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SDL_GestureRemoveTouch(SDL_TouchID id) {
|
||||
int i;
|
||||
for (i = 0; i < SDL_numGestureTouches; i++) {
|
||||
if (SDL_gestureTouch[i].id == id) {
|
||||
SDL_numGestureTouches--;
|
||||
SDL_memcpy(&SDL_gestureTouch[i], &SDL_gestureTouch[SDL_numGestureTouches], sizeof(SDL_gestureTouch[i]));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id) {
|
||||
int i;
|
||||
for(i = 0;i < SDL_numGestureTouches; i++) {
|
||||
//printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
|
||||
if(SDL_gestureTouch[i].id == id) return &SDL_gestureTouch[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SDL_SendGestureMulti(SDL_GestureTouch* touch,float dTheta,float dDist) {
|
||||
SDL_Event event;
|
||||
event.mgesture.type = SDL_MULTIGESTURE;
|
||||
event.mgesture.touchId = touch->id;
|
||||
event.mgesture.x = touch->centroid.x;
|
||||
event.mgesture.y = touch->centroid.y;
|
||||
event.mgesture.dTheta = dTheta;
|
||||
event.mgesture.dDist = dDist;
|
||||
event.mgesture.numFingers = touch->numDownFingers;
|
||||
return SDL_PushEvent(&event) > 0;
|
||||
}
|
||||
|
||||
int SDL_SendGestureDollar(SDL_GestureTouch* touch,
|
||||
SDL_GestureID gestureId,float error) {
|
||||
SDL_Event event;
|
||||
event.dgesture.type = SDL_DOLLARGESTURE;
|
||||
event.dgesture.touchId = touch->id;
|
||||
/*
|
||||
//TODO: Add this to give location of gesture?
|
||||
event.mgesture.x = touch->centroid.x;
|
||||
event.mgesture.y = touch->centroid.y;
|
||||
*/
|
||||
event.dgesture.gestureId = gestureId;
|
||||
event.dgesture.error = error;
|
||||
//A finger came up to trigger this event.
|
||||
event.dgesture.numFingers = touch->numDownFingers + 1;
|
||||
return SDL_PushEvent(&event) > 0;
|
||||
}
|
||||
|
||||
|
||||
int SDL_SendDollarRecord(SDL_GestureTouch* touch,SDL_GestureID gestureId) {
|
||||
SDL_Event event;
|
||||
event.dgesture.type = SDL_DOLLARRECORD;
|
||||
event.dgesture.touchId = touch->id;
|
||||
event.dgesture.gestureId = gestureId;
|
||||
return SDL_PushEvent(&event) > 0;
|
||||
}
|
||||
|
||||
|
||||
void SDL_GestureProcessEvent(SDL_Event* event)
|
||||
{
|
||||
float x,y;
|
||||
SDL_FloatPoint path[DOLLARNPOINTS];
|
||||
int index;
|
||||
int i;
|
||||
float pathDx, pathDy;
|
||||
SDL_FloatPoint lastP;
|
||||
SDL_FloatPoint lastCentroid;
|
||||
float lDist;
|
||||
float Dist;
|
||||
float dtheta;
|
||||
float dDist;
|
||||
|
||||
if(event->type == SDL_FINGERMOTION ||
|
||||
event->type == SDL_FINGERDOWN ||
|
||||
event->type == SDL_FINGERUP) {
|
||||
SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
|
||||
|
||||
//Shouldn't be possible
|
||||
if(inTouch == NULL) return;
|
||||
|
||||
//printf("@ (%i,%i) with res: (%i,%i)\n",(int)event->tfinger.x,
|
||||
// (int)event->tfinger.y,
|
||||
// (int)inTouch->res.x,(int)inTouch->res.y);
|
||||
|
||||
|
||||
x = ((float)event->tfinger.x)/(float)inTouch->res.x;
|
||||
y = ((float)event->tfinger.y)/(float)inTouch->res.y;
|
||||
|
||||
|
||||
//Finger Up
|
||||
if(event->type == SDL_FINGERUP) {
|
||||
inTouch->numDownFingers--;
|
||||
|
||||
#ifdef ENABLE_DOLLAR
|
||||
if(inTouch->recording) {
|
||||
inTouch->recording = SDL_FALSE;
|
||||
dollarNormalize(&inTouch->dollarPath,path);
|
||||
//PrintPath(path);
|
||||
if(recordAll) {
|
||||
index = SDL_AddDollarGesture(NULL,path);
|
||||
for(i = 0;i < SDL_numGestureTouches; i++)
|
||||
SDL_gestureTouch[i].recording = SDL_FALSE;
|
||||
}
|
||||
else {
|
||||
index = SDL_AddDollarGesture(inTouch,path);
|
||||
}
|
||||
|
||||
if(index >= 0) {
|
||||
SDL_SendDollarRecord(inTouch,inTouch->dollarTemplate[index].hash);
|
||||
}
|
||||
else {
|
||||
SDL_SendDollarRecord(inTouch,-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int bestTempl;
|
||||
float error;
|
||||
error = dollarRecognize(&inTouch->dollarPath,
|
||||
&bestTempl,inTouch);
|
||||
if(bestTempl >= 0){
|
||||
//Send Event
|
||||
unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
|
||||
SDL_SendGestureDollar(inTouch,gestureId,error);
|
||||
//printf ("%s\n",);("Dollar error: %f\n",error);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
|
||||
if(inTouch->numDownFingers > 0) {
|
||||
inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
|
||||
x)/inTouch->numDownFingers;
|
||||
inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers+1)-
|
||||
y)/inTouch->numDownFingers;
|
||||
}
|
||||
}
|
||||
else if(event->type == SDL_FINGERMOTION) {
|
||||
float dx = ((float)event->tfinger.dx)/(float)inTouch->res.x;
|
||||
float dy = ((float)event->tfinger.dy)/(float)inTouch->res.y;
|
||||
//printf("dx,dy: (%f,%f)\n",dx,dy);
|
||||
#ifdef ENABLE_DOLLAR
|
||||
SDL_DollarPath* path = &inTouch->dollarPath;
|
||||
if(path->numPoints < MAXPATHSIZE) {
|
||||
path->p[path->numPoints].x = inTouch->centroid.x;
|
||||
path->p[path->numPoints].y = inTouch->centroid.y;
|
||||
pathDx =
|
||||
(path->p[path->numPoints].x-path->p[path->numPoints-1].x);
|
||||
pathDy =
|
||||
(path->p[path->numPoints].y-path->p[path->numPoints-1].y);
|
||||
path->length += (float)SDL_sqrt(pathDx*pathDx + pathDy*pathDy);
|
||||
path->numPoints++;
|
||||
}
|
||||
#endif
|
||||
lastP.x = x - dx;
|
||||
lastP.y = y - dy;
|
||||
lastCentroid = inTouch->centroid;
|
||||
|
||||
inTouch->centroid.x += dx/inTouch->numDownFingers;
|
||||
inTouch->centroid.y += dy/inTouch->numDownFingers;
|
||||
//printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
|
||||
if(inTouch->numDownFingers > 1) {
|
||||
SDL_FloatPoint lv; //Vector from centroid to last x,y position
|
||||
SDL_FloatPoint v; //Vector from centroid to current x,y position
|
||||
//lv = inTouch->gestureLast[j].cv;
|
||||
lv.x = lastP.x - lastCentroid.x;
|
||||
lv.y = lastP.y - lastCentroid.y;
|
||||
lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
|
||||
//printf("lDist = %f\n",lDist);
|
||||
v.x = x - inTouch->centroid.x;
|
||||
v.y = y - inTouch->centroid.y;
|
||||
//inTouch->gestureLast[j].cv = v;
|
||||
Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
|
||||
// SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
|
||||
|
||||
//Normalize Vectors to simplify angle calculation
|
||||
lv.x/=lDist;
|
||||
lv.y/=lDist;
|
||||
v.x/=Dist;
|
||||
v.y/=Dist;
|
||||
dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
|
||||
|
||||
dDist = (Dist - lDist);
|
||||
if(lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
|
||||
|
||||
//inTouch->gestureLast[j].dDist = dDist;
|
||||
//inTouch->gestureLast[j].dtheta = dtheta;
|
||||
|
||||
//printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
|
||||
//gdtheta = gdtheta*.9 + dtheta*.1;
|
||||
//gdDist = gdDist*.9 + dDist*.1
|
||||
//knob.r += dDist/numDownFingers;
|
||||
//knob.ang += dtheta;
|
||||
//printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
|
||||
//printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
|
||||
SDL_SendGestureMulti(inTouch,dtheta,dDist);
|
||||
}
|
||||
else {
|
||||
//inTouch->gestureLast[j].dDist = 0;
|
||||
//inTouch->gestureLast[j].dtheta = 0;
|
||||
//inTouch->gestureLast[j].cv.x = 0;
|
||||
//inTouch->gestureLast[j].cv.y = 0;
|
||||
}
|
||||
//inTouch->gestureLast[j].f.p.x = x;
|
||||
//inTouch->gestureLast[j].f.p.y = y;
|
||||
//break;
|
||||
//pressure?
|
||||
}
|
||||
|
||||
if(event->type == SDL_FINGERDOWN) {
|
||||
|
||||
inTouch->numDownFingers++;
|
||||
inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers - 1)+
|
||||
x)/inTouch->numDownFingers;
|
||||
inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
|
||||
y)/inTouch->numDownFingers;
|
||||
//printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
|
||||
// inTouch->centroid.x,inTouch->centroid.y);
|
||||
|
||||
#ifdef ENABLE_DOLLAR
|
||||
inTouch->dollarPath.length = 0;
|
||||
inTouch->dollarPath.p[0].x = x;
|
||||
inTouch->dollarPath.p[0].y = y;
|
||||
inTouch->dollarPath.numPoints = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
34
thirdparty/SDL/src/events/SDL_gesture_c.h
vendored
Normal file
34
thirdparty/SDL/src/events/SDL_gesture_c.h
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_gesture_c_h
|
||||
#define _SDL_gesture_c_h
|
||||
|
||||
extern void SDL_GestureProcessEvent(SDL_Event* event);
|
||||
|
||||
extern int SDL_RecordGesture(SDL_TouchID touchId);
|
||||
|
||||
extern int SDL_GestureAddTouch(SDL_Touch* touch);
|
||||
|
||||
#endif /* _SDL_gesture_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
922
thirdparty/SDL/src/events/SDL_keyboard.c
vendored
Normal file
922
thirdparty/SDL/src/events/SDL_keyboard.c
vendored
Normal file
@@ -0,0 +1,922 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General keyboard handling code for SDL */
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
|
||||
/* Global keyboard information */
|
||||
|
||||
typedef struct SDL_Keyboard SDL_Keyboard;
|
||||
|
||||
struct SDL_Keyboard
|
||||
{
|
||||
/* Data common to all keyboards */
|
||||
SDL_Window *focus;
|
||||
Uint16 modstate;
|
||||
Uint8 keystate[SDL_NUM_SCANCODES];
|
||||
SDL_Keycode keymap[SDL_NUM_SCANCODES];
|
||||
};
|
||||
|
||||
static SDL_Keyboard SDL_keyboard;
|
||||
|
||||
static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = {
|
||||
0, 0, 0, 0,
|
||||
'a',
|
||||
'b',
|
||||
'c',
|
||||
'd',
|
||||
'e',
|
||||
'f',
|
||||
'g',
|
||||
'h',
|
||||
'i',
|
||||
'j',
|
||||
'k',
|
||||
'l',
|
||||
'm',
|
||||
'n',
|
||||
'o',
|
||||
'p',
|
||||
'q',
|
||||
'r',
|
||||
's',
|
||||
't',
|
||||
'u',
|
||||
'v',
|
||||
'w',
|
||||
'x',
|
||||
'y',
|
||||
'z',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'0',
|
||||
SDLK_RETURN,
|
||||
SDLK_ESCAPE,
|
||||
SDLK_BACKSPACE,
|
||||
SDLK_TAB,
|
||||
SDLK_SPACE,
|
||||
'-',
|
||||
'=',
|
||||
'[',
|
||||
']',
|
||||
'\\',
|
||||
'#',
|
||||
';',
|
||||
'\'',
|
||||
'`',
|
||||
',',
|
||||
'.',
|
||||
'/',
|
||||
SDLK_CAPSLOCK,
|
||||
SDLK_F1,
|
||||
SDLK_F2,
|
||||
SDLK_F3,
|
||||
SDLK_F4,
|
||||
SDLK_F5,
|
||||
SDLK_F6,
|
||||
SDLK_F7,
|
||||
SDLK_F8,
|
||||
SDLK_F9,
|
||||
SDLK_F10,
|
||||
SDLK_F11,
|
||||
SDLK_F12,
|
||||
SDLK_PRINTSCREEN,
|
||||
SDLK_SCROLLLOCK,
|
||||
SDLK_PAUSE,
|
||||
SDLK_INSERT,
|
||||
SDLK_HOME,
|
||||
SDLK_PAGEUP,
|
||||
SDLK_DELETE,
|
||||
SDLK_END,
|
||||
SDLK_PAGEDOWN,
|
||||
SDLK_RIGHT,
|
||||
SDLK_LEFT,
|
||||
SDLK_DOWN,
|
||||
SDLK_UP,
|
||||
SDLK_NUMLOCKCLEAR,
|
||||
SDLK_KP_DIVIDE,
|
||||
SDLK_KP_MULTIPLY,
|
||||
SDLK_KP_MINUS,
|
||||
SDLK_KP_PLUS,
|
||||
SDLK_KP_ENTER,
|
||||
SDLK_KP_1,
|
||||
SDLK_KP_2,
|
||||
SDLK_KP_3,
|
||||
SDLK_KP_4,
|
||||
SDLK_KP_5,
|
||||
SDLK_KP_6,
|
||||
SDLK_KP_7,
|
||||
SDLK_KP_8,
|
||||
SDLK_KP_9,
|
||||
SDLK_KP_0,
|
||||
SDLK_KP_PERIOD,
|
||||
0,
|
||||
SDLK_APPLICATION,
|
||||
SDLK_POWER,
|
||||
SDLK_KP_EQUALS,
|
||||
SDLK_F13,
|
||||
SDLK_F14,
|
||||
SDLK_F15,
|
||||
SDLK_F16,
|
||||
SDLK_F17,
|
||||
SDLK_F18,
|
||||
SDLK_F19,
|
||||
SDLK_F20,
|
||||
SDLK_F21,
|
||||
SDLK_F22,
|
||||
SDLK_F23,
|
||||
SDLK_F24,
|
||||
SDLK_EXECUTE,
|
||||
SDLK_HELP,
|
||||
SDLK_MENU,
|
||||
SDLK_SELECT,
|
||||
SDLK_STOP,
|
||||
SDLK_AGAIN,
|
||||
SDLK_UNDO,
|
||||
SDLK_CUT,
|
||||
SDLK_COPY,
|
||||
SDLK_PASTE,
|
||||
SDLK_FIND,
|
||||
SDLK_MUTE,
|
||||
SDLK_VOLUMEUP,
|
||||
SDLK_VOLUMEDOWN,
|
||||
0, 0, 0,
|
||||
SDLK_KP_COMMA,
|
||||
SDLK_KP_EQUALSAS400,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
SDLK_ALTERASE,
|
||||
SDLK_SYSREQ,
|
||||
SDLK_CANCEL,
|
||||
SDLK_CLEAR,
|
||||
SDLK_PRIOR,
|
||||
SDLK_RETURN2,
|
||||
SDLK_SEPARATOR,
|
||||
SDLK_OUT,
|
||||
SDLK_OPER,
|
||||
SDLK_CLEARAGAIN,
|
||||
SDLK_CRSEL,
|
||||
SDLK_EXSEL,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
SDLK_KP_00,
|
||||
SDLK_KP_000,
|
||||
SDLK_THOUSANDSSEPARATOR,
|
||||
SDLK_DECIMALSEPARATOR,
|
||||
SDLK_CURRENCYUNIT,
|
||||
SDLK_CURRENCYSUBUNIT,
|
||||
SDLK_KP_LEFTPAREN,
|
||||
SDLK_KP_RIGHTPAREN,
|
||||
SDLK_KP_LEFTBRACE,
|
||||
SDLK_KP_RIGHTBRACE,
|
||||
SDLK_KP_TAB,
|
||||
SDLK_KP_BACKSPACE,
|
||||
SDLK_KP_A,
|
||||
SDLK_KP_B,
|
||||
SDLK_KP_C,
|
||||
SDLK_KP_D,
|
||||
SDLK_KP_E,
|
||||
SDLK_KP_F,
|
||||
SDLK_KP_XOR,
|
||||
SDLK_KP_POWER,
|
||||
SDLK_KP_PERCENT,
|
||||
SDLK_KP_LESS,
|
||||
SDLK_KP_GREATER,
|
||||
SDLK_KP_AMPERSAND,
|
||||
SDLK_KP_DBLAMPERSAND,
|
||||
SDLK_KP_VERTICALBAR,
|
||||
SDLK_KP_DBLVERTICALBAR,
|
||||
SDLK_KP_COLON,
|
||||
SDLK_KP_HASH,
|
||||
SDLK_KP_SPACE,
|
||||
SDLK_KP_AT,
|
||||
SDLK_KP_EXCLAM,
|
||||
SDLK_KP_MEMSTORE,
|
||||
SDLK_KP_MEMRECALL,
|
||||
SDLK_KP_MEMCLEAR,
|
||||
SDLK_KP_MEMADD,
|
||||
SDLK_KP_MEMSUBTRACT,
|
||||
SDLK_KP_MEMMULTIPLY,
|
||||
SDLK_KP_MEMDIVIDE,
|
||||
SDLK_KP_PLUSMINUS,
|
||||
SDLK_KP_CLEAR,
|
||||
SDLK_KP_CLEARENTRY,
|
||||
SDLK_KP_BINARY,
|
||||
SDLK_KP_OCTAL,
|
||||
SDLK_KP_DECIMAL,
|
||||
SDLK_KP_HEXADECIMAL,
|
||||
0, 0,
|
||||
SDLK_LCTRL,
|
||||
SDLK_LSHIFT,
|
||||
SDLK_LALT,
|
||||
SDLK_LGUI,
|
||||
SDLK_RCTRL,
|
||||
SDLK_RSHIFT,
|
||||
SDLK_RALT,
|
||||
SDLK_RGUI,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
SDLK_MODE,
|
||||
SDLK_AUDIONEXT,
|
||||
SDLK_AUDIOPREV,
|
||||
SDLK_AUDIOSTOP,
|
||||
SDLK_AUDIOPLAY,
|
||||
SDLK_AUDIOMUTE,
|
||||
SDLK_MEDIASELECT,
|
||||
SDLK_WWW,
|
||||
SDLK_MAIL,
|
||||
SDLK_CALCULATOR,
|
||||
SDLK_COMPUTER,
|
||||
SDLK_AC_SEARCH,
|
||||
SDLK_AC_HOME,
|
||||
SDLK_AC_BACK,
|
||||
SDLK_AC_FORWARD,
|
||||
SDLK_AC_STOP,
|
||||
SDLK_AC_REFRESH,
|
||||
SDLK_AC_BOOKMARKS,
|
||||
SDLK_BRIGHTNESSDOWN,
|
||||
SDLK_BRIGHTNESSUP,
|
||||
SDLK_DISPLAYSWITCH,
|
||||
SDLK_KBDILLUMTOGGLE,
|
||||
SDLK_KBDILLUMDOWN,
|
||||
SDLK_KBDILLUMUP,
|
||||
SDLK_EJECT,
|
||||
SDLK_SLEEP,
|
||||
};
|
||||
|
||||
static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
|
||||
NULL, NULL, NULL, NULL,
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"0",
|
||||
"Return",
|
||||
"Escape",
|
||||
"Backspace",
|
||||
"Tab",
|
||||
"Space",
|
||||
"-",
|
||||
"=",
|
||||
"[",
|
||||
"]",
|
||||
"\\",
|
||||
"#",
|
||||
";",
|
||||
"'",
|
||||
"`",
|
||||
",",
|
||||
".",
|
||||
"/",
|
||||
"CapsLock",
|
||||
"F1",
|
||||
"F2",
|
||||
"F3",
|
||||
"F4",
|
||||
"F5",
|
||||
"F6",
|
||||
"F7",
|
||||
"F8",
|
||||
"F9",
|
||||
"F10",
|
||||
"F11",
|
||||
"F12",
|
||||
"PrintScreen",
|
||||
"ScrollLock",
|
||||
"Pause",
|
||||
"Insert",
|
||||
"Home",
|
||||
"PageUp",
|
||||
"Delete",
|
||||
"End",
|
||||
"PageDown",
|
||||
"Right",
|
||||
"Left",
|
||||
"Down",
|
||||
"Up",
|
||||
"Numlock",
|
||||
"Keypad /",
|
||||
"Keypad *",
|
||||
"Keypad -",
|
||||
"Keypad +",
|
||||
"Keypad Enter",
|
||||
"Keypad 1",
|
||||
"Keypad 2",
|
||||
"Keypad 3",
|
||||
"Keypad 4",
|
||||
"Keypad 5",
|
||||
"Keypad 6",
|
||||
"Keypad 7",
|
||||
"Keypad 8",
|
||||
"Keypad 9",
|
||||
"Keypad 0",
|
||||
"Keypad .",
|
||||
NULL,
|
||||
"Application",
|
||||
"Power",
|
||||
"Keypad =",
|
||||
"F13",
|
||||
"F14",
|
||||
"F15",
|
||||
"F16",
|
||||
"F17",
|
||||
"F18",
|
||||
"F19",
|
||||
"F20",
|
||||
"F21",
|
||||
"F22",
|
||||
"F23",
|
||||
"F24",
|
||||
"Execute",
|
||||
"Help",
|
||||
"Menu",
|
||||
"Select",
|
||||
"Stop",
|
||||
"Again",
|
||||
"Undo",
|
||||
"Cut",
|
||||
"Copy",
|
||||
"Paste",
|
||||
"Find",
|
||||
"Mute",
|
||||
"VolumeUp",
|
||||
"VolumeDown",
|
||||
NULL, NULL, NULL,
|
||||
"Keypad ,",
|
||||
"Keypad = (AS400)",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
"AltErase",
|
||||
"SysReq",
|
||||
"Cancel",
|
||||
"Clear",
|
||||
"Prior",
|
||||
"Return",
|
||||
"Separator",
|
||||
"Out",
|
||||
"Oper",
|
||||
"Clear / Again",
|
||||
"CrSel",
|
||||
"ExSel",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
"Keypad 00",
|
||||
"Keypad 000",
|
||||
"ThousandsSeparator",
|
||||
"DecimalSeparator",
|
||||
"CurrencyUnit",
|
||||
"CurrencySubUnit",
|
||||
"Keypad (",
|
||||
"Keypad )",
|
||||
"Keypad {",
|
||||
"Keypad }",
|
||||
"Keypad Tab",
|
||||
"Keypad Backspace",
|
||||
"Keypad A",
|
||||
"Keypad B",
|
||||
"Keypad C",
|
||||
"Keypad D",
|
||||
"Keypad E",
|
||||
"Keypad F",
|
||||
"Keypad XOR",
|
||||
"Keypad ^",
|
||||
"Keypad %",
|
||||
"Keypad <",
|
||||
"Keypad >",
|
||||
"Keypad &",
|
||||
"Keypad &&",
|
||||
"Keypad |",
|
||||
"Keypad ||",
|
||||
"Keypad :",
|
||||
"Keypad #",
|
||||
"Keypad Space",
|
||||
"Keypad @",
|
||||
"Keypad !",
|
||||
"Keypad MemStore",
|
||||
"Keypad MemRecall",
|
||||
"Keypad MemClear",
|
||||
"Keypad MemAdd",
|
||||
"Keypad MemSubtract",
|
||||
"Keypad MemMultiply",
|
||||
"Keypad MemDivide",
|
||||
"Keypad +/-",
|
||||
"Keypad Clear",
|
||||
"Keypad ClearEntry",
|
||||
"Keypad Binary",
|
||||
"Keypad Octal",
|
||||
"Keypad Decimal",
|
||||
"Keypad Hexadecimal",
|
||||
NULL, NULL,
|
||||
"Left Ctrl",
|
||||
"Left Shift",
|
||||
"Left Alt",
|
||||
"Left GUI",
|
||||
"Right Ctrl",
|
||||
"Right Shift",
|
||||
"Right Alt",
|
||||
"Right GUI",
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
"ModeSwitch",
|
||||
"AudioNext",
|
||||
"AudioPrev",
|
||||
"AudioStop",
|
||||
"AudioPlay",
|
||||
"AudioMute",
|
||||
"MediaSelect",
|
||||
"WWW",
|
||||
"Mail",
|
||||
"Calculator",
|
||||
"Computer",
|
||||
"AC Search",
|
||||
"AC Home",
|
||||
"AC Back",
|
||||
"AC Forward",
|
||||
"AC Stop",
|
||||
"AC Refresh",
|
||||
"AC Bookmarks",
|
||||
"BrightnessDown",
|
||||
"BrightnessUp",
|
||||
"DisplaySwitch",
|
||||
"KBDIllumToggle",
|
||||
"KBDIllumDown",
|
||||
"KBDIllumUp",
|
||||
"Eject",
|
||||
"Sleep",
|
||||
};
|
||||
|
||||
/* Taken from SDL_iconv() */
|
||||
static char *
|
||||
SDL_UCS4ToUTF8(Uint32 ch, char *dst)
|
||||
{
|
||||
Uint8 *p = (Uint8 *) dst;
|
||||
if (ch <= 0x7F) {
|
||||
*p = (Uint8) ch;
|
||||
++dst;
|
||||
} else if (ch <= 0x7FF) {
|
||||
p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
|
||||
p[1] = 0x80 | (Uint8) (ch & 0x3F);
|
||||
dst += 2;
|
||||
} else if (ch <= 0xFFFF) {
|
||||
p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
|
||||
p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8) (ch & 0x3F);
|
||||
dst += 3;
|
||||
} else if (ch <= 0x1FFFFF) {
|
||||
p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
|
||||
p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
||||
p[3] = 0x80 | (Uint8) (ch & 0x3F);
|
||||
dst += 4;
|
||||
} else if (ch <= 0x3FFFFFF) {
|
||||
p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
|
||||
p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
|
||||
p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
||||
p[4] = 0x80 | (Uint8) (ch & 0x3F);
|
||||
dst += 5;
|
||||
} else {
|
||||
p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
|
||||
p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
|
||||
p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
|
||||
p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
|
||||
p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
|
||||
p[5] = 0x80 | (Uint8) (ch & 0x3F);
|
||||
dst += 6;
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
||||
/* Public functions */
|
||||
int
|
||||
SDL_KeyboardInit(void)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
/* Set the default keymap */
|
||||
SDL_memcpy(keyboard->keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_ResetKeyboard(void)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
SDL_Scancode scancode;
|
||||
|
||||
for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
|
||||
if (keyboard->keystate[scancode] == SDL_PRESSED) {
|
||||
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SDL_GetDefaultKeymap(SDL_Keycode * keymap)
|
||||
{
|
||||
SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetKeymap(int start, SDL_Keycode * keys, int length)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
if (start < 0 || start + length > SDL_NUM_SCANCODES) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
|
||||
{
|
||||
SDL_scancode_names[scancode] = name;
|
||||
}
|
||||
|
||||
SDL_Window *
|
||||
SDL_GetKeyboardFocus(void)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
return keyboard->focus;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetKeyboardFocus(SDL_Window * window)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
/* See if the current window has lost focus */
|
||||
if (keyboard->focus && keyboard->focus != window) {
|
||||
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
|
||||
0, 0);
|
||||
|
||||
/* Ensures IME compositions are committed */
|
||||
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
|
||||
SDL_VideoDevice *video = SDL_GetVideoDevice();
|
||||
if (video && video->StopTextInput) {
|
||||
video->StopTextInput(video);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keyboard->focus = window;
|
||||
|
||||
if (keyboard->focus) {
|
||||
SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
|
||||
0, 0);
|
||||
|
||||
if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
|
||||
SDL_VideoDevice *video = SDL_GetVideoDevice();
|
||||
if (video && video->StartTextInput) {
|
||||
video->StartTextInput(video);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
int posted;
|
||||
Uint16 modstate;
|
||||
Uint32 type;
|
||||
Uint8 repeat;
|
||||
|
||||
if (!scancode) {
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
|
||||
state == SDL_PRESSED ? "pressed" : "released");
|
||||
#endif
|
||||
if (state == SDL_PRESSED) {
|
||||
modstate = keyboard->modstate;
|
||||
switch (scancode) {
|
||||
case SDL_SCANCODE_NUMLOCKCLEAR:
|
||||
keyboard->modstate ^= KMOD_NUM;
|
||||
break;
|
||||
case SDL_SCANCODE_CAPSLOCK:
|
||||
keyboard->modstate ^= KMOD_CAPS;
|
||||
break;
|
||||
case SDL_SCANCODE_LCTRL:
|
||||
keyboard->modstate |= KMOD_LCTRL;
|
||||
break;
|
||||
case SDL_SCANCODE_RCTRL:
|
||||
keyboard->modstate |= KMOD_RCTRL;
|
||||
break;
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
keyboard->modstate |= KMOD_LSHIFT;
|
||||
break;
|
||||
case SDL_SCANCODE_RSHIFT:
|
||||
keyboard->modstate |= KMOD_RSHIFT;
|
||||
break;
|
||||
case SDL_SCANCODE_LALT:
|
||||
keyboard->modstate |= KMOD_LALT;
|
||||
break;
|
||||
case SDL_SCANCODE_RALT:
|
||||
keyboard->modstate |= KMOD_RALT;
|
||||
break;
|
||||
case SDL_SCANCODE_LGUI:
|
||||
keyboard->modstate |= KMOD_LGUI;
|
||||
break;
|
||||
case SDL_SCANCODE_RGUI:
|
||||
keyboard->modstate |= KMOD_RGUI;
|
||||
break;
|
||||
case SDL_SCANCODE_MODE:
|
||||
keyboard->modstate |= KMOD_MODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (scancode) {
|
||||
case SDL_SCANCODE_NUMLOCKCLEAR:
|
||||
case SDL_SCANCODE_CAPSLOCK:
|
||||
break;
|
||||
case SDL_SCANCODE_LCTRL:
|
||||
keyboard->modstate &= ~KMOD_LCTRL;
|
||||
break;
|
||||
case SDL_SCANCODE_RCTRL:
|
||||
keyboard->modstate &= ~KMOD_RCTRL;
|
||||
break;
|
||||
case SDL_SCANCODE_LSHIFT:
|
||||
keyboard->modstate &= ~KMOD_LSHIFT;
|
||||
break;
|
||||
case SDL_SCANCODE_RSHIFT:
|
||||
keyboard->modstate &= ~KMOD_RSHIFT;
|
||||
break;
|
||||
case SDL_SCANCODE_LALT:
|
||||
keyboard->modstate &= ~KMOD_LALT;
|
||||
break;
|
||||
case SDL_SCANCODE_RALT:
|
||||
keyboard->modstate &= ~KMOD_RALT;
|
||||
break;
|
||||
case SDL_SCANCODE_LGUI:
|
||||
keyboard->modstate &= ~KMOD_LGUI;
|
||||
break;
|
||||
case SDL_SCANCODE_RGUI:
|
||||
keyboard->modstate &= ~KMOD_RGUI;
|
||||
break;
|
||||
case SDL_SCANCODE_MODE:
|
||||
keyboard->modstate &= ~KMOD_MODE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
modstate = keyboard->modstate;
|
||||
}
|
||||
|
||||
/* Figure out what type of event this is */
|
||||
switch (state) {
|
||||
case SDL_PRESSED:
|
||||
type = SDL_KEYDOWN;
|
||||
break;
|
||||
case SDL_RELEASED:
|
||||
type = SDL_KEYUP;
|
||||
break;
|
||||
default:
|
||||
/* Invalid state -- bail */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Drop events that don't change state */
|
||||
repeat = (state && keyboard->keystate[scancode]);
|
||||
if (keyboard->keystate[scancode] == state && !repeat) {
|
||||
#if 0
|
||||
printf("Keyboard event didn't change state - dropped!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal keyboard state */
|
||||
keyboard->keystate[scancode] = state;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(type) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.key.type = type;
|
||||
event.key.state = state;
|
||||
event.key.repeat = repeat;
|
||||
event.key.keysym.scancode = scancode;
|
||||
event.key.keysym.sym = keyboard->keymap[scancode];
|
||||
event.key.keysym.mod = modstate;
|
||||
event.key.keysym.unicode = 0;
|
||||
event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendKeyboardText(const char *text)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
int posted;
|
||||
|
||||
/* Don't post text events for unprintable characters */
|
||||
if ((unsigned char)*text < ' ' || *text == 127) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.text.type = SDL_TEXTINPUT;
|
||||
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
||||
SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendEditingText(const char *text, int start, int length)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
int posted;
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.edit.type = SDL_TEXTEDITING;
|
||||
event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
|
||||
event.edit.start = start;
|
||||
event.edit.length = length;
|
||||
SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_KeyboardQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
Uint8 *
|
||||
SDL_GetKeyboardState(int *numkeys)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
if (numkeys != (int *) 0) {
|
||||
*numkeys = SDL_NUM_SCANCODES;
|
||||
}
|
||||
return keyboard->keystate;
|
||||
}
|
||||
|
||||
SDL_Keymod
|
||||
SDL_GetModState(void)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
return keyboard->modstate;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetModState(SDL_Keymod modstate)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
keyboard->modstate = modstate;
|
||||
}
|
||||
|
||||
SDL_Keycode
|
||||
SDL_GetKeyFromScancode(SDL_Scancode scancode)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
|
||||
return keyboard->keymap[scancode];
|
||||
}
|
||||
|
||||
SDL_Scancode
|
||||
SDL_GetScancodeFromKey(SDL_Keycode key)
|
||||
{
|
||||
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||
SDL_Scancode scancode;
|
||||
|
||||
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
|
||||
++scancode) {
|
||||
if (keyboard->keymap[scancode] == key) {
|
||||
return scancode;
|
||||
}
|
||||
}
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_GetScancodeName(SDL_Scancode scancode)
|
||||
{
|
||||
const char *name = SDL_scancode_names[scancode];
|
||||
|
||||
if (name)
|
||||
return name;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *
|
||||
SDL_GetKeyName(SDL_Keycode key)
|
||||
{
|
||||
static char name[8];
|
||||
char *end;
|
||||
|
||||
if (key & SDLK_SCANCODE_MASK) {
|
||||
return
|
||||
SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case SDLK_RETURN:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
|
||||
case SDLK_ESCAPE:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
|
||||
case SDLK_BACKSPACE:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
|
||||
case SDLK_TAB:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_TAB);
|
||||
case SDLK_SPACE:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
|
||||
case SDLK_DELETE:
|
||||
return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
|
||||
default:
|
||||
/* Unaccented letter keys on latin keyboards are normally
|
||||
labeled in upper case (and probably on others like Greek or
|
||||
Cyrillic too, so if you happen to know for sure, please
|
||||
adapt this). */
|
||||
if (key >= 'a' && key <= 'z') {
|
||||
key -= 32;
|
||||
}
|
||||
|
||||
end = SDL_UCS4ToUTF8((Uint32) key, name);
|
||||
*end = '\0';
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
64
thirdparty/SDL/src/events/SDL_keyboard_c.h
vendored
Normal file
64
thirdparty/SDL/src/events/SDL_keyboard_c.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_keyboard_c_h
|
||||
#define _SDL_keyboard_c_h
|
||||
|
||||
#include "SDL_keycode.h"
|
||||
#include "SDL_events.h"
|
||||
|
||||
/* Initialize the keyboard subsystem */
|
||||
extern int SDL_KeyboardInit(void);
|
||||
|
||||
/* Clear the state of the keyboard */
|
||||
extern void SDL_ResetKeyboard(void);
|
||||
|
||||
/* Get the default keymap */
|
||||
extern void SDL_GetDefaultKeymap(SDL_Keycode * keymap);
|
||||
|
||||
/* Set the mapping of scancode to key codes */
|
||||
extern void SDL_SetKeymap(int start, SDL_Keycode * keys, int length);
|
||||
|
||||
/* Set a platform-dependent key name, overriding the default platform-agnostic
|
||||
name. Encoded as UTF-8. The string is not copied, thus the pointer given to
|
||||
this function must stay valid forever (or at least until the call to
|
||||
VideoQuit()). */
|
||||
extern void SDL_SetScancodeName(SDL_Scancode scancode, const char *name);
|
||||
|
||||
/* Set the keyboard focus window */
|
||||
extern void SDL_SetKeyboardFocus(SDL_Window * window);
|
||||
|
||||
/* Send a keyboard key event */
|
||||
extern int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode);
|
||||
|
||||
/* Send keyboard text input */
|
||||
extern int SDL_SendKeyboardText(const char *text);
|
||||
|
||||
/* Send editing text for selected range from start to end */
|
||||
extern int SDL_SendEditingText(const char *text, int start, int end);
|
||||
|
||||
/* Shutdown the keyboard subsystem */
|
||||
extern void SDL_KeyboardQuit(void);
|
||||
|
||||
#endif /* _SDL_keyboard_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
552
thirdparty/SDL/src/events/SDL_mouse.c
vendored
Normal file
552
thirdparty/SDL/src/events/SDL_mouse.c
vendored
Normal file
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General mouse handling code for SDL */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "default_cursor.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
|
||||
/* The mouse state */
|
||||
static SDL_Mouse SDL_mouse;
|
||||
|
||||
|
||||
/* Public functions */
|
||||
int
|
||||
SDL_MouseInit(void)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
mouse->cursor_shown = SDL_TRUE;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetDefaultCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
mouse->def_cursor = cursor;
|
||||
if (!mouse->cur_cursor) {
|
||||
SDL_SetCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Mouse *
|
||||
SDL_GetMouse(void)
|
||||
{
|
||||
return &SDL_mouse;
|
||||
}
|
||||
|
||||
SDL_Window *
|
||||
SDL_GetMouseFocus(void)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
return mouse->focus;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetMouseFocus(SDL_Window * window)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->focus == window) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if the current window has lost focus */
|
||||
if (mouse->focus) {
|
||||
SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
|
||||
}
|
||||
|
||||
mouse->focus = window;
|
||||
|
||||
if (mouse->focus) {
|
||||
SDL_SendWindowEvent(mouse->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int posted;
|
||||
int xrel;
|
||||
int yrel;
|
||||
int x_max = 0, y_max = 0;
|
||||
|
||||
if (window) {
|
||||
SDL_SetMouseFocus(window);
|
||||
}
|
||||
|
||||
/* the relative motion is calculated regarding the system cursor last position */
|
||||
if (relative) {
|
||||
xrel = x;
|
||||
yrel = y;
|
||||
x = (mouse->last_x + x);
|
||||
y = (mouse->last_y + y);
|
||||
} else {
|
||||
xrel = x - mouse->last_x;
|
||||
yrel = y - mouse->last_y;
|
||||
}
|
||||
|
||||
/* Drop events that don't change state */
|
||||
if (!xrel && !yrel) {
|
||||
#if 0
|
||||
printf("Mouse event didn't change state - dropped!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal mouse coordinates */
|
||||
if (mouse->relative_mode == SDL_FALSE) {
|
||||
mouse->x = x;
|
||||
mouse->y = y;
|
||||
} else {
|
||||
mouse->x += xrel;
|
||||
mouse->y += yrel;
|
||||
}
|
||||
|
||||
SDL_GetWindowSize(mouse->focus, &x_max, &y_max);
|
||||
--x_max;
|
||||
--y_max;
|
||||
|
||||
/* make sure that the pointers find themselves inside the windows */
|
||||
/* only check if mouse->xmax is set ! */
|
||||
if (mouse->x > x_max) {
|
||||
mouse->x = x_max;
|
||||
}
|
||||
if (mouse->x < 0) {
|
||||
mouse->x = 0;
|
||||
}
|
||||
|
||||
if (mouse->y > y_max) {
|
||||
mouse->y = y_max;
|
||||
}
|
||||
if (mouse->y < 0) {
|
||||
mouse->y = 0;
|
||||
}
|
||||
|
||||
mouse->xdelta += xrel;
|
||||
mouse->ydelta += yrel;
|
||||
|
||||
#if 0 /* FIXME */
|
||||
/* Move the mouse cursor, if needed */
|
||||
if (mouse->cursor_shown && !mouse->relative_mode &&
|
||||
mouse->MoveCursor && mouse->cur_cursor) {
|
||||
mouse->MoveCursor(mouse->cur_cursor);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_MOUSEMOTION) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.motion.type = SDL_MOUSEMOTION;
|
||||
event.motion.windowID = mouse->focus ? mouse->focus->id : 0;
|
||||
event.motion.state = mouse->buttonstate;
|
||||
event.motion.x = mouse->x;
|
||||
event.motion.y = mouse->y;
|
||||
event.motion.xrel = xrel;
|
||||
event.motion.yrel = yrel;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
mouse->last_x = mouse->x;
|
||||
mouse->last_y = mouse->y;
|
||||
return posted;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendMouseButton(SDL_Window * window, Uint8 state, Uint8 button)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int posted;
|
||||
Uint32 type;
|
||||
|
||||
if (window) {
|
||||
SDL_SetMouseFocus(window);
|
||||
}
|
||||
|
||||
/* Figure out which event to perform */
|
||||
switch (state) {
|
||||
case SDL_PRESSED:
|
||||
if (mouse->buttonstate & SDL_BUTTON(button)) {
|
||||
/* Ignore this event, no state change */
|
||||
return 0;
|
||||
}
|
||||
type = SDL_MOUSEBUTTONDOWN;
|
||||
mouse->buttonstate |= SDL_BUTTON(button);
|
||||
break;
|
||||
case SDL_RELEASED:
|
||||
if (!(mouse->buttonstate & SDL_BUTTON(button))) {
|
||||
/* Ignore this event, no state change */
|
||||
return 0;
|
||||
}
|
||||
type = SDL_MOUSEBUTTONUP;
|
||||
mouse->buttonstate &= ~SDL_BUTTON(button);
|
||||
break;
|
||||
default:
|
||||
/* Invalid state -- bail */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(type) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = type;
|
||||
event.button.state = state;
|
||||
event.button.button = button;
|
||||
event.button.x = mouse->x;
|
||||
event.button.y = mouse->y;
|
||||
event.button.windowID = mouse->focus ? mouse->focus->id : 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendMouseWheel(SDL_Window * window, int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
int posted;
|
||||
|
||||
if (window) {
|
||||
SDL_SetMouseFocus(window);
|
||||
}
|
||||
|
||||
if (!x && !y) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_MOUSEWHEEL;
|
||||
event.wheel.windowID = mouse->focus ? mouse->focus->id : 0;
|
||||
event.wheel.x = x;
|
||||
event.wheel.y = y;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_MouseQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
Uint8
|
||||
SDL_GetMouseState(int *x, int *y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (x) {
|
||||
*x = mouse->x;
|
||||
}
|
||||
if (y) {
|
||||
*y = mouse->y;
|
||||
}
|
||||
return mouse->buttonstate;
|
||||
}
|
||||
|
||||
Uint8
|
||||
SDL_GetRelativeMouseState(int *x, int *y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (x) {
|
||||
*x = mouse->xdelta;
|
||||
}
|
||||
if (y) {
|
||||
*y = mouse->ydelta;
|
||||
}
|
||||
mouse->xdelta = 0;
|
||||
mouse->ydelta = 0;
|
||||
return mouse->buttonstate;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (mouse->WarpMouse) {
|
||||
mouse->WarpMouse(window, x, y);
|
||||
} else {
|
||||
SDL_SendMouseMotion(window, 0, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SetRelativeMouseMode(SDL_bool enabled)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (enabled == mouse->relative_mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!mouse->SetRelativeMouseMode) {
|
||||
SDL_Unsupported();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mouse->SetRelativeMouseMode(enabled) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the relative mode */
|
||||
mouse->relative_mode = enabled;
|
||||
|
||||
if (!enabled) {
|
||||
/* Restore the expected mouse position */
|
||||
SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
|
||||
}
|
||||
|
||||
/* Flush pending mouse motion */
|
||||
SDL_FlushEvent(SDL_MOUSEMOTION);
|
||||
|
||||
/* Update cursor visibility */
|
||||
SDL_SetCursor(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_bool
|
||||
SDL_GetRelativeMouseMode()
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
return mouse->relative_mode;
|
||||
}
|
||||
|
||||
SDL_Cursor *
|
||||
SDL_CreateCursor(const Uint8 * data, const Uint8 * mask,
|
||||
int w, int h, int hot_x, int hot_y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Surface *surface;
|
||||
SDL_Cursor *cursor;
|
||||
int x, y;
|
||||
Uint32 *pixel;
|
||||
Uint8 datab = 0, maskb = 0;
|
||||
const Uint32 black = 0xFF000000;
|
||||
const Uint32 white = 0xFFFFFFFF;
|
||||
const Uint32 transparent = 0x00000000;
|
||||
|
||||
/* Make sure the width is a multiple of 8 */
|
||||
w = ((w + 7) & ~7);
|
||||
|
||||
/* Create the surface from a bitmap */
|
||||
surface = SDL_CreateRGBSurface(0, w, h, 32,
|
||||
0x00FF0000,
|
||||
0x0000FF00,
|
||||
0x000000FF,
|
||||
0xFF000000);
|
||||
if (!surface) {
|
||||
return NULL;
|
||||
}
|
||||
for (y = 0; y < h; ++y) {
|
||||
pixel = (Uint32 *) ((Uint8 *) surface->pixels + y * surface->pitch);
|
||||
for (x = 0; x < w; ++x) {
|
||||
if ((x % 8) == 0) {
|
||||
datab = *data++;
|
||||
maskb = *mask++;
|
||||
}
|
||||
if (maskb & 0x80) {
|
||||
*pixel++ = (datab & 0x80) ? black : white;
|
||||
} else {
|
||||
*pixel++ = (datab & 0x80) ? black : transparent;
|
||||
}
|
||||
datab <<= 1;
|
||||
maskb <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
cursor = SDL_CreateColorCursor(surface, hot_x, hot_y);
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
SDL_Cursor *
|
||||
SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Surface *temp = NULL;
|
||||
SDL_Cursor *cursor;
|
||||
|
||||
if (!surface) {
|
||||
SDL_SetError("Passed NULL cursor surface");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!mouse->CreateCursor) {
|
||||
SDL_SetError("Cursors are not currently supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sanity check the hot spot */
|
||||
if ((hot_x < 0) || (hot_y < 0) ||
|
||||
(hot_x >= surface->w) || (hot_y >= surface->h)) {
|
||||
SDL_SetError("Cursor hot spot doesn't lie within cursor");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) {
|
||||
temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888, 0);
|
||||
if (!temp) {
|
||||
return NULL;
|
||||
}
|
||||
surface = temp;
|
||||
}
|
||||
|
||||
cursor = mouse->CreateCursor(surface, hot_x, hot_y);
|
||||
if (cursor) {
|
||||
cursor->next = mouse->cursors;
|
||||
mouse->cursors = cursor;
|
||||
}
|
||||
|
||||
if (temp) {
|
||||
SDL_FreeSurface(temp);
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
/* SDL_SetCursor(NULL) can be used to force the cursor redraw,
|
||||
if this is desired for any reason. This is used when setting
|
||||
the video mode and when the SDL window gains the mouse focus.
|
||||
*/
|
||||
void
|
||||
SDL_SetCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
/* Set the new cursor */
|
||||
if (cursor) {
|
||||
/* Make sure the cursor is still valid for this mouse */
|
||||
if (cursor != mouse->def_cursor) {
|
||||
SDL_Cursor *found;
|
||||
for (found = mouse->cursors; found; found = found->next) {
|
||||
if (found == cursor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SDL_SetError("Cursor not associated with the current mouse");
|
||||
return;
|
||||
}
|
||||
}
|
||||
mouse->cur_cursor = cursor;
|
||||
} else {
|
||||
cursor = mouse->cur_cursor;
|
||||
}
|
||||
|
||||
if (cursor && mouse->cursor_shown && !mouse->relative_mode) {
|
||||
if (mouse->ShowCursor) {
|
||||
mouse->ShowCursor(cursor);
|
||||
}
|
||||
} else {
|
||||
if (mouse->ShowCursor) {
|
||||
mouse->ShowCursor(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Cursor *
|
||||
SDL_GetCursor(void)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
|
||||
if (!mouse) {
|
||||
return NULL;
|
||||
}
|
||||
return mouse->cur_cursor;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FreeCursor(SDL_Cursor * cursor)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_Cursor *curr, *prev;
|
||||
|
||||
if (!cursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor == mouse->def_cursor) {
|
||||
return;
|
||||
}
|
||||
if (cursor == mouse->cur_cursor) {
|
||||
SDL_SetCursor(mouse->def_cursor);
|
||||
}
|
||||
|
||||
for (prev = NULL, curr = mouse->cursors; curr;
|
||||
prev = curr, curr = curr->next) {
|
||||
if (curr == cursor) {
|
||||
if (prev) {
|
||||
prev->next = curr->next;
|
||||
} else {
|
||||
mouse->cursors = curr->next;
|
||||
}
|
||||
|
||||
if (mouse->FreeCursor) {
|
||||
mouse->FreeCursor(curr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_ShowCursor(int toggle)
|
||||
{
|
||||
SDL_Mouse *mouse = SDL_GetMouse();
|
||||
SDL_bool shown;
|
||||
|
||||
if (!mouse) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
shown = mouse->cursor_shown;
|
||||
if (toggle >= 0) {
|
||||
if (toggle) {
|
||||
mouse->cursor_shown = SDL_TRUE;
|
||||
} else {
|
||||
mouse->cursor_shown = SDL_FALSE;
|
||||
}
|
||||
if (mouse->cursor_shown != shown) {
|
||||
SDL_SetCursor(NULL);
|
||||
}
|
||||
}
|
||||
return shown;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
97
thirdparty/SDL/src/events/SDL_mouse_c.h
vendored
Normal file
97
thirdparty/SDL/src/events/SDL_mouse_c.h
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_mouse_c_h
|
||||
#define _SDL_mouse_c_h
|
||||
|
||||
#include "SDL_mouse.h"
|
||||
|
||||
struct SDL_Cursor
|
||||
{
|
||||
struct SDL_Cursor *next;
|
||||
void *driverdata;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Create a cursor from a surface */
|
||||
SDL_Cursor *(*CreateCursor) (SDL_Surface * surface, int hot_x, int hot_y);
|
||||
|
||||
/* Show the specified cursor, or hide if cursor is NULL */
|
||||
int (*ShowCursor) (SDL_Cursor * cursor);
|
||||
|
||||
/* This is called when a mouse motion event occurs */
|
||||
void (*MoveCursor) (SDL_Cursor * cursor);
|
||||
|
||||
/* Free a window manager cursor */
|
||||
void (*FreeCursor) (SDL_Cursor * cursor);
|
||||
|
||||
/* Warp the mouse to (x,y) */
|
||||
void (*WarpMouse) (SDL_Window * window, int x, int y);
|
||||
|
||||
/* Set relative mode */
|
||||
int (*SetRelativeMouseMode) (SDL_bool enabled);
|
||||
|
||||
/* Data common to all mice */
|
||||
SDL_Window *focus;
|
||||
int x;
|
||||
int y;
|
||||
int xdelta;
|
||||
int ydelta;
|
||||
int last_x, last_y; /* the last reported x and y coordinates */
|
||||
Uint8 buttonstate;
|
||||
SDL_bool relative_mode;
|
||||
|
||||
SDL_Cursor *cursors;
|
||||
SDL_Cursor *def_cursor;
|
||||
SDL_Cursor *cur_cursor;
|
||||
SDL_bool cursor_shown;
|
||||
} SDL_Mouse;
|
||||
|
||||
|
||||
/* Initialize the mouse subsystem */
|
||||
extern int SDL_MouseInit(void);
|
||||
|
||||
/* Get the mouse state structure */
|
||||
SDL_Mouse *SDL_GetMouse(void);
|
||||
|
||||
/* Set the default mouse cursor */
|
||||
extern void SDL_SetDefaultCursor(SDL_Cursor * cursor);
|
||||
|
||||
/* Set the mouse focus window */
|
||||
extern void SDL_SetMouseFocus(SDL_Window * window);
|
||||
|
||||
/* Send a mouse motion event */
|
||||
extern int SDL_SendMouseMotion(SDL_Window * window, int relative, int x, int y);
|
||||
|
||||
/* Send a mouse button event */
|
||||
extern int SDL_SendMouseButton(SDL_Window * window, Uint8 state, Uint8 button);
|
||||
|
||||
/* Send a mouse wheel event */
|
||||
extern int SDL_SendMouseWheel(SDL_Window * window, int x, int y);
|
||||
|
||||
/* Shutdown the mouse subsystem */
|
||||
extern void SDL_MouseQuit(void);
|
||||
|
||||
#endif /* _SDL_mouse_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
119
thirdparty/SDL/src/events/SDL_quit.c
vendored
Normal file
119
thirdparty/SDL/src/events/SDL_quit.c
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* General quit handling code for SDL */
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
static void
|
||||
SDL_HandleSIG(int sig)
|
||||
{
|
||||
/* Reset the signal handler */
|
||||
signal(sig, SDL_HandleSIG);
|
||||
|
||||
/* Signal a quit interrupt */
|
||||
SDL_SendQuit();
|
||||
}
|
||||
#endif /* HAVE_SIGNAL_H */
|
||||
|
||||
/* Public functions */
|
||||
int
|
||||
SDL_QuitInit(void)
|
||||
{
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction action;
|
||||
sigaction(SIGINT, NULL, &action);
|
||||
if ( action.sa_handler == SIG_DFL && action.sa_sigaction == (void*)SIG_DFL ) {
|
||||
action.sa_handler = SDL_HandleSIG;
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
}
|
||||
sigaction(SIGTERM, NULL, &action);
|
||||
if ( action.sa_handler == SIG_DFL && action.sa_sigaction == (void*)SIG_DFL ) {
|
||||
action.sa_handler = SDL_HandleSIG;
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
}
|
||||
#elif HAVE_SIGNAL_H
|
||||
void (*ohandler) (int);
|
||||
|
||||
/* Both SIGINT and SIGTERM are translated into quit interrupts */
|
||||
ohandler = signal(SIGINT, SDL_HandleSIG);
|
||||
if (ohandler != SIG_DFL)
|
||||
signal(SIGINT, ohandler);
|
||||
ohandler = signal(SIGTERM, SDL_HandleSIG);
|
||||
if (ohandler != SIG_DFL)
|
||||
signal(SIGTERM, ohandler);
|
||||
#endif /* HAVE_SIGNAL_H */
|
||||
|
||||
/* That's it! */
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_QuitQuit(void)
|
||||
{
|
||||
#ifdef HAVE_SIGACTION
|
||||
struct sigaction action;
|
||||
sigaction(SIGINT, NULL, &action);
|
||||
if ( action.sa_handler == SDL_HandleSIG ) {
|
||||
action.sa_handler = SIG_DFL;
|
||||
sigaction(SIGINT, &action, NULL);
|
||||
}
|
||||
sigaction(SIGTERM, NULL, &action);
|
||||
if ( action.sa_handler == SDL_HandleSIG ) {
|
||||
action.sa_handler = SIG_DFL;
|
||||
sigaction(SIGTERM, &action, NULL);
|
||||
}
|
||||
#elif HAVE_SIGNAL_H
|
||||
void (*ohandler) (int);
|
||||
|
||||
ohandler = signal(SIGINT, SIG_DFL);
|
||||
if (ohandler != SDL_HandleSIG)
|
||||
signal(SIGINT, ohandler);
|
||||
ohandler = signal(SIGTERM, SIG_DFL);
|
||||
if (ohandler != SDL_HandleSIG)
|
||||
signal(SIGTERM, ohandler);
|
||||
#endif /* HAVE_SIGNAL_H */
|
||||
}
|
||||
|
||||
/* This function returns 1 if it's okay to close the application window */
|
||||
int
|
||||
SDL_SendQuit(void)
|
||||
{
|
||||
int posted;
|
||||
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_QUIT;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return (posted);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
35
thirdparty/SDL/src/events/SDL_sysevents.h
vendored
Normal file
35
thirdparty/SDL/src/events/SDL_sysevents.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
/* Useful functions and variables from SDL_sysevents.c */
|
||||
|
||||
#ifdef __BEOS__ /* The Be event loop runs in a separate thread */
|
||||
#define MUST_THREAD_EVENTS
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__ /* Windows doesn't allow a separate event thread */
|
||||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
575
thirdparty/SDL/src/events/SDL_touch.c
vendored
Normal file
575
thirdparty/SDL/src/events/SDL_touch.c
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* General touch handling code for SDL */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static int SDL_num_touch = 0;
|
||||
static SDL_Touch **SDL_touchPads = NULL;
|
||||
|
||||
|
||||
/* Public functions */
|
||||
int
|
||||
SDL_TouchInit(void)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
SDL_Touch *
|
||||
SDL_GetTouch(SDL_TouchID id)
|
||||
{
|
||||
int index = SDL_GetTouchIndexId(id);
|
||||
if (index < 0 || index >= SDL_num_touch) {
|
||||
return NULL;
|
||||
}
|
||||
return SDL_touchPads[index];
|
||||
}
|
||||
|
||||
SDL_Touch *
|
||||
SDL_GetTouchIndex(int index)
|
||||
{
|
||||
if (index < 0 || index >= SDL_num_touch) {
|
||||
return NULL;
|
||||
}
|
||||
return SDL_touchPads[index];
|
||||
}
|
||||
|
||||
int
|
||||
SDL_GetFingerIndexId(SDL_Touch* touch,SDL_FingerID fingerid)
|
||||
{
|
||||
int i;
|
||||
for(i = 0;i < touch->num_fingers;i++)
|
||||
if(touch->fingers[i]->id == fingerid)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SDL_Finger *
|
||||
SDL_GetFinger(SDL_Touch* touch,SDL_FingerID id)
|
||||
{
|
||||
int index = SDL_GetFingerIndexId(touch,id);
|
||||
if(index < 0 || index >= touch->num_fingers)
|
||||
return NULL;
|
||||
return touch->fingers[index];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SDL_GetTouchIndexId(SDL_TouchID id)
|
||||
{
|
||||
int index;
|
||||
SDL_Touch *touch;
|
||||
|
||||
for (index = 0; index < SDL_num_touch; ++index) {
|
||||
touch = SDL_touchPads[index];
|
||||
if (touch->id == id) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_AddTouch(const SDL_Touch * touch, char *name)
|
||||
{
|
||||
SDL_Touch **touchPads;
|
||||
int index;
|
||||
size_t length;
|
||||
|
||||
if (SDL_GetTouchIndexId(touch->id) != -1) {
|
||||
SDL_SetError("Touch ID already in use");
|
||||
}
|
||||
|
||||
/* Add the touch to the list of touch */
|
||||
touchPads = (SDL_Touch **) SDL_realloc(SDL_touchPads,
|
||||
(SDL_num_touch + 1) * sizeof(*touch));
|
||||
if (!touchPads) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_touchPads = touchPads;
|
||||
index = SDL_num_touch++;
|
||||
|
||||
SDL_touchPads[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchPads[index]));
|
||||
if (!SDL_touchPads[index]) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
SDL_memcpy(SDL_touchPads[index], touch, sizeof(*touch));
|
||||
|
||||
/* we're setting the touch properties */
|
||||
length = 0;
|
||||
length = SDL_strlen(name);
|
||||
SDL_touchPads[index]->focus = 0;
|
||||
SDL_touchPads[index]->name = SDL_malloc((length + 2) * sizeof(char));
|
||||
SDL_strlcpy(SDL_touchPads[index]->name, name, length + 1);
|
||||
|
||||
SDL_touchPads[index]->num_fingers = 0;
|
||||
SDL_touchPads[index]->max_fingers = 1;
|
||||
SDL_touchPads[index]->fingers = (SDL_Finger **) SDL_malloc(sizeof(SDL_Finger*));
|
||||
SDL_touchPads[index]->fingers[0] = NULL;
|
||||
SDL_touchPads[index]->buttonstate = 0;
|
||||
SDL_touchPads[index]->relative_mode = SDL_FALSE;
|
||||
SDL_touchPads[index]->flush_motion = SDL_FALSE;
|
||||
|
||||
// Wil 06/10/11: WTF is this for? It's stomping over what's been passed in!
|
||||
//SDL_touchPads[index]->xres = (1<<(16-1));
|
||||
//SDL_touchPads[index]->yres = (1<<(16-1));
|
||||
|
||||
//Do I want this here? Probably
|
||||
SDL_GestureAddTouch(SDL_touchPads[index]);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DelTouch(SDL_TouchID id)
|
||||
{
|
||||
int index = SDL_GetTouchIndexId(id);
|
||||
SDL_Touch *touch = SDL_GetTouch(id);
|
||||
|
||||
if (!touch) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SDL_free(touch->name);
|
||||
|
||||
if (touch->FreeTouch) {
|
||||
touch->FreeTouch(touch);
|
||||
}
|
||||
SDL_free(touch);
|
||||
|
||||
SDL_num_touch--;
|
||||
SDL_touchPads[index] = SDL_touchPads[SDL_num_touch];
|
||||
}
|
||||
|
||||
void
|
||||
SDL_TouchQuit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = SDL_num_touch-1; i > 0 ; --i) {
|
||||
SDL_DelTouch(i);
|
||||
}
|
||||
SDL_num_touch = 0;
|
||||
|
||||
if (SDL_touchPads) {
|
||||
SDL_free(SDL_touchPads);
|
||||
SDL_touchPads = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_GetNumTouch(void)
|
||||
{
|
||||
return SDL_num_touch;
|
||||
}
|
||||
SDL_Window *
|
||||
SDL_GetTouchFocusWindow(SDL_TouchID id)
|
||||
{
|
||||
SDL_Touch *touch = SDL_GetTouch(id);
|
||||
|
||||
if (!touch) {
|
||||
return 0;
|
||||
}
|
||||
return touch->focus;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SetTouchFocus(SDL_TouchID id, SDL_Window * window)
|
||||
{
|
||||
int index = SDL_GetTouchIndexId(id);
|
||||
SDL_Touch *touch = SDL_GetTouch(id);
|
||||
int i;
|
||||
SDL_bool focus;
|
||||
|
||||
if (!touch || (touch->focus == window)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* See if the current window has lost focus */
|
||||
if (touch->focus) {
|
||||
focus = SDL_FALSE;
|
||||
for (i = 0; i < SDL_num_touch; ++i) {
|
||||
SDL_Touch *check;
|
||||
if (i != index) {
|
||||
check = SDL_touchPads[i];
|
||||
if (check && check->focus == touch->focus) {
|
||||
focus = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!focus) {
|
||||
SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_LEAVE, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
touch->focus = window;
|
||||
|
||||
if (touch->focus) {
|
||||
focus = SDL_FALSE;
|
||||
for (i = 0; i < SDL_num_touch; ++i) {
|
||||
SDL_Touch *check;
|
||||
if (i != index) {
|
||||
check = SDL_touchPads[i];
|
||||
if (check && check->focus == touch->focus) {
|
||||
focus = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!focus) {
|
||||
SDL_SendWindowEvent(touch->focus, SDL_WINDOWEVENT_ENTER, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_AddFinger(SDL_Touch* touch,SDL_Finger *finger)
|
||||
{
|
||||
int index;
|
||||
SDL_Finger **fingers;
|
||||
//printf("Adding Finger...\n");
|
||||
if (SDL_GetFingerIndexId(touch,finger->id) != -1) {
|
||||
SDL_SetError("Finger ID already in use");
|
||||
}
|
||||
|
||||
/* Add the touch to the list of touch */
|
||||
if(touch->num_fingers >= touch->max_fingers){
|
||||
//printf("Making room for it!\n");
|
||||
fingers = (SDL_Finger **) SDL_realloc(touch->fingers,
|
||||
(touch->num_fingers + 1) * sizeof(SDL_Finger *));
|
||||
touch->max_fingers = touch->num_fingers+1;
|
||||
if (!fingers) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
} else {
|
||||
touch->max_fingers = touch->num_fingers+1;
|
||||
touch->fingers = fingers;
|
||||
}
|
||||
}
|
||||
|
||||
index = touch->num_fingers;
|
||||
//printf("Max_Fingers: %i Index: %i\n",touch->max_fingers,index);
|
||||
|
||||
touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(SDL_Finger));
|
||||
if (!touch->fingers[index]) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
*(touch->fingers[index]) = *finger;
|
||||
touch->num_fingers++;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_DelFinger(SDL_Touch* touch,SDL_FingerID fingerid)
|
||||
{
|
||||
int index = SDL_GetFingerIndexId(touch,fingerid);
|
||||
SDL_Finger* finger = SDL_GetFinger(touch,fingerid);
|
||||
|
||||
if (!finger) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
SDL_free(finger);
|
||||
touch->num_fingers--;
|
||||
touch->fingers[index] = touch->fingers[touch->num_fingers];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid, SDL_bool down,
|
||||
float xin, float yin, float pressurein)
|
||||
{
|
||||
int posted;
|
||||
Uint16 x;
|
||||
Uint16 y;
|
||||
Uint16 pressure;
|
||||
SDL_Finger *finger;
|
||||
|
||||
SDL_Touch* touch = SDL_GetTouch(id);
|
||||
|
||||
if(!touch) {
|
||||
return SDL_TouchNotFoundError(id);
|
||||
}
|
||||
|
||||
//scale to Integer coordinates
|
||||
x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres));
|
||||
y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
|
||||
pressure = (Uint16)((pressurein+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
|
||||
|
||||
finger = SDL_GetFinger(touch,fingerid);
|
||||
if(down) {
|
||||
if(finger == NULL) {
|
||||
SDL_Finger nf;
|
||||
nf.id = fingerid;
|
||||
nf.x = x;
|
||||
nf.y = y;
|
||||
nf.pressure = pressure;
|
||||
nf.xdelta = 0;
|
||||
nf.ydelta = 0;
|
||||
nf.last_x = x;
|
||||
nf.last_y = y;
|
||||
nf.last_pressure = pressure;
|
||||
nf.down = SDL_FALSE;
|
||||
if(SDL_AddFinger(touch,&nf) < 0) return 0;
|
||||
finger = SDL_GetFinger(touch,fingerid);
|
||||
}
|
||||
else if(finger->down) return 0;
|
||||
if(xin < touch->x_min || yin < touch->y_min) return 0; //should defer if only a partial input
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.tfinger.type = SDL_FINGERDOWN;
|
||||
event.tfinger.touchId = id;
|
||||
event.tfinger.x = x;
|
||||
event.tfinger.y = y;
|
||||
event.tfinger.pressure = pressure;
|
||||
event.tfinger.state = touch->buttonstate;
|
||||
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
||||
event.tfinger.fingerId = fingerid;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
if(posted) finger->down = SDL_TRUE;
|
||||
return posted;
|
||||
}
|
||||
else {
|
||||
if(finger == NULL) {
|
||||
SDL_SetError("Finger not found.");
|
||||
return 0;
|
||||
}
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.tfinger.type = SDL_FINGERUP;
|
||||
event.tfinger.touchId = id;
|
||||
event.tfinger.state = touch->buttonstate;
|
||||
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
||||
event.tfinger.fingerId = fingerid;
|
||||
//I don't trust the coordinates passed on fingerUp
|
||||
event.tfinger.x = finger->x;
|
||||
event.tfinger.y = finger->y;
|
||||
event.tfinger.dx = 0;
|
||||
event.tfinger.dy = 0;
|
||||
|
||||
if(SDL_DelFinger(touch,fingerid) < 0) return 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative,
|
||||
float xin, float yin, float pressurein)
|
||||
{
|
||||
SDL_Touch *touch;
|
||||
SDL_Finger *finger;
|
||||
int posted;
|
||||
Sint16 xrel, yrel;
|
||||
Uint16 x;
|
||||
Uint16 y;
|
||||
Uint16 pressure;
|
||||
|
||||
touch = SDL_GetTouch(id);
|
||||
if (!touch) {
|
||||
return SDL_TouchNotFoundError(id);
|
||||
}
|
||||
|
||||
//scale to Integer coordinates
|
||||
x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres));
|
||||
y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres));
|
||||
pressure = (Uint16)((yin+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres));
|
||||
if(touch->flush_motion) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
finger = SDL_GetFinger(touch,fingerid);
|
||||
if(finger == NULL || !finger->down) {
|
||||
return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein);
|
||||
} else {
|
||||
/* the relative motion is calculated regarding the last position */
|
||||
if (relative) {
|
||||
xrel = x;
|
||||
yrel = y;
|
||||
x = (finger->last_x + x);
|
||||
y = (finger->last_y + y);
|
||||
} else {
|
||||
if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/
|
||||
if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/
|
||||
if(pressurein < touch->pressure_min) pressure = finger->last_pressure;
|
||||
xrel = x - finger->last_x;
|
||||
yrel = y - finger->last_y;
|
||||
//printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel);
|
||||
}
|
||||
|
||||
/* Drop events that don't change state */
|
||||
if (!xrel && !yrel) {
|
||||
#if 0
|
||||
printf("Touch event didn't change state - dropped!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update internal touch coordinates */
|
||||
|
||||
finger->x = x;
|
||||
finger->y = y;
|
||||
|
||||
/*Should scale to window? Normalize? Maintain Aspect?*/
|
||||
//SDL_GetWindowSize(touch->focus, &x_max, &y_max);
|
||||
|
||||
/* make sure that the pointers find themselves inside the windows */
|
||||
/* only check if touch->xmax is set ! */
|
||||
/*
|
||||
if (x_max && touch->x > x_max) {
|
||||
touch->x = x_max;
|
||||
} else if (touch->x < 0) {
|
||||
touch->x = 0;
|
||||
}
|
||||
|
||||
if (y_max && touch->y > y_max) {
|
||||
touch->y = y_max;
|
||||
} else if (touch->y < 0) {
|
||||
touch->y = 0;
|
||||
}
|
||||
*/
|
||||
finger->xdelta = xrel;
|
||||
finger->ydelta = yrel;
|
||||
finger->pressure = pressure;
|
||||
|
||||
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.tfinger.type = SDL_FINGERMOTION;
|
||||
event.tfinger.touchId = id;
|
||||
event.tfinger.fingerId = fingerid;
|
||||
event.tfinger.x = x;
|
||||
event.tfinger.y = y;
|
||||
event.tfinger.dx = xrel;
|
||||
event.tfinger.dy = yrel;
|
||||
|
||||
event.tfinger.pressure = pressure;
|
||||
event.tfinger.state = touch->buttonstate;
|
||||
event.tfinger.windowID = touch->focus ? touch->focus->id : 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
finger->last_x = finger->x;
|
||||
finger->last_y = finger->y;
|
||||
finger->last_pressure = finger->pressure;
|
||||
return posted;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendTouchButton(SDL_TouchID id, Uint8 state, Uint8 button)
|
||||
{
|
||||
SDL_Touch *touch;
|
||||
int posted;
|
||||
Uint32 type;
|
||||
|
||||
|
||||
touch = SDL_GetTouch(id);
|
||||
if (!touch) {
|
||||
return SDL_TouchNotFoundError(id);
|
||||
}
|
||||
|
||||
/* Figure out which event to perform */
|
||||
switch (state) {
|
||||
case SDL_PRESSED:
|
||||
if (touch->buttonstate & SDL_BUTTON(button)) {
|
||||
/* Ignore this event, no state change */
|
||||
return 0;
|
||||
}
|
||||
type = SDL_TOUCHBUTTONDOWN;
|
||||
touch->buttonstate |= SDL_BUTTON(button);
|
||||
break;
|
||||
case SDL_RELEASED:
|
||||
if (!(touch->buttonstate & SDL_BUTTON(button))) {
|
||||
/* Ignore this event, no state change */
|
||||
return 0;
|
||||
}
|
||||
type = SDL_TOUCHBUTTONUP;
|
||||
touch->buttonstate &= ~SDL_BUTTON(button);
|
||||
break;
|
||||
default:
|
||||
/* Invalid state -- bail */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(type) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = type;
|
||||
event.tbutton.touchId = touch->id;
|
||||
event.tbutton.state = state;
|
||||
event.tbutton.button = button;
|
||||
event.tbutton.windowID = touch->focus ? touch->focus->id : 0;
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
return posted;
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetTouchName(SDL_TouchID id)
|
||||
{
|
||||
SDL_Touch *touch = SDL_GetTouch(id);
|
||||
if (!touch) {
|
||||
return NULL;
|
||||
}
|
||||
return touch->name;
|
||||
}
|
||||
|
||||
int SDL_TouchNotFoundError(SDL_TouchID id) {
|
||||
//int i;
|
||||
SDL_SetError("ERROR: Cannot send touch on non-existent device with id: %li make sure SDL_AddTouch has been called\n",id);
|
||||
#if 0
|
||||
printf("ERROR: There are %i touches installed with Id's:\n",SDL_num_touch);
|
||||
for(i=0;i < SDL_num_touch;i++) {
|
||||
printf("ERROR: %li\n",SDL_touchPads[i]->id);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
78
thirdparty/SDL/src/events/SDL_touch_c.h
vendored
Normal file
78
thirdparty/SDL/src/events/SDL_touch_c.h
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
#include "../../include/SDL_touch.h"
|
||||
|
||||
#ifndef _SDL_touch_c_h
|
||||
#define _SDL_touch_c_h
|
||||
|
||||
|
||||
|
||||
/* Initialize the touch subsystem */
|
||||
extern int SDL_TouchInit(void);
|
||||
|
||||
/*Get the touch at an index */
|
||||
extern SDL_Touch *SDL_GetTouchIndex(int index);
|
||||
|
||||
/* Get the touch with id = id */
|
||||
extern SDL_Touch *SDL_GetTouch(SDL_TouchID id);
|
||||
|
||||
/*Get the finger at an index */
|
||||
extern SDL_Finger *SDL_GetFingerIndex(SDL_Touch *touch, int index);
|
||||
|
||||
/* Get the finger with id = id */
|
||||
extern SDL_Finger *SDL_GetFinger(SDL_Touch *touch,SDL_FingerID id);
|
||||
|
||||
|
||||
/* Add a touch, possibly reattaching at a particular index (or -1),
|
||||
returning the index of the touch, or -1 if there was an error. */
|
||||
extern int SDL_AddTouch(const SDL_Touch * touch, char *name);
|
||||
|
||||
|
||||
/* Remove a touch at an index, clearing the slot for later */
|
||||
extern void SDL_DelTouch(SDL_TouchID id);
|
||||
|
||||
/* Set the touch focus window */
|
||||
extern void SDL_SetTouchFocus(SDL_TouchID id, SDL_Window * window);
|
||||
|
||||
/* Send a touch motion event for a touch */
|
||||
extern int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid,
|
||||
int relative, float x, float y, float z);
|
||||
|
||||
/* Send a touch down/up event for a touch */
|
||||
extern int SDL_SendFingerDown(SDL_TouchID id, SDL_FingerID fingerid,
|
||||
SDL_bool down, float x, float y, float pressure);
|
||||
|
||||
/* Send a touch button event for a touch */
|
||||
extern int SDL_SendTouchButton(SDL_TouchID id, Uint8 state, Uint8 button);
|
||||
|
||||
/* Shutdown the touch subsystem */
|
||||
extern void SDL_TouchQuit(void);
|
||||
|
||||
/* Get the index of a touch device */
|
||||
extern int SDL_GetTouchIndexId(SDL_TouchID id);
|
||||
|
||||
/* Print a debug message for a nonexistent touch */
|
||||
extern int SDL_TouchNotFoundError(SDL_TouchID id);
|
||||
|
||||
#endif /* _SDL_touch_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
193
thirdparty/SDL/src/events/SDL_windowevents.c
vendored
Normal file
193
thirdparty/SDL/src/events/SDL_windowevents.c
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* Window event handling code for SDL */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
|
||||
|
||||
static int
|
||||
RemovePendingSizeEvents(void * userdata, SDL_Event *event)
|
||||
{
|
||||
SDL_Event *new_event = (SDL_Event *)userdata;
|
||||
|
||||
if (event->type == SDL_WINDOWEVENT &&
|
||||
(event->window.event == SDL_WINDOWEVENT_RESIZED ||
|
||||
event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) &&
|
||||
event->window.windowID == new_event->window.windowID) {
|
||||
/* We're about to post a new size event, drop the old one */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
RemovePendingMoveEvents(void * userdata, SDL_Event *event)
|
||||
{
|
||||
SDL_Event *new_event = (SDL_Event *)userdata;
|
||||
|
||||
if (event->type == SDL_WINDOWEVENT &&
|
||||
event->window.event == SDL_WINDOWEVENT_MOVED &&
|
||||
event->window.windowID == new_event->window.windowID) {
|
||||
/* We're about to post a new move event, drop the old one */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,
|
||||
int data2)
|
||||
{
|
||||
int posted;
|
||||
|
||||
if (!window) {
|
||||
return 0;
|
||||
}
|
||||
switch (windowevent) {
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
if (window->flags & SDL_WINDOW_SHOWN) {
|
||||
return 0;
|
||||
}
|
||||
window->flags &= ~SDL_WINDOW_HIDDEN;
|
||||
window->flags |= SDL_WINDOW_SHOWN;
|
||||
SDL_OnWindowShown(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
if (!(window->flags & SDL_WINDOW_SHOWN)) {
|
||||
return 0;
|
||||
}
|
||||
window->flags &= ~SDL_WINDOW_SHOWN;
|
||||
window->flags |= SDL_WINDOW_HIDDEN;
|
||||
SDL_OnWindowHidden(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
if (SDL_WINDOWPOS_ISUNDEFINED(data1) ||
|
||||
SDL_WINDOWPOS_ISUNDEFINED(data2)) {
|
||||
return 0;
|
||||
}
|
||||
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||
window->windowed.x = data1;
|
||||
window->windowed.y = data2;
|
||||
}
|
||||
if (data1 == window->x && data2 == window->y) {
|
||||
return 0;
|
||||
}
|
||||
window->x = data1;
|
||||
window->y = data2;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||
window->windowed.w = data1;
|
||||
window->windowed.h = data2;
|
||||
}
|
||||
if (data1 == window->w && data2 == window->h) {
|
||||
return 0;
|
||||
}
|
||||
window->w = data1;
|
||||
window->h = data2;
|
||||
SDL_OnWindowResized(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
if (window->flags & SDL_WINDOW_MINIMIZED) {
|
||||
return 0;
|
||||
}
|
||||
window->flags |= SDL_WINDOW_MINIMIZED;
|
||||
SDL_OnWindowMinimized(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
if (window->flags & SDL_WINDOW_MAXIMIZED) {
|
||||
return 0;
|
||||
}
|
||||
window->flags |= SDL_WINDOW_MAXIMIZED;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) {
|
||||
return 0;
|
||||
}
|
||||
window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED);
|
||||
SDL_OnWindowRestored(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
if (window->flags & SDL_WINDOW_MOUSE_FOCUS) {
|
||||
return 0;
|
||||
}
|
||||
window->flags |= SDL_WINDOW_MOUSE_FOCUS;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) {
|
||||
return 0;
|
||||
}
|
||||
window->flags &= ~SDL_WINDOW_MOUSE_FOCUS;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
if (window->flags & SDL_WINDOW_INPUT_FOCUS) {
|
||||
return 0;
|
||||
}
|
||||
window->flags |= SDL_WINDOW_INPUT_FOCUS;
|
||||
SDL_OnWindowFocusGained(window);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
return 0;
|
||||
}
|
||||
window->flags &= ~SDL_WINDOW_INPUT_FOCUS;
|
||||
SDL_OnWindowFocusLost(window);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Post the event, if desired */
|
||||
posted = 0;
|
||||
if (SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE) {
|
||||
SDL_Event event;
|
||||
event.type = SDL_WINDOWEVENT;
|
||||
event.window.event = windowevent;
|
||||
event.window.data1 = data1;
|
||||
event.window.data2 = data2;
|
||||
event.window.windowID = window->id;
|
||||
|
||||
/* Fixes queue overflow with resize events that aren't processed */
|
||||
if (windowevent == SDL_WINDOWEVENT_RESIZED ||
|
||||
windowevent == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
SDL_FilterEvents(RemovePendingSizeEvents, &event);
|
||||
}
|
||||
if (windowevent == SDL_WINDOWEVENT_MOVED) {
|
||||
SDL_FilterEvents(RemovePendingMoveEvents, &event);
|
||||
}
|
||||
|
||||
posted = (SDL_PushEvent(&event) > 0);
|
||||
}
|
||||
|
||||
if (windowevent == SDL_WINDOWEVENT_CLOSE) {
|
||||
if ( !window->prev && !window->next ) {
|
||||
// This is the last window in the list so send the SDL_QUIT event
|
||||
SDL_SendQuit();
|
||||
}
|
||||
}
|
||||
|
||||
return (posted);
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
31
thirdparty/SDL/src/events/SDL_windowevents_c.h
vendored
Normal file
31
thirdparty/SDL/src/events/SDL_windowevents_c.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
#ifndef _SDL_windowevents_c_h
|
||||
#define _SDL_windowevents_c_h
|
||||
|
||||
extern int SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent,
|
||||
int data1, int data2);
|
||||
|
||||
#endif /* _SDL_windowevents_c_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
33
thirdparty/SDL/src/events/blank_cursor.h
vendored
Normal file
33
thirdparty/SDL/src/events/blank_cursor.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* A default blank 8x8 cursor */
|
||||
|
||||
#define BLANK_CWIDTH 8
|
||||
#define BLANK_CHEIGHT 8
|
||||
#define BLANK_CHOTX 0
|
||||
#define BLANK_CHOTY 0
|
||||
|
||||
static const unsigned char blank_cdata[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static const unsigned char blank_cmask[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
114
thirdparty/SDL/src/events/default_cursor.h
vendored
Normal file
114
thirdparty/SDL/src/events/default_cursor.h
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Default cursor - it happens to be the Mac cursor, but could be anything */
|
||||
|
||||
#define DEFAULT_CWIDTH 16
|
||||
#define DEFAULT_CHEIGHT 16
|
||||
#define DEFAULT_CHOTX 0
|
||||
#define DEFAULT_CHOTY 0
|
||||
|
||||
/* Added a real MacOS cursor, at the request of Luc-Olivier de Charrière */
|
||||
#define USE_MACOS_CURSOR
|
||||
|
||||
#ifdef USE_MACOS_CURSOR
|
||||
|
||||
static const unsigned char default_cdata[] = {
|
||||
0x00, 0x00,
|
||||
0x40, 0x00,
|
||||
0x60, 0x00,
|
||||
0x70, 0x00,
|
||||
0x78, 0x00,
|
||||
0x7C, 0x00,
|
||||
0x7E, 0x00,
|
||||
0x7F, 0x00,
|
||||
0x7F, 0x80,
|
||||
0x7C, 0x00,
|
||||
0x6C, 0x00,
|
||||
0x46, 0x00,
|
||||
0x06, 0x00,
|
||||
0x03, 0x00,
|
||||
0x03, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char default_cmask[] = {
|
||||
0xC0, 0x00,
|
||||
0xE0, 0x00,
|
||||
0xF0, 0x00,
|
||||
0xF8, 0x00,
|
||||
0xFC, 0x00,
|
||||
0xFE, 0x00,
|
||||
0xFF, 0x00,
|
||||
0xFF, 0x80,
|
||||
0xFF, 0xC0,
|
||||
0xFF, 0xE0,
|
||||
0xFE, 0x00,
|
||||
0xEF, 0x00,
|
||||
0xCF, 0x00,
|
||||
0x87, 0x80,
|
||||
0x07, 0x80,
|
||||
0x03, 0x00
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
static const unsigned char default_cdata[] = {
|
||||
0x00, 0x00,
|
||||
0x40, 0x00,
|
||||
0x60, 0x00,
|
||||
0x70, 0x00,
|
||||
0x78, 0x00,
|
||||
0x7C, 0x00,
|
||||
0x7E, 0x00,
|
||||
0x7F, 0x00,
|
||||
0x7F, 0x80,
|
||||
0x7C, 0x00,
|
||||
0x6C, 0x00,
|
||||
0x46, 0x00,
|
||||
0x06, 0x00,
|
||||
0x03, 0x00,
|
||||
0x03, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
static const unsigned char default_cmask[] = {
|
||||
0x40, 0x00,
|
||||
0xE0, 0x00,
|
||||
0xF0, 0x00,
|
||||
0xF8, 0x00,
|
||||
0xFC, 0x00,
|
||||
0xFE, 0x00,
|
||||
0xFF, 0x00,
|
||||
0xFF, 0x80,
|
||||
0xFF, 0xC0,
|
||||
0xFF, 0x80,
|
||||
0xFE, 0x00,
|
||||
0xEF, 0x00,
|
||||
0x4F, 0x00,
|
||||
0x07, 0x80,
|
||||
0x07, 0x80,
|
||||
0x03, 0x00
|
||||
};
|
||||
|
||||
#endif /* TRUE_MACINTOSH_CURSOR */
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
41
thirdparty/SDL/src/events/nds/SDL_ndsgesture.c
vendored
Normal file
41
thirdparty/SDL/src/events/nds/SDL_ndsgesture.c
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* No supported under the NDS because of math operations. */
|
||||
|
||||
#include "SDL_events.h"
|
||||
#include "../SDL_events_c.h"
|
||||
#include "../SDL_gesture_c.h"
|
||||
|
||||
int SDL_GestureAddTouch(SDL_Touch* touch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SDL_GestureProcessEvent(SDL_Event* event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
||||
159
thirdparty/SDL/src/events/scancodes_darwin.h
vendored
Normal file
159
thirdparty/SDL/src/events/scancodes_darwin.h
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* Mac virtual key code to SDL scancode mapping table
|
||||
Sources:
|
||||
- Inside Macintosh: Text <http://developer.apple.com/documentation/mac/Text/Text-571.html>
|
||||
- Apple USB keyboard driver source <http://darwinsource.opendarwin.org/10.4.6.ppc/IOHIDFamily-172.8/IOHIDFamily/Cosmo_USB2ADB.c>
|
||||
- experimentation on various ADB and USB ISO keyboards and one ADB ANSI keyboard
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
static const SDL_Scancode darwin_scancode_table[] = {
|
||||
/* 0 */ SDL_SCANCODE_A,
|
||||
/* 1 */ SDL_SCANCODE_S,
|
||||
/* 2 */ SDL_SCANCODE_D,
|
||||
/* 3 */ SDL_SCANCODE_F,
|
||||
/* 4 */ SDL_SCANCODE_H,
|
||||
/* 5 */ SDL_SCANCODE_G,
|
||||
/* 6 */ SDL_SCANCODE_Z,
|
||||
/* 7 */ SDL_SCANCODE_X,
|
||||
/* 8 */ SDL_SCANCODE_C,
|
||||
/* 9 */ SDL_SCANCODE_V,
|
||||
/* 10 */ SDL_SCANCODE_NONUSBACKSLASH, /* SDL_SCANCODE_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_SCANCODE_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard type when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.) */
|
||||
/* 11 */ SDL_SCANCODE_B,
|
||||
/* 12 */ SDL_SCANCODE_Q,
|
||||
/* 13 */ SDL_SCANCODE_W,
|
||||
/* 14 */ SDL_SCANCODE_E,
|
||||
/* 15 */ SDL_SCANCODE_R,
|
||||
/* 16 */ SDL_SCANCODE_Y,
|
||||
/* 17 */ SDL_SCANCODE_T,
|
||||
/* 18 */ SDL_SCANCODE_1,
|
||||
/* 19 */ SDL_SCANCODE_2,
|
||||
/* 20 */ SDL_SCANCODE_3,
|
||||
/* 21 */ SDL_SCANCODE_4,
|
||||
/* 22 */ SDL_SCANCODE_6,
|
||||
/* 23 */ SDL_SCANCODE_5,
|
||||
/* 24 */ SDL_SCANCODE_EQUALS,
|
||||
/* 25 */ SDL_SCANCODE_9,
|
||||
/* 26 */ SDL_SCANCODE_7,
|
||||
/* 27 */ SDL_SCANCODE_MINUS,
|
||||
/* 28 */ SDL_SCANCODE_8,
|
||||
/* 29 */ SDL_SCANCODE_0,
|
||||
/* 30 */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 31 */ SDL_SCANCODE_O,
|
||||
/* 32 */ SDL_SCANCODE_U,
|
||||
/* 33 */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 34 */ SDL_SCANCODE_I,
|
||||
/* 35 */ SDL_SCANCODE_P,
|
||||
/* 36 */ SDL_SCANCODE_RETURN,
|
||||
/* 37 */ SDL_SCANCODE_L,
|
||||
/* 38 */ SDL_SCANCODE_J,
|
||||
/* 39 */ SDL_SCANCODE_APOSTROPHE,
|
||||
/* 40 */ SDL_SCANCODE_K,
|
||||
/* 41 */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 42 */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 43 */ SDL_SCANCODE_COMMA,
|
||||
/* 44 */ SDL_SCANCODE_SLASH,
|
||||
/* 45 */ SDL_SCANCODE_N,
|
||||
/* 46 */ SDL_SCANCODE_M,
|
||||
/* 47 */ SDL_SCANCODE_PERIOD,
|
||||
/* 48 */ SDL_SCANCODE_TAB,
|
||||
/* 49 */ SDL_SCANCODE_SPACE,
|
||||
/* 50 */ SDL_SCANCODE_GRAVE, /* SDL_SCANCODE_GRAVE on ANSI and JIS keyboards, SDL_SCANCODE_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above) */
|
||||
/* 51 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 52 */ SDL_SCANCODE_KP_ENTER, /* keyboard enter on portables */
|
||||
/* 53 */ SDL_SCANCODE_ESCAPE,
|
||||
/* 54 */ SDL_SCANCODE_RGUI,
|
||||
/* 55 */ SDL_SCANCODE_LGUI,
|
||||
/* 56 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 57 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 58 */ SDL_SCANCODE_LALT,
|
||||
/* 59 */ SDL_SCANCODE_LCTRL,
|
||||
/* 60 */ SDL_SCANCODE_RSHIFT,
|
||||
/* 61 */ SDL_SCANCODE_RALT,
|
||||
/* 62 */ SDL_SCANCODE_RCTRL,
|
||||
/* 63 */ SDL_SCANCODE_RGUI, /* fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R */
|
||||
/* 64 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 65 */ SDL_SCANCODE_KP_PERIOD,
|
||||
/* 66 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 67 */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 68 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 69 */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 70 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 71 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 72 */ SDL_SCANCODE_VOLUMEUP,
|
||||
/* 73 */ SDL_SCANCODE_VOLUMEDOWN,
|
||||
/* 74 */ SDL_SCANCODE_MUTE,
|
||||
/* 75 */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 76 */ SDL_SCANCODE_KP_ENTER, /* keypad enter on external keyboards, fn-return on portables */
|
||||
/* 77 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 78 */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 79 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 80 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 81 */ SDL_SCANCODE_KP_EQUALS,
|
||||
/* 82 */ SDL_SCANCODE_KP_0,
|
||||
/* 83 */ SDL_SCANCODE_KP_1,
|
||||
/* 84 */ SDL_SCANCODE_KP_2,
|
||||
/* 85 */ SDL_SCANCODE_KP_3,
|
||||
/* 86 */ SDL_SCANCODE_KP_4,
|
||||
/* 87 */ SDL_SCANCODE_KP_5,
|
||||
/* 88 */ SDL_SCANCODE_KP_6,
|
||||
/* 89 */ SDL_SCANCODE_KP_7,
|
||||
/* 90 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 91 */ SDL_SCANCODE_KP_8,
|
||||
/* 92 */ SDL_SCANCODE_KP_9,
|
||||
/* 93 */ SDL_SCANCODE_INTERNATIONAL3, /* Cosmo_USB2ADB.c says "Yen (JIS)" */
|
||||
/* 94 */ SDL_SCANCODE_INTERNATIONAL1, /* Cosmo_USB2ADB.c says "Ro (JIS)" */
|
||||
/* 95 */ SDL_SCANCODE_KP_COMMA, /* Cosmo_USB2ADB.c says ", JIS only" */
|
||||
/* 96 */ SDL_SCANCODE_F5,
|
||||
/* 97 */ SDL_SCANCODE_F6,
|
||||
/* 98 */ SDL_SCANCODE_F7,
|
||||
/* 99 */ SDL_SCANCODE_F3,
|
||||
/* 100 */ SDL_SCANCODE_F8,
|
||||
/* 101 */ SDL_SCANCODE_F9,
|
||||
/* 102 */ SDL_SCANCODE_LANG2, /* Cosmo_USB2ADB.c says "Eisu" */
|
||||
/* 103 */ SDL_SCANCODE_F11,
|
||||
/* 104 */ SDL_SCANCODE_LANG1, /* Cosmo_USB2ADB.c says "Kana" */
|
||||
/* 105 */ SDL_SCANCODE_PRINTSCREEN, /* On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_SCANCODE_F13). I decided to use SDL_SCANCODE_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key. */
|
||||
/* 106 */ SDL_SCANCODE_F16,
|
||||
/* 107 */ SDL_SCANCODE_SCROLLLOCK, /* F14/scroll lock, see comment about F13/print screen above */
|
||||
/* 108 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 109 */ SDL_SCANCODE_F10,
|
||||
/* 110 */ SDL_SCANCODE_APPLICATION, /* windows contextual menu key, fn-enter on portables */
|
||||
/* 111 */ SDL_SCANCODE_F12,
|
||||
/* 112 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */
|
||||
/* 113 */ SDL_SCANCODE_PAUSE, /* F15/pause, see comment about F13/print screen above */
|
||||
/* 114 */ SDL_SCANCODE_INSERT, /* the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards */
|
||||
/* 115 */ SDL_SCANCODE_HOME,
|
||||
/* 116 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 117 */ SDL_SCANCODE_DELETE,
|
||||
/* 118 */ SDL_SCANCODE_F4,
|
||||
/* 119 */ SDL_SCANCODE_END,
|
||||
/* 120 */ SDL_SCANCODE_F2,
|
||||
/* 121 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 122 */ SDL_SCANCODE_F1,
|
||||
/* 123 */ SDL_SCANCODE_LEFT,
|
||||
/* 124 */ SDL_SCANCODE_RIGHT,
|
||||
/* 125 */ SDL_SCANCODE_DOWN,
|
||||
/* 126 */ SDL_SCANCODE_UP,
|
||||
/* 127 */ SDL_SCANCODE_POWER
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
263
thirdparty/SDL/src/events/scancodes_linux.h
vendored
Normal file
263
thirdparty/SDL/src/events/scancodes_linux.h
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 "../../include/SDL_scancode.h"
|
||||
|
||||
/* Linux virtual key code to SDL_Keycode mapping table
|
||||
Sources:
|
||||
- Linux kernel source input.h
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
static SDL_Scancode const linux_scancode_table[] = {
|
||||
/* 0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 1 */ SDL_SCANCODE_ESCAPE,
|
||||
/* 2 */ SDL_SCANCODE_1,
|
||||
/* 3 */ SDL_SCANCODE_2,
|
||||
/* 4 */ SDL_SCANCODE_3,
|
||||
/* 5 */ SDL_SCANCODE_4,
|
||||
/* 6 */ SDL_SCANCODE_5,
|
||||
/* 7 */ SDL_SCANCODE_6,
|
||||
/* 8 */ SDL_SCANCODE_7,
|
||||
/* 9 */ SDL_SCANCODE_8,
|
||||
/* 10 */ SDL_SCANCODE_9,
|
||||
/* 11 */ SDL_SCANCODE_0,
|
||||
/* 12 */ SDL_SCANCODE_MINUS,
|
||||
/* 13 */ SDL_SCANCODE_EQUALS,
|
||||
/* 14 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 15 */ SDL_SCANCODE_TAB,
|
||||
/* 16 */ SDL_SCANCODE_Q,
|
||||
/* 17 */ SDL_SCANCODE_W,
|
||||
/* 18 */ SDL_SCANCODE_E,
|
||||
/* 19 */ SDL_SCANCODE_R,
|
||||
/* 20 */ SDL_SCANCODE_T,
|
||||
/* 21 */ SDL_SCANCODE_Y,
|
||||
/* 22 */ SDL_SCANCODE_U,
|
||||
/* 23 */ SDL_SCANCODE_I,
|
||||
/* 24 */ SDL_SCANCODE_O,
|
||||
/* 25 */ SDL_SCANCODE_P,
|
||||
/* 26 */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 27 */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 28 */ SDL_SCANCODE_RETURN,
|
||||
/* 29 */ SDL_SCANCODE_LCTRL,
|
||||
/* 30 */ SDL_SCANCODE_A,
|
||||
/* 31 */ SDL_SCANCODE_S,
|
||||
/* 32 */ SDL_SCANCODE_D,
|
||||
/* 33 */ SDL_SCANCODE_F,
|
||||
/* 34 */ SDL_SCANCODE_G,
|
||||
/* 35 */ SDL_SCANCODE_H,
|
||||
/* 36 */ SDL_SCANCODE_J,
|
||||
/* 37 */ SDL_SCANCODE_K,
|
||||
/* 38 */ SDL_SCANCODE_L,
|
||||
/* 39 */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 40 */ SDL_SCANCODE_APOSTROPHE,
|
||||
/* 41 */ SDL_SCANCODE_GRAVE,
|
||||
/* 42 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 43 */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 44 */ SDL_SCANCODE_Z,
|
||||
/* 45 */ SDL_SCANCODE_X,
|
||||
/* 46 */ SDL_SCANCODE_C,
|
||||
/* 47 */ SDL_SCANCODE_V,
|
||||
/* 48 */ SDL_SCANCODE_B,
|
||||
/* 49 */ SDL_SCANCODE_N,
|
||||
/* 50 */ SDL_SCANCODE_M,
|
||||
/* 51 */ SDL_SCANCODE_COMMA,
|
||||
/* 52 */ SDL_SCANCODE_PERIOD,
|
||||
/* 53 */ SDL_SCANCODE_SLASH,
|
||||
/* 54 */ SDL_SCANCODE_RSHIFT,
|
||||
/* 55 */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 56 */ SDL_SCANCODE_LALT,
|
||||
/* 57 */ SDL_SCANCODE_SPACE,
|
||||
/* 58 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 59 */ SDL_SCANCODE_F1,
|
||||
/* 60 */ SDL_SCANCODE_F2,
|
||||
/* 61 */ SDL_SCANCODE_F3,
|
||||
/* 62 */ SDL_SCANCODE_F4,
|
||||
/* 63 */ SDL_SCANCODE_F5,
|
||||
/* 64 */ SDL_SCANCODE_F6,
|
||||
/* 65 */ SDL_SCANCODE_F7,
|
||||
/* 66 */ SDL_SCANCODE_F8,
|
||||
/* 67 */ SDL_SCANCODE_F9,
|
||||
/* 68 */ SDL_SCANCODE_F10,
|
||||
/* 69 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 70 */ SDL_SCANCODE_SCROLLLOCK,
|
||||
/* 71 */ SDL_SCANCODE_KP_7,
|
||||
/* 72 */ SDL_SCANCODE_KP_8,
|
||||
/* 73 */ SDL_SCANCODE_KP_9,
|
||||
/* 74 */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 75 */ SDL_SCANCODE_KP_4,
|
||||
/* 76 */ SDL_SCANCODE_KP_5,
|
||||
/* 77 */ SDL_SCANCODE_KP_6,
|
||||
/* 78 */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 79 */ SDL_SCANCODE_KP_1,
|
||||
/* 80 */ SDL_SCANCODE_KP_2,
|
||||
/* 81 */ SDL_SCANCODE_KP_3,
|
||||
/* 82 */ SDL_SCANCODE_KP_0,
|
||||
/* 83 */ SDL_SCANCODE_KP_PERIOD,
|
||||
0,
|
||||
/* 85 */ SDL_SCANCODE_UNKNOWN, /* KEY_ZENKAKUHANKAKU */
|
||||
/* 86 */ SDL_SCANCODE_NONUSBACKSLASH, /* KEY_102ND */
|
||||
/* 87 */ SDL_SCANCODE_F11,
|
||||
/* 88 */ SDL_SCANCODE_F12,
|
||||
/* 89 */ SDL_SCANCODE_INTERNATIONAL1, /* KEY_RO */
|
||||
/* 90 */ SDL_SCANCODE_LANG3, /* KEY_KATAKANA */
|
||||
/* 91 */ SDL_SCANCODE_LANG4, /* KEY_HIRAGANA */
|
||||
/* 92 */ SDL_SCANCODE_INTERNATIONAL4, /* KEY_HENKAN */
|
||||
/* 93 */ SDL_SCANCODE_INTERNATIONAL2, /* KEY_KATAKANAHIRAGANA */
|
||||
/* 94 */ SDL_SCANCODE_INTERNATIONAL5, /* KEY_MUHENKAN */
|
||||
/* 95 */ SDL_SCANCODE_INTERNATIONAL5, /* KEY_KPJPCOMMA */
|
||||
/* 96 */ SDL_SCANCODE_KP_ENTER,
|
||||
/* 97 */ SDL_SCANCODE_RCTRL,
|
||||
/* 98 */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 99 */ SDL_SCANCODE_SYSREQ,
|
||||
/* 100 */ SDL_SCANCODE_RALT,
|
||||
/* 101 */ SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED */
|
||||
/* 102 */ SDL_SCANCODE_HOME,
|
||||
/* 103 */ SDL_SCANCODE_UP,
|
||||
/* 104 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 105 */ SDL_SCANCODE_LEFT,
|
||||
/* 106 */ SDL_SCANCODE_RIGHT,
|
||||
/* 107 */ SDL_SCANCODE_END,
|
||||
/* 108 */ SDL_SCANCODE_DOWN,
|
||||
/* 109 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 110 */ SDL_SCANCODE_INSERT,
|
||||
/* 111 */ SDL_SCANCODE_DELETE,
|
||||
/* 112 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO */
|
||||
/* 113 */ SDL_SCANCODE_MUTE,
|
||||
/* 114 */ SDL_SCANCODE_VOLUMEDOWN,
|
||||
/* 115 */ SDL_SCANCODE_VOLUMEUP,
|
||||
/* 116 */ SDL_SCANCODE_POWER,
|
||||
/* 117 */ SDL_SCANCODE_KP_EQUALS,
|
||||
/* 118 */ SDL_SCANCODE_KP_PLUSMINUS,
|
||||
/* 119 */ SDL_SCANCODE_PAUSE,
|
||||
0,
|
||||
/* 121 */ SDL_SCANCODE_KP_COMMA,
|
||||
/* 122 */ SDL_SCANCODE_LANG1, /* KEY_HANGUEL */
|
||||
/* 123 */ SDL_SCANCODE_LANG2, /* KEY_HANJA */
|
||||
/* 124 */ SDL_SCANCODE_INTERNATIONAL3, /* KEY_YEN */
|
||||
/* 125 */ SDL_SCANCODE_LGUI,
|
||||
/* 126 */ SDL_SCANCODE_RGUI,
|
||||
/* 127 */ SDL_SCANCODE_UNKNOWN, /* KEY_COMPOSE */
|
||||
/* 128 */ SDL_SCANCODE_STOP,
|
||||
/* 129 */ SDL_SCANCODE_AGAIN,
|
||||
/* 130 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROPS */
|
||||
/* 131 */ SDL_SCANCODE_UNDO,
|
||||
/* 132 */ SDL_SCANCODE_UNKNOWN, /* KEY_FRONT */
|
||||
/* 133 */ SDL_SCANCODE_COPY,
|
||||
/* 134 */ SDL_SCANCODE_UNKNOWN, /* KEY_OPEN */
|
||||
/* 135 */ SDL_SCANCODE_PASTE,
|
||||
/* 136 */ SDL_SCANCODE_FIND,
|
||||
/* 137 */ SDL_SCANCODE_CUT,
|
||||
/* 138 */ SDL_SCANCODE_HELP,
|
||||
/* 139 */ SDL_SCANCODE_MENU,
|
||||
/* 140 */ SDL_SCANCODE_CALCULATOR,
|
||||
/* 141 */ SDL_SCANCODE_UNKNOWN, /* KEY_SETUP */
|
||||
/* 142 */ SDL_SCANCODE_SLEEP,
|
||||
/* 143 */ SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP */
|
||||
/* 144 */ SDL_SCANCODE_UNKNOWN, /* KEY_FILE */
|
||||
/* 145 */ SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE */
|
||||
/* 146 */ SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE */
|
||||
/* 147 */ SDL_SCANCODE_UNKNOWN, /* KEY_XFER */
|
||||
/* 148 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG1 */
|
||||
/* 149 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG2 */
|
||||
/* 150 */ SDL_SCANCODE_UNKNOWN, /* KEY_WWW */
|
||||
/* 151 */ SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS */
|
||||
/* 152 */ SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE */
|
||||
/* 153 */ SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION */
|
||||
/* 154 */ SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS */
|
||||
/* 155 */ SDL_SCANCODE_MAIL,
|
||||
/* 156 */ SDL_SCANCODE_AC_BOOKMARKS,
|
||||
/* 157 */ SDL_SCANCODE_COMPUTER,
|
||||
/* 158 */ SDL_SCANCODE_AC_BACK,
|
||||
/* 159 */ SDL_SCANCODE_AC_FORWARD,
|
||||
/* 160 */ SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD */
|
||||
/* 161 */ SDL_SCANCODE_EJECT, /* KEY_EJECTCD */
|
||||
/* 162 */ SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD */
|
||||
/* 163 */ SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG */
|
||||
/* 164 */ SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE */
|
||||
/* 165 */ SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG */
|
||||
/* 166 */ SDL_SCANCODE_UNKNOWN, /* KEY_STOPCD */
|
||||
/* 167 */ SDL_SCANCODE_UNKNOWN, /* KEY_RECORD */
|
||||
/* 168 */ SDL_SCANCODE_UNKNOWN, /* KEY_REWIND */
|
||||
/* 169 */ SDL_SCANCODE_UNKNOWN, /* KEY_PHONE */
|
||||
/* 170 */ SDL_SCANCODE_UNKNOWN, /* KEY_ISO */
|
||||
/* 171 */ SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG */
|
||||
/* 172 */ SDL_SCANCODE_AC_HOME,
|
||||
/* 173 */ SDL_SCANCODE_AC_REFRESH,
|
||||
/* 174 */ SDL_SCANCODE_UNKNOWN, /* KEY_EXIT */
|
||||
/* 175 */ SDL_SCANCODE_UNKNOWN, /* KEY_MOVE */
|
||||
/* 176 */ SDL_SCANCODE_UNKNOWN, /* KEY_EDIT */
|
||||
/* 177 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP */
|
||||
/* 178 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN */
|
||||
/* 179 */ SDL_SCANCODE_KP_LEFTPAREN,
|
||||
/* 180 */ SDL_SCANCODE_KP_RIGHTPAREN,
|
||||
/* 181 */ SDL_SCANCODE_UNKNOWN, /* KEY_NEW */
|
||||
/* 182 */ SDL_SCANCODE_UNKNOWN, /* KEY_REDO */
|
||||
/* 183 */ SDL_SCANCODE_F13,
|
||||
/* 184 */ SDL_SCANCODE_F14,
|
||||
/* 185 */ SDL_SCANCODE_F15,
|
||||
/* 186 */ SDL_SCANCODE_F16,
|
||||
/* 187 */ SDL_SCANCODE_F17,
|
||||
/* 188 */ SDL_SCANCODE_F18,
|
||||
/* 189 */ SDL_SCANCODE_F19,
|
||||
/* 190 */ SDL_SCANCODE_F20,
|
||||
/* 191 */ SDL_SCANCODE_F21,
|
||||
/* 192 */ SDL_SCANCODE_F22,
|
||||
/* 193 */ SDL_SCANCODE_F23,
|
||||
/* 194 */ SDL_SCANCODE_F24,
|
||||
0, 0, 0, 0,
|
||||
/* 200 */ SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD */
|
||||
/* 201 */ SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD */
|
||||
/* 202 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 */
|
||||
/* 203 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 */
|
||||
0,
|
||||
/* 205 */ SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND */
|
||||
/* 206 */ SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE */
|
||||
/* 207 */ SDL_SCANCODE_UNKNOWN, /* KEY_PLAY */
|
||||
/* 208 */ SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD */
|
||||
/* 209 */ SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST */
|
||||
/* 210 */ SDL_SCANCODE_UNKNOWN, /* KEY_PRINT */
|
||||
/* 211 */ SDL_SCANCODE_UNKNOWN, /* KEY_HP */
|
||||
/* 212 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA */
|
||||
/* 213 */ SDL_SCANCODE_UNKNOWN, /* KEY_SOUND */
|
||||
/* 214 */ SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION */
|
||||
/* 215 */ SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL */
|
||||
/* 216 */ SDL_SCANCODE_UNKNOWN, /* KEY_CHAT */
|
||||
/* 217 */ SDL_SCANCODE_AC_SEARCH,
|
||||
/* 218 */ SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT */
|
||||
/* 219 */ SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE */
|
||||
/* 220 */ SDL_SCANCODE_UNKNOWN, /* KEY_SPORT */
|
||||
/* 221 */ SDL_SCANCODE_UNKNOWN, /* KEY_SHOP */
|
||||
/* 222 */ SDL_SCANCODE_ALTERASE,
|
||||
/* 223 */ SDL_SCANCODE_CANCEL,
|
||||
/* 224 */ SDL_SCANCODE_BRIGHTNESSDOWN,
|
||||
/* 225 */ SDL_SCANCODE_BRIGHTNESSUP,
|
||||
/* 226 */ SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA */
|
||||
/* 227 */ SDL_SCANCODE_DISPLAYSWITCH, /* KEY_SWITCHVIDEOMODE */
|
||||
/* 228 */ SDL_SCANCODE_KBDILLUMTOGGLE,
|
||||
/* 229 */ SDL_SCANCODE_KBDILLUMDOWN,
|
||||
/* 230 */ SDL_SCANCODE_KBDILLUMUP,
|
||||
/* 231 */ SDL_SCANCODE_UNKNOWN, /* KEY_SEND */
|
||||
/* 232 */ SDL_SCANCODE_UNKNOWN, /* KEY_REPLY */
|
||||
/* 233 */ SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL */
|
||||
/* 234 */ SDL_SCANCODE_UNKNOWN, /* KEY_SAVE */
|
||||
/* 235 */ SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS */
|
||||
/* 236 */ SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY */
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
286
thirdparty/SDL/src/events/scancodes_windows.h
vendored
Normal file
286
thirdparty/SDL/src/events/scancodes_windows.h
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 "../../include/SDL_scancode.h"
|
||||
|
||||
/* Win32 virtual key code to SDL scancode mapping table
|
||||
Sources:
|
||||
- msdn.microsoft.com
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
static const SDL_Scancode windows_scancode_table[] = {
|
||||
/* 0, 0x00 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 1, 0x01 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 2, 0x02 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 3, 0x03 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 4, 0x04 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 5, 0x05 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 6, 0x06 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 7, 0x07 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 8, 0x08 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 9, 0x09 */ SDL_SCANCODE_TAB,
|
||||
/* 10, 0x0a */ SDL_SCANCODE_KP_ENTER, /* Not a VKEY, SDL specific */
|
||||
/* 11, 0x0b */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 12, 0x0c */ SDL_SCANCODE_CLEAR,
|
||||
/* 13, 0x0d */ SDL_SCANCODE_RETURN,
|
||||
/* 14, 0x0e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 15, 0x0f */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 16, 0x10 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 17, 0x11 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 18, 0x12 */ SDL_SCANCODE_APPLICATION,
|
||||
/* 19, 0x13 */ SDL_SCANCODE_PAUSE,
|
||||
/* 20, 0x14 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 21, 0x15 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 22, 0x16 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 23, 0x17 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 24, 0x18 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 25, 0x19 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 26, 0x1a */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 27, 0x1b */ SDL_SCANCODE_ESCAPE,
|
||||
/* 28, 0x1c */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 29, 0x1d */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 30, 0x1e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 31, 0x1f */ SDL_SCANCODE_MODE,
|
||||
/* 32, 0x20 */ SDL_SCANCODE_SPACE,
|
||||
/* 33, 0x21 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 34, 0x22 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 35, 0x23 */ SDL_SCANCODE_END,
|
||||
/* 36, 0x24 */ SDL_SCANCODE_HOME,
|
||||
/* 37, 0x25 */ SDL_SCANCODE_LEFT,
|
||||
/* 38, 0x26 */ SDL_SCANCODE_UP,
|
||||
/* 39, 0x27 */ SDL_SCANCODE_RIGHT,
|
||||
/* 40, 0x28 */ SDL_SCANCODE_DOWN,
|
||||
/* 41, 0x29 */ SDL_SCANCODE_SELECT,
|
||||
/* 42, 0x2a */ SDL_SCANCODE_UNKNOWN, /* VK_PRINT */
|
||||
/* 43, 0x2b */ SDL_SCANCODE_EXECUTE,
|
||||
/* 44, 0x2c */ SDL_SCANCODE_PRINTSCREEN,
|
||||
/* 45, 0x2d */ SDL_SCANCODE_INSERT,
|
||||
/* 46, 0x2e */ SDL_SCANCODE_DELETE,
|
||||
/* 47, 0x2f */ SDL_SCANCODE_HELP,
|
||||
/* 48, 0x30 */ SDL_SCANCODE_0,
|
||||
/* 49, 0x31 */ SDL_SCANCODE_1,
|
||||
/* 50, 0x32 */ SDL_SCANCODE_2,
|
||||
/* 51, 0x33 */ SDL_SCANCODE_3,
|
||||
/* 52, 0x34 */ SDL_SCANCODE_4,
|
||||
/* 53, 0x35 */ SDL_SCANCODE_5,
|
||||
/* 54, 0x36 */ SDL_SCANCODE_6,
|
||||
/* 55, 0x37 */ SDL_SCANCODE_7,
|
||||
/* 56, 0x38 */ SDL_SCANCODE_8,
|
||||
/* 57, 0x39 */ SDL_SCANCODE_9,
|
||||
/* 58, 0x3a */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 59, 0x3b */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 60, 0x3c */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 61, 0x3d */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 62, 0x3e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 63, 0x3f */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 64, 0x40 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 65, 0x41 */ SDL_SCANCODE_A,
|
||||
/* 66, 0x42 */ SDL_SCANCODE_B,
|
||||
/* 67, 0x43 */ SDL_SCANCODE_C,
|
||||
/* 68, 0x44 */ SDL_SCANCODE_D,
|
||||
/* 69, 0x45 */ SDL_SCANCODE_E,
|
||||
/* 70, 0x46 */ SDL_SCANCODE_F,
|
||||
/* 71, 0x47 */ SDL_SCANCODE_G,
|
||||
/* 72, 0x48 */ SDL_SCANCODE_H,
|
||||
/* 73, 0x49 */ SDL_SCANCODE_I,
|
||||
/* 74, 0x4a */ SDL_SCANCODE_J,
|
||||
/* 75, 0x4b */ SDL_SCANCODE_K,
|
||||
/* 76, 0x4c */ SDL_SCANCODE_L,
|
||||
/* 77, 0x4d */ SDL_SCANCODE_M,
|
||||
/* 78, 0x4e */ SDL_SCANCODE_N,
|
||||
/* 79, 0x4f */ SDL_SCANCODE_O,
|
||||
/* 80, 0x50 */ SDL_SCANCODE_P,
|
||||
/* 81, 0x51 */ SDL_SCANCODE_Q,
|
||||
/* 82, 0x52 */ SDL_SCANCODE_R,
|
||||
/* 83, 0x53 */ SDL_SCANCODE_S,
|
||||
/* 84, 0x54 */ SDL_SCANCODE_T,
|
||||
/* 85, 0x55 */ SDL_SCANCODE_U,
|
||||
/* 86, 0x56 */ SDL_SCANCODE_V,
|
||||
/* 87, 0x57 */ SDL_SCANCODE_W,
|
||||
/* 88, 0x58 */ SDL_SCANCODE_X,
|
||||
/* 89, 0x59 */ SDL_SCANCODE_Y,
|
||||
/* 90, 0x5a */ SDL_SCANCODE_Z,
|
||||
/* 91, 0x5b */ SDL_SCANCODE_LGUI,
|
||||
/* 92, 0x5c */ SDL_SCANCODE_RGUI,
|
||||
/* 93, 0x5d */ SDL_SCANCODE_APPLICATION,
|
||||
/* 94, 0x5e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 95, 0x5f */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 96, 0x60 */ SDL_SCANCODE_KP_0,
|
||||
/* 97, 0x61 */ SDL_SCANCODE_KP_1,
|
||||
/* 98, 0x62 */ SDL_SCANCODE_KP_2,
|
||||
/* 99, 0x63 */ SDL_SCANCODE_KP_3,
|
||||
/* 100, 0x64 */ SDL_SCANCODE_KP_4,
|
||||
/* 101, 0x65 */ SDL_SCANCODE_KP_5,
|
||||
/* 102, 0x66 */ SDL_SCANCODE_KP_6,
|
||||
/* 103, 0x67 */ SDL_SCANCODE_KP_7,
|
||||
/* 104, 0x68 */ SDL_SCANCODE_KP_8,
|
||||
/* 105, 0x69 */ SDL_SCANCODE_KP_9,
|
||||
/* 106, 0x6a */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 107, 0x6b */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 108, 0x6c */ SDL_SCANCODE_SEPARATOR,
|
||||
/* 109, 0x6d */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 110, 0x6e */ SDL_SCANCODE_KP_DECIMAL,
|
||||
/* 111, 0x6f */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 112, 0x70 */ SDL_SCANCODE_F1,
|
||||
/* 113, 0x71 */ SDL_SCANCODE_F2,
|
||||
/* 114, 0x72 */ SDL_SCANCODE_F3,
|
||||
/* 115, 0x73 */ SDL_SCANCODE_F4,
|
||||
/* 116, 0x74 */ SDL_SCANCODE_F5,
|
||||
/* 117, 0x75 */ SDL_SCANCODE_F6,
|
||||
/* 118, 0x76 */ SDL_SCANCODE_F7,
|
||||
/* 119, 0x77 */ SDL_SCANCODE_F8,
|
||||
/* 120, 0x78 */ SDL_SCANCODE_F9,
|
||||
/* 121, 0x79 */ SDL_SCANCODE_F10,
|
||||
/* 122, 0x7a */ SDL_SCANCODE_F11,
|
||||
/* 123, 0x7b */ SDL_SCANCODE_F12,
|
||||
/* 124, 0x7c */ SDL_SCANCODE_F13,
|
||||
/* 125, 0x7d */ SDL_SCANCODE_F14,
|
||||
/* 126, 0x7e */ SDL_SCANCODE_F15,
|
||||
/* 127, 0x7f */ SDL_SCANCODE_F16,
|
||||
/* 128, 0x80 */ SDL_SCANCODE_F17, /* or SDL_SCANCODE_AUDIONEXT */
|
||||
/* 129, 0x81 */ SDL_SCANCODE_F18, /* or SDL_SCANCODE_AUDIOPREV */
|
||||
/* 130, 0x82 */ SDL_SCANCODE_F19, /* or SDL_SCANCODE_AUDIOSTOP */
|
||||
/* 131, 0x83 */ SDL_SCANCODE_F20, /* or SDL_SCANCODE_AUDIOPLAY */
|
||||
/* 132, 0x84 */ SDL_SCANCODE_F21, /* or SDL_SCANCODE_MAIL */
|
||||
/* 133, 0x85 */ SDL_SCANCODE_F22, /* or SDL_SCANCODE_MEDIASELECT */
|
||||
/* 134, 0x86 */ SDL_SCANCODE_F23, /* or SDL_SCANCODE_WWW */
|
||||
/* 135, 0x87 */ SDL_SCANCODE_F24, /* or SDL_SCANCODE_CALCULATOR */
|
||||
/* 136, 0x88 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 137, 0x89 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 138, 0x8a */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 139, 0x8b */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 140, 0x8c */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 141, 0x8d */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 142, 0x8e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 143, 0x8f */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 144, 0x90 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 145, 0x91 */ SDL_SCANCODE_SCROLLLOCK,
|
||||
/* 146, 0x92 */ SDL_SCANCODE_KP_EQUALS,
|
||||
/* 147, 0x93 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 148, 0x94 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 149, 0x95 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 150, 0x96 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 151, 0x97 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 152, 0x98 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 153, 0x99 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 154, 0x9a */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 155, 0x9b */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 156, 0x9c */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 157, 0x9d */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 158, 0x9e */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 159, 0x9f */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 160, 0xa0 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 161, 0xa1 */ SDL_SCANCODE_RSHIFT,
|
||||
/* 162, 0xa2 */ SDL_SCANCODE_LCTRL,
|
||||
/* 163, 0xa3 */ SDL_SCANCODE_RCTRL,
|
||||
/* 164, 0xa4 */ SDL_SCANCODE_LALT,
|
||||
/* 165, 0xa5 */ SDL_SCANCODE_RALT,
|
||||
/* 166, 0xa6 */ SDL_SCANCODE_AC_BACK,
|
||||
/* 167, 0xa7 */ SDL_SCANCODE_AC_FORWARD,
|
||||
/* 168, 0xa8 */ SDL_SCANCODE_AC_REFRESH,
|
||||
/* 169, 0xa9 */ SDL_SCANCODE_AC_STOP,
|
||||
/* 170, 0xaa */ SDL_SCANCODE_AC_SEARCH,
|
||||
/* 171, 0xab */ SDL_SCANCODE_AC_BOOKMARKS,
|
||||
/* 172, 0xac */ SDL_SCANCODE_AC_HOME,
|
||||
/* 173, 0xad */ SDL_SCANCODE_AUDIOMUTE,
|
||||
/* 174, 0xae */ SDL_SCANCODE_VOLUMEDOWN,
|
||||
/* 175, 0xaf */ SDL_SCANCODE_VOLUMEUP,
|
||||
/* 176, 0xb0 */ SDL_SCANCODE_AUDIONEXT,
|
||||
/* 177, 0xb1 */ SDL_SCANCODE_AUDIOPREV,
|
||||
/* 178, 0xb2 */ SDL_SCANCODE_AUDIOSTOP,
|
||||
/* 179, 0xb3 */ SDL_SCANCODE_AUDIOPLAY,
|
||||
/* 180, 0xb4 */ SDL_SCANCODE_MAIL,
|
||||
/* 181, 0xb5 */ SDL_SCANCODE_MEDIASELECT,
|
||||
/* 182, 0xb6 */ SDL_SCANCODE_UNKNOWN, /* VK_LAUNCH_APP1 */
|
||||
/* 183, 0xb7 */ SDL_SCANCODE_UNKNOWN, /* VK_LAUNCH_APP2 */
|
||||
/* 184, 0xb8 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 185, 0xb9 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 186, 0xba */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 187, 0xbb */ SDL_SCANCODE_EQUALS,
|
||||
/* 188, 0xbc */ SDL_SCANCODE_COMMA,
|
||||
/* 189, 0xbd */ SDL_SCANCODE_MINUS,
|
||||
/* 190, 0xbe */ SDL_SCANCODE_PERIOD,
|
||||
/* 191, 0xbf */ SDL_SCANCODE_SLASH,
|
||||
/* 192, 0xc0 */ SDL_SCANCODE_GRAVE,
|
||||
/* 193, 0xc1 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 194, 0xc2 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 195, 0xc3 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 196, 0xc4 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 197, 0xc5 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 198, 0xc6 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 199, 0xc7 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 200, 0xc8 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 201, 0xc9 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 202, 0xca */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 203, 0xcb */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 204, 0xcc */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 205, 0xcd */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 206, 0xce */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 207, 0xcf */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 208, 0xd0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 209, 0xd1 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 210, 0xd2 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 211, 0xd3 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 212, 0xd4 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 213, 0xd5 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 214, 0xd6 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 215, 0xd7 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 216, 0xd8 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 217, 0xd9 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 218, 0xda */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 219, 0xdb */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 220, 0xdc */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 221, 0xdd */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 222, 0xde */ SDL_SCANCODE_APOSTROPHE,
|
||||
/* 223, 0xdf */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 224, 0xe0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 225, 0xe1 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 226, 0xe2 */ SDL_SCANCODE_NONUSBACKSLASH,
|
||||
/* 227, 0xe3 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 228, 0xe4 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 229, 0xe5 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 230, 0xe6 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 231, 0xe7 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 232, 0xe8 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 233, 0xe9 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 234, 0xea */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 235, 0xeb */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 236, 0xec */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 237, 0xed */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 238, 0xee */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 239, 0xef */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 240, 0xf0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 241, 0xf1 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 242, 0xf2 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 243, 0xf3 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 244, 0xf4 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 245, 0xf5 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 246, 0xf6 */ SDL_SCANCODE_SYSREQ,
|
||||
/* 247, 0xf7 */ SDL_SCANCODE_CRSEL,
|
||||
/* 248, 0xf8 */ SDL_SCANCODE_EXSEL,
|
||||
/* 249, 0xf9 */ SDL_SCANCODE_UNKNOWN, /* VK_EREOF */
|
||||
/* 250, 0xfa */ SDL_SCANCODE_UNKNOWN, /* VK_PLAY */
|
||||
/* 251, 0xfb */ SDL_SCANCODE_UNKNOWN, /* VK_ZOOM */
|
||||
/* 252, 0xfc */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 253, 0xfd */ SDL_SCANCODE_UNKNOWN, /* VK_PA1 */
|
||||
/* 254, 0xfe */ SDL_SCANCODE_CLEAR,
|
||||
/* 255, 0xff */ SDL_SCANCODE_UNKNOWN,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
421
thirdparty/SDL/src/events/scancodes_xfree86.h
vendored
Normal file
421
thirdparty/SDL/src/events/scancodes_xfree86.h
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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 "../../include/SDL_scancode.h"
|
||||
|
||||
/* XFree86 key code to SDL scancode mapping table
|
||||
Sources:
|
||||
- atKeyNames.h from XFree86 source code
|
||||
*/
|
||||
/* *INDENT-OFF* */
|
||||
static const SDL_Scancode xfree86_scancode_table[] = {
|
||||
/* 0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 1 */ SDL_SCANCODE_ESCAPE,
|
||||
/* 2 */ SDL_SCANCODE_1,
|
||||
/* 3 */ SDL_SCANCODE_2,
|
||||
/* 4 */ SDL_SCANCODE_3,
|
||||
/* 5 */ SDL_SCANCODE_4,
|
||||
/* 6 */ SDL_SCANCODE_5,
|
||||
/* 7 */ SDL_SCANCODE_6,
|
||||
/* 8 */ SDL_SCANCODE_7,
|
||||
/* 9 */ SDL_SCANCODE_8,
|
||||
/* 10 */ SDL_SCANCODE_9,
|
||||
/* 11 */ SDL_SCANCODE_0,
|
||||
/* 12 */ SDL_SCANCODE_MINUS,
|
||||
/* 13 */ SDL_SCANCODE_EQUALS,
|
||||
/* 14 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 15 */ SDL_SCANCODE_TAB,
|
||||
/* 16 */ SDL_SCANCODE_Q,
|
||||
/* 17 */ SDL_SCANCODE_W,
|
||||
/* 18 */ SDL_SCANCODE_E,
|
||||
/* 19 */ SDL_SCANCODE_R,
|
||||
/* 20 */ SDL_SCANCODE_T,
|
||||
/* 21 */ SDL_SCANCODE_Y,
|
||||
/* 22 */ SDL_SCANCODE_U,
|
||||
/* 23 */ SDL_SCANCODE_I,
|
||||
/* 24 */ SDL_SCANCODE_O,
|
||||
/* 25 */ SDL_SCANCODE_P,
|
||||
/* 26 */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 27 */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 28 */ SDL_SCANCODE_RETURN,
|
||||
/* 29 */ SDL_SCANCODE_LCTRL,
|
||||
/* 30 */ SDL_SCANCODE_A,
|
||||
/* 31 */ SDL_SCANCODE_S,
|
||||
/* 32 */ SDL_SCANCODE_D,
|
||||
/* 33 */ SDL_SCANCODE_F,
|
||||
/* 34 */ SDL_SCANCODE_G,
|
||||
/* 35 */ SDL_SCANCODE_H,
|
||||
/* 36 */ SDL_SCANCODE_J,
|
||||
/* 37 */ SDL_SCANCODE_K,
|
||||
/* 38 */ SDL_SCANCODE_L,
|
||||
/* 39 */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 40 */ SDL_SCANCODE_APOSTROPHE,
|
||||
/* 41 */ SDL_SCANCODE_GRAVE,
|
||||
/* 42 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 43 */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 44 */ SDL_SCANCODE_Z,
|
||||
/* 45 */ SDL_SCANCODE_X,
|
||||
/* 46 */ SDL_SCANCODE_C,
|
||||
/* 47 */ SDL_SCANCODE_V,
|
||||
/* 48 */ SDL_SCANCODE_B,
|
||||
/* 49 */ SDL_SCANCODE_N,
|
||||
/* 50 */ SDL_SCANCODE_M,
|
||||
/* 51 */ SDL_SCANCODE_COMMA,
|
||||
/* 52 */ SDL_SCANCODE_PERIOD,
|
||||
/* 53 */ SDL_SCANCODE_SLASH,
|
||||
/* 54 */ SDL_SCANCODE_RSHIFT,
|
||||
/* 55 */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 56 */ SDL_SCANCODE_LALT,
|
||||
/* 57 */ SDL_SCANCODE_SPACE,
|
||||
/* 58 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 59 */ SDL_SCANCODE_F1,
|
||||
/* 60 */ SDL_SCANCODE_F2,
|
||||
/* 61 */ SDL_SCANCODE_F3,
|
||||
/* 62 */ SDL_SCANCODE_F4,
|
||||
/* 63 */ SDL_SCANCODE_F5,
|
||||
/* 64 */ SDL_SCANCODE_F6,
|
||||
/* 65 */ SDL_SCANCODE_F7,
|
||||
/* 66 */ SDL_SCANCODE_F8,
|
||||
/* 67 */ SDL_SCANCODE_F9,
|
||||
/* 68 */ SDL_SCANCODE_F10,
|
||||
/* 69 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 70 */ SDL_SCANCODE_SCROLLLOCK,
|
||||
/* 71 */ SDL_SCANCODE_KP_7,
|
||||
/* 72 */ SDL_SCANCODE_KP_8,
|
||||
/* 73 */ SDL_SCANCODE_KP_9,
|
||||
/* 74 */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 75 */ SDL_SCANCODE_KP_4,
|
||||
/* 76 */ SDL_SCANCODE_KP_5,
|
||||
/* 77 */ SDL_SCANCODE_KP_6,
|
||||
/* 78 */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 79 */ SDL_SCANCODE_KP_1,
|
||||
/* 80 */ SDL_SCANCODE_KP_2,
|
||||
/* 81 */ SDL_SCANCODE_KP_3,
|
||||
/* 82 */ SDL_SCANCODE_KP_0,
|
||||
/* 83 */ SDL_SCANCODE_KP_PERIOD,
|
||||
/* 84 */ SDL_SCANCODE_SYSREQ,
|
||||
/* 85 */ SDL_SCANCODE_MODE,
|
||||
/* 86 */ SDL_SCANCODE_NONUSBACKSLASH,
|
||||
/* 87 */ SDL_SCANCODE_F11,
|
||||
/* 88 */ SDL_SCANCODE_F12,
|
||||
/* 89 */ SDL_SCANCODE_HOME,
|
||||
/* 90 */ SDL_SCANCODE_UP,
|
||||
/* 91 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 92 */ SDL_SCANCODE_LEFT,
|
||||
/* 93 */ SDL_SCANCODE_BRIGHTNESSDOWN, /* on PowerBook G4 / KEY_Begin */
|
||||
/* 94 */ SDL_SCANCODE_RIGHT,
|
||||
/* 95 */ SDL_SCANCODE_END,
|
||||
/* 96 */ SDL_SCANCODE_DOWN,
|
||||
/* 97 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 98 */ SDL_SCANCODE_INSERT,
|
||||
/* 99 */ SDL_SCANCODE_DELETE,
|
||||
/* 100 */ SDL_SCANCODE_KP_ENTER,
|
||||
/* 101 */ SDL_SCANCODE_RCTRL,
|
||||
/* 102 */ SDL_SCANCODE_PAUSE,
|
||||
/* 103 */ SDL_SCANCODE_PRINTSCREEN,
|
||||
/* 104 */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 105 */ SDL_SCANCODE_RALT,
|
||||
/* 106 */ SDL_SCANCODE_UNKNOWN, /* BREAK */
|
||||
/* 107 */ SDL_SCANCODE_LGUI,
|
||||
/* 108 */ SDL_SCANCODE_RGUI,
|
||||
/* 109 */ SDL_SCANCODE_APPLICATION,
|
||||
/* 110 */ SDL_SCANCODE_F13,
|
||||
/* 111 */ SDL_SCANCODE_F14,
|
||||
/* 112 */ SDL_SCANCODE_F15,
|
||||
/* 113 */ SDL_SCANCODE_F16,
|
||||
/* 114 */ SDL_SCANCODE_F17,
|
||||
/* 115 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 116 */ SDL_SCANCODE_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_SCANCODE_* for it is */
|
||||
/* 117 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 118 */ SDL_SCANCODE_KP_EQUALS,
|
||||
/* 119 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 120 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 121 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 122 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 123 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 124 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 125 */ SDL_SCANCODE_INTERNATIONAL3, /* Yen */
|
||||
/* 126 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 127 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 128 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 129 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 130 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 131 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 132 */ SDL_SCANCODE_POWER,
|
||||
/* 133 */ SDL_SCANCODE_MUTE,
|
||||
/* 134 */ SDL_SCANCODE_VOLUMEDOWN,
|
||||
/* 135 */ SDL_SCANCODE_VOLUMEUP,
|
||||
/* 136 */ SDL_SCANCODE_HELP,
|
||||
/* 137 */ SDL_SCANCODE_STOP,
|
||||
/* 138 */ SDL_SCANCODE_AGAIN,
|
||||
/* 139 */ SDL_SCANCODE_UNKNOWN, /* PROPS */
|
||||
/* 140 */ SDL_SCANCODE_UNDO,
|
||||
/* 141 */ SDL_SCANCODE_UNKNOWN, /* FRONT */
|
||||
/* 142 */ SDL_SCANCODE_COPY,
|
||||
/* 143 */ SDL_SCANCODE_UNKNOWN, /* OPEN */
|
||||
/* 144 */ SDL_SCANCODE_PASTE,
|
||||
/* 145 */ SDL_SCANCODE_FIND,
|
||||
/* 146 */ SDL_SCANCODE_CUT,
|
||||
};
|
||||
|
||||
/* for wireless usb keyboard (manufacturer TRUST) without numpad. */
|
||||
static const SDL_Scancode xfree86_scancode_table2[] = {
|
||||
/* 0 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 1 */ SDL_SCANCODE_ESCAPE,
|
||||
/* 2 */ SDL_SCANCODE_1,
|
||||
/* 3 */ SDL_SCANCODE_2,
|
||||
/* 4 */ SDL_SCANCODE_3,
|
||||
/* 5 */ SDL_SCANCODE_4,
|
||||
/* 6 */ SDL_SCANCODE_5,
|
||||
/* 7 */ SDL_SCANCODE_6,
|
||||
/* 8 */ SDL_SCANCODE_7,
|
||||
/* 9 */ SDL_SCANCODE_8,
|
||||
/* 10 */ SDL_SCANCODE_9,
|
||||
/* 11 */ SDL_SCANCODE_0,
|
||||
/* 12 */ SDL_SCANCODE_MINUS,
|
||||
/* 13 */ SDL_SCANCODE_EQUALS,
|
||||
/* 14 */ SDL_SCANCODE_BACKSPACE,
|
||||
/* 15 */ SDL_SCANCODE_TAB,
|
||||
/* 16 */ SDL_SCANCODE_Q,
|
||||
/* 17 */ SDL_SCANCODE_W,
|
||||
/* 18 */ SDL_SCANCODE_E,
|
||||
/* 19 */ SDL_SCANCODE_R,
|
||||
/* 20 */ SDL_SCANCODE_T,
|
||||
/* 21 */ SDL_SCANCODE_Y,
|
||||
/* 22 */ SDL_SCANCODE_U,
|
||||
/* 23 */ SDL_SCANCODE_I,
|
||||
/* 24 */ SDL_SCANCODE_O,
|
||||
/* 25 */ SDL_SCANCODE_P,
|
||||
/* 26 */ SDL_SCANCODE_LEFTBRACKET,
|
||||
/* 27 */ SDL_SCANCODE_RIGHTBRACKET,
|
||||
/* 28 */ SDL_SCANCODE_RETURN,
|
||||
/* 29 */ SDL_SCANCODE_LCTRL,
|
||||
/* 30 */ SDL_SCANCODE_A,
|
||||
/* 31 */ SDL_SCANCODE_S,
|
||||
/* 32 */ SDL_SCANCODE_D,
|
||||
/* 33 */ SDL_SCANCODE_F,
|
||||
/* 34 */ SDL_SCANCODE_G,
|
||||
/* 35 */ SDL_SCANCODE_H,
|
||||
/* 36 */ SDL_SCANCODE_J,
|
||||
/* 37 */ SDL_SCANCODE_K,
|
||||
/* 38 */ SDL_SCANCODE_L,
|
||||
/* 39 */ SDL_SCANCODE_SEMICOLON,
|
||||
/* 40 */ SDL_SCANCODE_APOSTROPHE,
|
||||
/* 41 */ SDL_SCANCODE_GRAVE,
|
||||
/* 42 */ SDL_SCANCODE_LSHIFT,
|
||||
/* 43 */ SDL_SCANCODE_BACKSLASH,
|
||||
/* 44 */ SDL_SCANCODE_Z,
|
||||
/* 45 */ SDL_SCANCODE_X,
|
||||
/* 46 */ SDL_SCANCODE_C,
|
||||
/* 47 */ SDL_SCANCODE_V,
|
||||
/* 48 */ SDL_SCANCODE_B,
|
||||
/* 49 */ SDL_SCANCODE_N,
|
||||
/* 50 */ SDL_SCANCODE_M,
|
||||
/* 51 */ SDL_SCANCODE_COMMA,
|
||||
/* 52 */ SDL_SCANCODE_PERIOD,
|
||||
/* 53 */ SDL_SCANCODE_SLASH,
|
||||
/* 54 */ SDL_SCANCODE_RSHIFT,
|
||||
/* 55 */ SDL_SCANCODE_KP_MULTIPLY,
|
||||
/* 56 */ SDL_SCANCODE_LALT,
|
||||
/* 57 */ SDL_SCANCODE_SPACE,
|
||||
/* 58 */ SDL_SCANCODE_CAPSLOCK,
|
||||
/* 59 */ SDL_SCANCODE_F1,
|
||||
/* 60 */ SDL_SCANCODE_F2,
|
||||
/* 61 */ SDL_SCANCODE_F3,
|
||||
/* 62 */ SDL_SCANCODE_F4,
|
||||
/* 63 */ SDL_SCANCODE_F5,
|
||||
/* 64 */ SDL_SCANCODE_F6,
|
||||
/* 65 */ SDL_SCANCODE_F7,
|
||||
/* 66 */ SDL_SCANCODE_F8,
|
||||
/* 67 */ SDL_SCANCODE_F9,
|
||||
/* 68 */ SDL_SCANCODE_F10,
|
||||
/* 69 */ SDL_SCANCODE_NUMLOCKCLEAR,
|
||||
/* 70 */ SDL_SCANCODE_SCROLLLOCK,
|
||||
/* 71 */ SDL_SCANCODE_KP_7,
|
||||
/* 72 */ SDL_SCANCODE_KP_8,
|
||||
/* 73 */ SDL_SCANCODE_KP_9,
|
||||
/* 74 */ SDL_SCANCODE_KP_MINUS,
|
||||
/* 75 */ SDL_SCANCODE_KP_4,
|
||||
/* 76 */ SDL_SCANCODE_KP_5,
|
||||
/* 77 */ SDL_SCANCODE_KP_6,
|
||||
/* 78 */ SDL_SCANCODE_KP_PLUS,
|
||||
/* 79 */ SDL_SCANCODE_KP_1,
|
||||
/* 80 */ SDL_SCANCODE_KP_2,
|
||||
/* 81 */ SDL_SCANCODE_KP_3,
|
||||
/* 82 */ SDL_SCANCODE_KP_0,
|
||||
/* 83 */ SDL_SCANCODE_KP_PERIOD,
|
||||
/* 84 */ SDL_SCANCODE_SYSREQ, /* ???? */
|
||||
/* 85 */ SDL_SCANCODE_MODE, /* ???? */
|
||||
/* 86 */ SDL_SCANCODE_NONUSBACKSLASH,
|
||||
/* 87 */ SDL_SCANCODE_F11,
|
||||
/* 88 */ SDL_SCANCODE_F12,
|
||||
/* 89 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 90 */ SDL_SCANCODE_UNKNOWN, /* Katakana */
|
||||
/* 91 */ SDL_SCANCODE_UNKNOWN, /* Hiragana */
|
||||
/* 92 */ SDL_SCANCODE_UNKNOWN, /* Henkan_Mode */
|
||||
/* 93 */ SDL_SCANCODE_UNKNOWN, /* Hiragana_Katakana */
|
||||
/* 94 */ SDL_SCANCODE_UNKNOWN, /* Muhenkan */
|
||||
/* 95 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 96 */ SDL_SCANCODE_KP_ENTER,
|
||||
/* 97 */ SDL_SCANCODE_RCTRL,
|
||||
/* 98 */ SDL_SCANCODE_KP_DIVIDE,
|
||||
/* 99 */ SDL_SCANCODE_PRINTSCREEN,
|
||||
/* 100 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift, ALTGR, RALT */
|
||||
/* 101 */ SDL_SCANCODE_UNKNOWN, /* Linefeed */
|
||||
/* 102 */ SDL_SCANCODE_HOME,
|
||||
/* 103 */ SDL_SCANCODE_UP,
|
||||
/* 104 */ SDL_SCANCODE_PAGEUP,
|
||||
/* 105 */ SDL_SCANCODE_LEFT,
|
||||
/* 106 */ SDL_SCANCODE_RIGHT,
|
||||
/* 107 */ SDL_SCANCODE_END,
|
||||
/* 108 */ SDL_SCANCODE_DOWN,
|
||||
/* 109 */ SDL_SCANCODE_PAGEDOWN,
|
||||
/* 110 */ SDL_SCANCODE_INSERT,
|
||||
/* 111 */ SDL_SCANCODE_DELETE,
|
||||
/* 112 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 113 */ SDL_SCANCODE_MUTE,
|
||||
/* 114 */ SDL_SCANCODE_VOLUMEDOWN,
|
||||
/* 115 */ SDL_SCANCODE_VOLUMEUP,
|
||||
/* 116 */ SDL_SCANCODE_POWER,
|
||||
/* 117 */ SDL_SCANCODE_KP_EQUALS,
|
||||
/* 118 */ SDL_SCANCODE_UNKNOWN, /* plusminus */
|
||||
/* 119 */ SDL_SCANCODE_PAUSE,
|
||||
/* 120 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchA */
|
||||
/* 121 */ SDL_SCANCODE_UNKNOWN, /* KP_Decimal */
|
||||
/* 122 */ SDL_SCANCODE_UNKNOWN, /* Hangul */
|
||||
/* 123 */ SDL_SCANCODE_UNKNOWN, /* Hangul_Hanja */
|
||||
/* 124 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 125 */ SDL_SCANCODE_LGUI,
|
||||
/* 126 */ SDL_SCANCODE_RGUI,
|
||||
/* 127 */ SDL_SCANCODE_APPLICATION,
|
||||
/* 128 */ SDL_SCANCODE_CANCEL,
|
||||
/* 129 */ SDL_SCANCODE_AGAIN,
|
||||
/* 130 */ SDL_SCANCODE_UNKNOWN, /* SunProps */
|
||||
/* 131 */ SDL_SCANCODE_UNDO,
|
||||
/* 132 */ SDL_SCANCODE_UNKNOWN, /* SunFront */
|
||||
/* 133 */ SDL_SCANCODE_COPY,
|
||||
/* 134 */ SDL_SCANCODE_UNKNOWN, /* SunOpen */
|
||||
/* 135 */ SDL_SCANCODE_PASTE,
|
||||
/* 136 */ SDL_SCANCODE_FIND,
|
||||
/* 137 */ SDL_SCANCODE_CUT,
|
||||
/* 138 */ SDL_SCANCODE_HELP,
|
||||
/* 139 */ SDL_SCANCODE_UNKNOWN, /* XF86MenuKB */
|
||||
/* 140 */ SDL_SCANCODE_CALCULATOR,
|
||||
/* 141 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 142 */ SDL_SCANCODE_SLEEP,
|
||||
/* 143 */ SDL_SCANCODE_UNKNOWN, /* XF86WakeUp */
|
||||
/* 144 */ SDL_SCANCODE_UNKNOWN, /* XF86Explorer */
|
||||
/* 145 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
|
||||
/* 146 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 147 */ SDL_SCANCODE_UNKNOWN, /* XF86Xfer */
|
||||
/* 148 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch1 */
|
||||
/* 149 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch2 */
|
||||
/* 150 */ SDL_SCANCODE_WWW,
|
||||
/* 151 */ SDL_SCANCODE_UNKNOWN, /* XF86DOS */
|
||||
/* 152 */ SDL_SCANCODE_UNKNOWN, /* XF86ScreenSaver */
|
||||
/* 153 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 154 */ SDL_SCANCODE_UNKNOWN, /* XF86RotateWindows */
|
||||
/* 155 */ SDL_SCANCODE_MAIL,
|
||||
/* 156 */ SDL_SCANCODE_UNKNOWN, /* XF86Favorites */
|
||||
/* 157 */ SDL_SCANCODE_COMPUTER,
|
||||
/* 158 */ SDL_SCANCODE_AC_BACK,
|
||||
/* 159 */ SDL_SCANCODE_AC_FORWARD,
|
||||
/* 160 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 161 */ SDL_SCANCODE_EJECT,
|
||||
/* 162 */ SDL_SCANCODE_EJECT,
|
||||
/* 163 */ SDL_SCANCODE_AUDIONEXT,
|
||||
/* 164 */ SDL_SCANCODE_AUDIOPLAY,
|
||||
/* 165 */ SDL_SCANCODE_AUDIOPREV,
|
||||
/* 166 */ SDL_SCANCODE_AUDIOSTOP,
|
||||
/* 167 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioRecord */
|
||||
/* 168 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioRewind */
|
||||
/* 169 */ SDL_SCANCODE_UNKNOWN, /* XF86Phone */
|
||||
/* 170 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 171 */ SDL_SCANCODE_UNKNOWN, /* XF86Tools */
|
||||
/* 172 */ SDL_SCANCODE_AC_HOME,
|
||||
/* 173 */ SDL_SCANCODE_AC_REFRESH,
|
||||
/* 174 */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
|
||||
/* 175 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 176 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 177 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollUp */
|
||||
/* 178 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollDown */
|
||||
/* 179 */ SDL_SCANCODE_UNKNOWN, /* parenleft */
|
||||
/* 180 */ SDL_SCANCODE_UNKNOWN, /* parenright */
|
||||
/* 181 */ SDL_SCANCODE_UNKNOWN, /* XF86New */
|
||||
/* 182 */ SDL_SCANCODE_AGAIN,
|
||||
/* 183 */ SDL_SCANCODE_UNKNOWN, /* XF86Tools */
|
||||
/* 184 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch5 */
|
||||
/* 185 */ SDL_SCANCODE_UNKNOWN, /* XF86MenuKB */
|
||||
/* 186 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 187 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 188 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 189 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 190 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 191 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 192 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadToggle */
|
||||
/* 193 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 194 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 195 */ SDL_SCANCODE_MODE,
|
||||
/* 196 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 197 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 198 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 199 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 200 */ SDL_SCANCODE_AUDIOPLAY,
|
||||
/* 201 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPause */
|
||||
/* 202 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch3 */
|
||||
/* 203 */ SDL_SCANCODE_UNKNOWN, /* XF86Launch4 */
|
||||
/* 204 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchB */
|
||||
/* 205 */ SDL_SCANCODE_UNKNOWN, /* XF86Suspend */
|
||||
/* 206 */ SDL_SCANCODE_UNKNOWN, /* XF86Close */
|
||||
/* 207 */ SDL_SCANCODE_AUDIOPLAY,
|
||||
/* 208 */ SDL_SCANCODE_AUDIONEXT,
|
||||
/* 209 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 210 */ SDL_SCANCODE_PRINTSCREEN,
|
||||
/* 211 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 212 */ SDL_SCANCODE_UNKNOWN, /* XF86WebCam */
|
||||
/* 213 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 214 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 215 */ SDL_SCANCODE_MAIL,
|
||||
/* 216 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 217 */ SDL_SCANCODE_AC_SEARCH,
|
||||
/* 218 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 219 */ SDL_SCANCODE_UNKNOWN, /* XF86Finance */
|
||||
/* 220 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 221 */ SDL_SCANCODE_UNKNOWN, /* XF86Shop */
|
||||
/* 222 */ SDL_SCANCODE_UNKNOWN,
|
||||
/* 223 */ SDL_SCANCODE_STOP,
|
||||
/* 224 */ SDL_SCANCODE_BRIGHTNESSDOWN,
|
||||
/* 225 */ SDL_SCANCODE_BRIGHTNESSUP,
|
||||
/* 226 */ SDL_SCANCODE_MEDIASELECT,
|
||||
/* 227 */ SDL_SCANCODE_DISPLAYSWITCH,
|
||||
/* 228 */ SDL_SCANCODE_KBDILLUMTOGGLE,
|
||||
/* 229 */ SDL_SCANCODE_KBDILLUMDOWN,
|
||||
/* 230 */ SDL_SCANCODE_KBDILLUMUP,
|
||||
/* 231 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */
|
||||
/* 232 */ SDL_SCANCODE_UNKNOWN, /* XF86Reply */
|
||||
/* 233 */ SDL_SCANCODE_UNKNOWN, /* XF86MailForward */
|
||||
/* 234 */ SDL_SCANCODE_UNKNOWN, /* XF86Save */
|
||||
/* 235 */ SDL_SCANCODE_UNKNOWN, /* XF86Documents */
|
||||
/* 236 */ SDL_SCANCODE_UNKNOWN, /* XF86Battery */
|
||||
/* 237 */ SDL_SCANCODE_UNKNOWN, /* XF86Bluetooth */
|
||||
/* 238 */ SDL_SCANCODE_UNKNOWN, /* XF86WLAN */
|
||||
};
|
||||
|
||||
/* *INDENT-ON* */
|
||||
660
thirdparty/SDL/src/file/SDL_rwops.c
vendored
Normal file
660
thirdparty/SDL/src/file/SDL_rwops.c
vendored
Normal file
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_config.h"
|
||||
|
||||
/* This file provides a general interface for SDL to read and write
|
||||
data sources. It can easily be extended to files, memory, etc.
|
||||
*/
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_rwops.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "cocoa/SDL_rwopsbundlesupport.h"
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#ifdef __NDS__
|
||||
/* include libfat headers for fatInitDefault(). */
|
||||
#include <fat.h>
|
||||
#endif /* __NDS__ */
|
||||
|
||||
#ifdef __WIN32__
|
||||
|
||||
/* Functions to read/write Win32 API file pointers */
|
||||
/* Will not use it on WinCE because stdio is buffered, it means
|
||||
faster, and all stdio functions anyway are embedded in coredll.dll -
|
||||
the main wince dll*/
|
||||
|
||||
#include "../core/windows/SDL_windows.h"
|
||||
|
||||
#ifndef INVALID_SET_FILE_POINTER
|
||||
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#define READAHEAD_BUFFER_SIZE 1024
|
||||
|
||||
static int SDLCALL
|
||||
windows_file_open(SDL_RWops * context, const char *filename, const char *mode)
|
||||
{
|
||||
#ifndef _WIN32_WCE
|
||||
UINT old_error_mode;
|
||||
#endif
|
||||
HANDLE h;
|
||||
DWORD r_right, w_right;
|
||||
DWORD must_exist, truncate;
|
||||
int a_mode;
|
||||
|
||||
if (!context)
|
||||
return -1; /* failed (invalid call) */
|
||||
|
||||
context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* mark this as unusable */
|
||||
context->hidden.windowsio.buffer.data = NULL;
|
||||
context->hidden.windowsio.buffer.size = 0;
|
||||
context->hidden.windowsio.buffer.left = 0;
|
||||
|
||||
/* "r" = reading, file must exist */
|
||||
/* "w" = writing, truncate existing, file may not exist */
|
||||
/* "r+"= reading or writing, file must exist */
|
||||
/* "a" = writing, append file may not exist */
|
||||
/* "a+"= append + read, file may not exist */
|
||||
/* "w+" = read, write, truncate. file may not exist */
|
||||
|
||||
must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0;
|
||||
truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0;
|
||||
r_right = (SDL_strchr(mode, '+') != NULL
|
||||
|| must_exist) ? GENERIC_READ : 0;
|
||||
a_mode = (SDL_strchr(mode, 'a') != NULL) ? OPEN_ALWAYS : 0;
|
||||
w_right = (a_mode || SDL_strchr(mode, '+')
|
||||
|| truncate) ? GENERIC_WRITE : 0;
|
||||
|
||||
if (!r_right && !w_right) /* inconsistent mode */
|
||||
return -1; /* failed (invalid call) */
|
||||
|
||||
context->hidden.windowsio.buffer.data =
|
||||
(char *) SDL_malloc(READAHEAD_BUFFER_SIZE);
|
||||
if (!context->hidden.windowsio.buffer.data) {
|
||||
SDL_OutOfMemory();
|
||||
return -1;
|
||||
}
|
||||
#ifdef _WIN32_WCE
|
||||
{
|
||||
LPTSTR tstr = WIN_UTF8ToString(filename);
|
||||
h = CreateFile(tstr, (w_right | r_right),
|
||||
(w_right) ? 0 : FILE_SHARE_READ, NULL,
|
||||
(must_exist | truncate | a_mode),
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
SDL_free(tstr);
|
||||
}
|
||||
#else
|
||||
/* Do not open a dialog box if failure */
|
||||
old_error_mode =
|
||||
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
|
||||
|
||||
{
|
||||
LPTSTR tstr = WIN_UTF8ToString(filename);
|
||||
h = CreateFile(tstr, (w_right | r_right),
|
||||
(w_right) ? 0 : FILE_SHARE_READ, NULL,
|
||||
(must_exist | truncate | a_mode),
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
SDL_free(tstr);
|
||||
}
|
||||
|
||||
/* restore old behavior */
|
||||
SetErrorMode(old_error_mode);
|
||||
#endif /* _WIN32_WCE */
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
SDL_free(context->hidden.windowsio.buffer.data);
|
||||
context->hidden.windowsio.buffer.data = NULL;
|
||||
SDL_SetError("Couldn't open %s", filename);
|
||||
return -2; /* failed (CreateFile) */
|
||||
}
|
||||
context->hidden.windowsio.h = h;
|
||||
context->hidden.windowsio.append = a_mode ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
return 0; /* ok */
|
||||
}
|
||||
|
||||
static long SDLCALL
|
||||
windows_file_seek(SDL_RWops * context, long offset, int whence)
|
||||
{
|
||||
DWORD windowswhence;
|
||||
long file_pos;
|
||||
|
||||
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) {
|
||||
SDL_SetError("windows_file_seek: invalid context/file not opened");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* FIXME: We may be able to satisfy the seek within buffered data */
|
||||
if (whence == RW_SEEK_CUR && context->hidden.windowsio.buffer.left) {
|
||||
offset -= (long)context->hidden.windowsio.buffer.left;
|
||||
}
|
||||
context->hidden.windowsio.buffer.left = 0;
|
||||
|
||||
switch (whence) {
|
||||
case RW_SEEK_SET:
|
||||
windowswhence = FILE_BEGIN;
|
||||
break;
|
||||
case RW_SEEK_CUR:
|
||||
windowswhence = FILE_CURRENT;
|
||||
break;
|
||||
case RW_SEEK_END:
|
||||
windowswhence = FILE_END;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("windows_file_seek: Unknown value for 'whence'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
file_pos =
|
||||
SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence);
|
||||
|
||||
if (file_pos != INVALID_SET_FILE_POINTER)
|
||||
return file_pos; /* success */
|
||||
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
return -1; /* error */
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
windows_file_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
||||
{
|
||||
size_t total_need;
|
||||
size_t total_read = 0;
|
||||
size_t read_ahead;
|
||||
DWORD byte_read;
|
||||
|
||||
total_need = size * maxnum;
|
||||
|
||||
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
|
||||
|| !total_need)
|
||||
return 0;
|
||||
|
||||
if (context->hidden.windowsio.buffer.left > 0) {
|
||||
void *data = (char *) context->hidden.windowsio.buffer.data +
|
||||
context->hidden.windowsio.buffer.size -
|
||||
context->hidden.windowsio.buffer.left;
|
||||
read_ahead =
|
||||
SDL_min(total_need, context->hidden.windowsio.buffer.left);
|
||||
SDL_memcpy(ptr, data, read_ahead);
|
||||
context->hidden.windowsio.buffer.left -= read_ahead;
|
||||
|
||||
if (read_ahead == total_need) {
|
||||
return maxnum;
|
||||
}
|
||||
ptr = (char *) ptr + read_ahead;
|
||||
total_need -= read_ahead;
|
||||
total_read += read_ahead;
|
||||
}
|
||||
|
||||
if (total_need < READAHEAD_BUFFER_SIZE) {
|
||||
if (!ReadFile
|
||||
(context->hidden.windowsio.h, context->hidden.windowsio.buffer.data,
|
||||
READAHEAD_BUFFER_SIZE, &byte_read, NULL)) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
return 0;
|
||||
}
|
||||
read_ahead = SDL_min(total_need, (int) byte_read);
|
||||
SDL_memcpy(ptr, context->hidden.windowsio.buffer.data, read_ahead);
|
||||
context->hidden.windowsio.buffer.size = byte_read;
|
||||
context->hidden.windowsio.buffer.left = byte_read - read_ahead;
|
||||
total_read += read_ahead;
|
||||
} else {
|
||||
if (!ReadFile
|
||||
(context->hidden.windowsio.h, ptr, (DWORD)total_need, &byte_read, NULL)) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
return 0;
|
||||
}
|
||||
total_read += byte_read;
|
||||
}
|
||||
return (total_read / size);
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
windows_file_write(SDL_RWops * context, const void *ptr, size_t size,
|
||||
size_t num)
|
||||
{
|
||||
|
||||
size_t total_bytes;
|
||||
DWORD byte_written;
|
||||
size_t nwritten;
|
||||
|
||||
total_bytes = size * num;
|
||||
|
||||
if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE
|
||||
|| total_bytes <= 0 || !size)
|
||||
return 0;
|
||||
|
||||
if (context->hidden.windowsio.buffer.left) {
|
||||
SetFilePointer(context->hidden.windowsio.h,
|
||||
-(LONG)context->hidden.windowsio.buffer.left, NULL,
|
||||
FILE_CURRENT);
|
||||
context->hidden.windowsio.buffer.left = 0;
|
||||
}
|
||||
|
||||
/* if in append mode, we must go to the EOF before write */
|
||||
if (context->hidden.windowsio.append) {
|
||||
if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
|
||||
INVALID_SET_FILE_POINTER) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WriteFile
|
||||
(context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nwritten = byte_written / size;
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
static int SDLCALL
|
||||
windows_file_close(SDL_RWops * context)
|
||||
{
|
||||
|
||||
if (context) {
|
||||
if (context->hidden.windowsio.h != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(context->hidden.windowsio.h);
|
||||
context->hidden.windowsio.h = INVALID_HANDLE_VALUE; /* to be sure */
|
||||
}
|
||||
if (context->hidden.windowsio.buffer.data) {
|
||||
SDL_free(context->hidden.windowsio.buffer.data);
|
||||
context->hidden.windowsio.buffer.data = NULL;
|
||||
}
|
||||
SDL_FreeRW(context);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif /* __WIN32__ */
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
|
||||
/* Functions to read/write stdio file pointers */
|
||||
|
||||
static long SDLCALL
|
||||
stdio_seek(SDL_RWops * context, long offset, int whence)
|
||||
{
|
||||
if (fseek(context->hidden.stdio.fp, offset, whence) == 0) {
|
||||
return (ftell(context->hidden.stdio.fp));
|
||||
} else {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
stdio_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
||||
{
|
||||
size_t nread;
|
||||
|
||||
nread = fread(ptr, size, maxnum, context->hidden.stdio.fp);
|
||||
if (nread == 0 && ferror(context->hidden.stdio.fp)) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
}
|
||||
return (nread);
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
stdio_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
||||
{
|
||||
size_t nwrote;
|
||||
|
||||
nwrote = fwrite(ptr, size, num, context->hidden.stdio.fp);
|
||||
if (nwrote == 0 && ferror(context->hidden.stdio.fp)) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
}
|
||||
return (nwrote);
|
||||
}
|
||||
|
||||
static int SDLCALL
|
||||
stdio_close(SDL_RWops * context)
|
||||
{
|
||||
int status = 0;
|
||||
if (context) {
|
||||
if (context->hidden.stdio.autoclose) {
|
||||
/* WARNING: Check the return value here! */
|
||||
if (fclose(context->hidden.stdio.fp) != 0) {
|
||||
SDL_Error(SDL_EFWRITE);
|
||||
status = -1;
|
||||
}
|
||||
}
|
||||
SDL_FreeRW(context);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif /* !HAVE_STDIO_H */
|
||||
|
||||
/* Functions to read/write memory pointers */
|
||||
|
||||
static long SDLCALL
|
||||
mem_seek(SDL_RWops * context, long offset, int whence)
|
||||
{
|
||||
Uint8 *newpos;
|
||||
|
||||
switch (whence) {
|
||||
case RW_SEEK_SET:
|
||||
newpos = context->hidden.mem.base + offset;
|
||||
break;
|
||||
case RW_SEEK_CUR:
|
||||
newpos = context->hidden.mem.here + offset;
|
||||
break;
|
||||
case RW_SEEK_END:
|
||||
newpos = context->hidden.mem.stop + offset;
|
||||
break;
|
||||
default:
|
||||
SDL_SetError("Unknown value for 'whence'");
|
||||
return (-1);
|
||||
}
|
||||
if (newpos < context->hidden.mem.base) {
|
||||
newpos = context->hidden.mem.base;
|
||||
}
|
||||
if (newpos > context->hidden.mem.stop) {
|
||||
newpos = context->hidden.mem.stop;
|
||||
}
|
||||
context->hidden.mem.here = newpos;
|
||||
return (long)(context->hidden.mem.here - context->hidden.mem.base);
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
mem_read(SDL_RWops * context, void *ptr, size_t size, size_t maxnum)
|
||||
{
|
||||
size_t total_bytes;
|
||||
size_t mem_available;
|
||||
|
||||
total_bytes = (maxnum * size);
|
||||
if ((maxnum <= 0) || (size <= 0)
|
||||
|| ((total_bytes / maxnum) != (size_t) size)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mem_available = (context->hidden.mem.stop - context->hidden.mem.here);
|
||||
if (total_bytes > mem_available) {
|
||||
total_bytes = mem_available;
|
||||
}
|
||||
|
||||
SDL_memcpy(ptr, context->hidden.mem.here, total_bytes);
|
||||
context->hidden.mem.here += total_bytes;
|
||||
|
||||
return (total_bytes / size);
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
mem_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
||||
{
|
||||
if ((context->hidden.mem.here + (num * size)) > context->hidden.mem.stop) {
|
||||
num = (context->hidden.mem.stop - context->hidden.mem.here) / size;
|
||||
}
|
||||
SDL_memcpy(context->hidden.mem.here, ptr, num * size);
|
||||
context->hidden.mem.here += num * size;
|
||||
return (num);
|
||||
}
|
||||
|
||||
static size_t SDLCALL
|
||||
mem_writeconst(SDL_RWops * context, const void *ptr, size_t size, size_t num)
|
||||
{
|
||||
SDL_SetError("Can't write to read-only memory");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int SDLCALL
|
||||
mem_close(SDL_RWops * context)
|
||||
{
|
||||
if (context) {
|
||||
SDL_FreeRW(context);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* Functions to create SDL_RWops structures from various data sources */
|
||||
|
||||
SDL_RWops *
|
||||
SDL_RWFromFile(const char *file, const char *mode)
|
||||
{
|
||||
SDL_RWops *rwops = NULL;
|
||||
#ifdef HAVE_STDIO_H
|
||||
FILE *fp = NULL;
|
||||
#endif
|
||||
if (!file || !*file || !mode || !*mode) {
|
||||
SDL_SetError("SDL_RWFromFile(): No file or no mode specified");
|
||||
return NULL;
|
||||
}
|
||||
#if defined(__WIN32__)
|
||||
rwops = SDL_AllocRW();
|
||||
if (!rwops)
|
||||
return NULL; /* SDL_SetError already setup by SDL_AllocRW() */
|
||||
if (windows_file_open(rwops, file, mode) < 0) {
|
||||
SDL_FreeRW(rwops);
|
||||
return NULL;
|
||||
}
|
||||
rwops->seek = windows_file_seek;
|
||||
rwops->read = windows_file_read;
|
||||
rwops->write = windows_file_write;
|
||||
rwops->close = windows_file_close;
|
||||
|
||||
#elif HAVE_STDIO_H
|
||||
#ifdef __APPLE__
|
||||
fp = SDL_OpenFPFromBundleOrFallback(file, mode);
|
||||
#else
|
||||
fp = fopen(file, mode);
|
||||
#endif
|
||||
if (fp == NULL) {
|
||||
SDL_SetError("Couldn't open %s", file);
|
||||
} else {
|
||||
rwops = SDL_RWFromFP(fp, 1);
|
||||
}
|
||||
#else
|
||||
SDL_SetError("SDL not compiled with stdio support");
|
||||
#endif /* !HAVE_STDIO_H */
|
||||
|
||||
return (rwops);
|
||||
}
|
||||
|
||||
#ifdef HAVE_STDIO_H
|
||||
SDL_RWops *
|
||||
SDL_RWFromFP(FILE * fp, SDL_bool autoclose)
|
||||
{
|
||||
SDL_RWops *rwops = NULL;
|
||||
|
||||
#if 0
|
||||
/*#ifdef __NDS__*/
|
||||
/* set it up so we can use stdio file function */
|
||||
fatInitDefault();
|
||||
printf("called fatInitDefault()");
|
||||
#endif /* __NDS__ */
|
||||
|
||||
rwops = SDL_AllocRW();
|
||||
if (rwops != NULL) {
|
||||
rwops->seek = stdio_seek;
|
||||
rwops->read = stdio_read;
|
||||
rwops->write = stdio_write;
|
||||
rwops->close = stdio_close;
|
||||
rwops->hidden.stdio.fp = fp;
|
||||
rwops->hidden.stdio.autoclose = autoclose;
|
||||
}
|
||||
return (rwops);
|
||||
}
|
||||
#else
|
||||
SDL_RWops *
|
||||
SDL_RWFromFP(void * fp, SDL_bool autoclose)
|
||||
{
|
||||
SDL_SetError("SDL not compiled with stdio support");
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_STDIO_H */
|
||||
|
||||
SDL_RWops *
|
||||
SDL_RWFromMem(void *mem, int size)
|
||||
{
|
||||
SDL_RWops *rwops;
|
||||
|
||||
rwops = SDL_AllocRW();
|
||||
if (rwops != NULL) {
|
||||
rwops->seek = mem_seek;
|
||||
rwops->read = mem_read;
|
||||
rwops->write = mem_write;
|
||||
rwops->close = mem_close;
|
||||
rwops->hidden.mem.base = (Uint8 *) mem;
|
||||
rwops->hidden.mem.here = rwops->hidden.mem.base;
|
||||
rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
|
||||
}
|
||||
return (rwops);
|
||||
}
|
||||
|
||||
SDL_RWops *
|
||||
SDL_RWFromConstMem(const void *mem, int size)
|
||||
{
|
||||
SDL_RWops *rwops;
|
||||
|
||||
rwops = SDL_AllocRW();
|
||||
if (rwops != NULL) {
|
||||
rwops->seek = mem_seek;
|
||||
rwops->read = mem_read;
|
||||
rwops->write = mem_writeconst;
|
||||
rwops->close = mem_close;
|
||||
rwops->hidden.mem.base = (Uint8 *) mem;
|
||||
rwops->hidden.mem.here = rwops->hidden.mem.base;
|
||||
rwops->hidden.mem.stop = rwops->hidden.mem.base + size;
|
||||
}
|
||||
return (rwops);
|
||||
}
|
||||
|
||||
SDL_RWops *
|
||||
SDL_AllocRW(void)
|
||||
{
|
||||
SDL_RWops *area;
|
||||
|
||||
area = (SDL_RWops *) SDL_malloc(sizeof *area);
|
||||
if (area == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
return (area);
|
||||
}
|
||||
|
||||
void
|
||||
SDL_FreeRW(SDL_RWops * area)
|
||||
{
|
||||
SDL_free(area);
|
||||
}
|
||||
|
||||
/* Functions for dynamically reading and writing endian-specific values */
|
||||
|
||||
Uint16
|
||||
SDL_ReadLE16(SDL_RWops * src)
|
||||
{
|
||||
Uint16 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapLE16(value));
|
||||
}
|
||||
|
||||
Uint16
|
||||
SDL_ReadBE16(SDL_RWops * src)
|
||||
{
|
||||
Uint16 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapBE16(value));
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_ReadLE32(SDL_RWops * src)
|
||||
{
|
||||
Uint32 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapLE32(value));
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_ReadBE32(SDL_RWops * src)
|
||||
{
|
||||
Uint32 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapBE32(value));
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_ReadLE64(SDL_RWops * src)
|
||||
{
|
||||
Uint64 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapLE64(value));
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_ReadBE64(SDL_RWops * src)
|
||||
{
|
||||
Uint64 value;
|
||||
|
||||
SDL_RWread(src, &value, (sizeof value), 1);
|
||||
return (SDL_SwapBE64(value));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteLE16(SDL_RWops * dst, Uint16 value)
|
||||
{
|
||||
value = SDL_SwapLE16(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteBE16(SDL_RWops * dst, Uint16 value)
|
||||
{
|
||||
value = SDL_SwapBE16(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteLE32(SDL_RWops * dst, Uint32 value)
|
||||
{
|
||||
value = SDL_SwapLE32(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteBE32(SDL_RWops * dst, Uint32 value)
|
||||
{
|
||||
value = SDL_SwapBE32(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteLE64(SDL_RWops * dst, Uint64 value)
|
||||
{
|
||||
value = SDL_SwapLE64(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
size_t
|
||||
SDL_WriteBE64(SDL_RWops * dst, Uint64 value)
|
||||
{
|
||||
value = SDL_SwapBE64(value);
|
||||
return (SDL_RWwrite(dst, &value, (sizeof value), 1));
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
9
thirdparty/SDL/src/file/cocoa/SDL_rwopsbundlesupport.h
vendored
Normal file
9
thirdparty/SDL/src/file/cocoa/SDL_rwopsbundlesupport.h
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef SDL_rwopsbundlesupport_h
|
||||
#define SDL_rwopsbundlesupport_h
|
||||
FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode);
|
||||
#endif
|
||||
#endif
|
||||
45
thirdparty/SDL/src/file/cocoa/SDL_rwopsbundlesupport.m
vendored
Normal file
45
thirdparty/SDL/src/file/cocoa/SDL_rwopsbundlesupport.m
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifdef __APPLE__
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "SDL_rwopsbundlesupport.h"
|
||||
|
||||
/* For proper OS X applications, the resources are contained inside the application bundle.
|
||||
So the strategy is to first check the application bundle for the file, then fallback to the current working directory.
|
||||
Note: One additional corner-case is if the resource is in a framework's resource bundle instead of the app.
|
||||
We might want to use bundle identifiers, e.g. org.libsdl.sdl to get the bundle for the framework,
|
||||
but we would somehow need to know what the bundle identifiers we need to search are.
|
||||
Also, note the bundle layouts are different for iPhone and Mac.
|
||||
*/
|
||||
FILE* SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode)
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
|
||||
// If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only.
|
||||
if(strcmp("r", mode) && strcmp("rb", mode))
|
||||
{
|
||||
return fopen(file, mode);
|
||||
}
|
||||
|
||||
NSAutoreleasePool* autorelease_pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
NSFileManager* file_manager = [NSFileManager defaultManager];
|
||||
NSString* resource_path = [[NSBundle mainBundle] resourcePath];
|
||||
|
||||
NSString* ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)];
|
||||
|
||||
NSString* full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component];
|
||||
if([file_manager fileExistsAtPath:full_path_with_file_to_try])
|
||||
{
|
||||
fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
fp = fopen(file, mode);
|
||||
}
|
||||
|
||||
[autorelease_pool drain];
|
||||
|
||||
return fp;
|
||||
}
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user