Merged default into iOS-improvements

--HG--
branch : iOS-improvements
This commit is contained in:
Alex Szpakowski 2015-04-06 15:26:37 -03:00
commit 0bacddf42e
150 changed files with 2690 additions and 1507 deletions

View file

@ -118,9 +118,9 @@ else()
endif()
if (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN) # JavaScript does not yet have threading support, so disable pthreads when building for Emscripten.
set(PTHREADS_ENABLED_BY_DEFAULT ON)
set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON)
else()
set(PTHREADS_ENABLED_BY_DEFAULT OFF)
set(SDL_PTHREADS_ENABLED_BY_DEFAULT OFF)
endif()
# Default option knobs
@ -202,6 +202,7 @@ include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include)
# All these ENABLED_BY_DEFAULT vars will default to ON if not specified, so
# you only need to have a platform override them if they are disabling.
set(OPT_DEF_ASM TRUE)
if(EMSCRIPTEN)
# Set up default values for the currently supported set of subsystems:
# Emscripten/Javascript does not have assembly support, a dynamic library
@ -212,12 +213,12 @@ if(EMSCRIPTEN)
set(SDL_THREADS_ENABLED_BY_DEFAULT OFF)
set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF)
set(DLOPEN_ENABLED_BY_DEFAULT OFF)
set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF)
endif()
set(SDL_SUBSYSTEMS
Atomic Audio Video Render Events Joystick Haptic Power Threads Timers
File Loadso CPUinfo Filesystem)
File Loadso CPUinfo Filesystem Dlopen)
foreach(_SUB ${SDL_SUBSYSTEMS})
string(TOUPPER ${_SUB} _OPT)
if (NOT DEFINED SDL_${_OPT}_ENABLED_BY_DEFAULT)
@ -246,9 +247,9 @@ dep_option(FUSIONSOUND_SHARED "Dynamically load fusionsound audio support" ON "
set_option(VIDEO_DUMMY "Use dummy video driver" ON)
set_option(VIDEO_OPENGL "Include OpenGL support" ON)
set_option(VIDEO_OPENGLES "Include OpenGL ES support" ON)
set_option(PTHREADS "Use POSIX threads for multi-threading" ${PTHREADS_ENABLED_BY_DEFAULT})
set_option(PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT})
dep_option(PTHREADS_SEM "Use pthread semaphores" ON "PTHREADS" OFF)
set_option(SDL_DLOPEN "Use dlopen for shared object loading" ${DLOPEN_ENABLED_BY_DEFAULT})
set_option(SDL_DLOPEN "Use dlopen for shared object loading" ${SDL_DLOPEN_ENABLED_BY_DEFAULT})
set_option(OSS "Support the OSS audio API" ${UNIX_SYS})
set_option(ALSA "Support the ALSA audio API" ${UNIX_SYS})
dep_option(ALSA_SHARED "Dynamically load ALSA audio support" ON "ALSA" OFF)
@ -266,7 +267,10 @@ set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" O
set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS})
set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS})
set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS})
dep_option(WAYLAND_SHARED "Dynamically load Wayland support" ON "VIDEO_WAYLAND" OFF)
dep_option(VIDEO_WAYLAND_QT_TOUCH "QtWayland server support for Wayland video driver" ON "VIDEO_WAYLAND" OFF)
set_option(VIDEO_MIR "Use Mir video driver" ${UNIX_SYS})
dep_option(MIR_SHARED "Dynamically load Mir support" ON "VIDEO_MIR" OFF)
set_option(VIDEO_RPI "Use Raspberry Pi video driver" ${UNIX_SYS})
dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF)
set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm)
@ -585,7 +589,7 @@ if(LIBC)
set(CMAKE_REQUIRED_LIBRARIES m)
foreach(_FN
atan atan2 ceil copysign cos cosf fabs floor log pow scalbn sin
sinf sqrt sqrtf tan tanf)
sinf sqrt sqrtf tan tanf acos asin)
string(TOUPPER ${_FN} _UPPER)
set(_HAVEVAR "HAVE_${_UPPER}")
check_function_exists("${_FN}" ${_HAVEVAR})
@ -597,6 +601,15 @@ if(LIBC)
check_library_exists(iconv iconv_open "" HAVE_LIBICONV)
if(HAVE_LIBICONV)
list(APPEND EXTRA_LIBS iconv)
set(HAVE_ICONV 1)
endif()
if(NOT APPLE)
check_include_file(alloca.h HAVE_ALLOCA_H)
check_function_exists(alloca HAVE_ALLOCA)
else()
set(HAVE_ALLOCA_H 1)
set(HAVE_ALLOCA 1)
endif()
check_struct_has_member("struct sigaction" "sa_sigaction" "signal.h" HAVE_SA_SIGACTION)
@ -1140,10 +1153,6 @@ elseif(APPLE)
set(SDL_VIDEO_OPENGL 1)
set(SDL_VIDEO_OPENGL_CGL 1)
set(SDL_VIDEO_RENDER_OGL 1)
if(DARWIN)
find_library(OpenGL_LIBRARY OpenGL)
list(APPEND EXTRA_LIBRARIES ${OpenGL_LIBRARY})
endif()
set(HAVE_VIDEO_OPENGL TRUE)
endif()
endif()

View file

@ -1,7 +1,7 @@
Summary: Simple DirectMedia Layer
Name: SDL2
Version: @SDL_VERSION@
Release: 1
Release: 2
Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
URL: http://www.libsdl.org/
License: zlib
@ -63,12 +63,12 @@ rm -rf $RPM_BUILD_ROOT
%files
%{__defattr}
%doc README-SDL.txt COPYING.txt CREDITS.txt BUGS.txt
%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt
%{_libdir}/lib*.%{__soext}.*
%files devel
%{__defattr}
%doc README README-SDL.txt COPYING CREDITS BUGS WhatsNew
%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt WhatsNew.txt
%{_bindir}/*-config
%{_libdir}/lib*.a
%{_libdir}/lib*.la
@ -78,13 +78,16 @@ rm -rf $RPM_BUILD_ROOT
%{_datadir}/aclocal/*
%changelog
* Sun Dec 07 2014 Simone Contini <s.contini@oltrelinux.com>
- Fixed changelog date issue and docs filenames
* Sun Jan 22 2012 Sam Lantinga <slouken@libsdl.org>
- Updated for SDL 2.0
* Tue May 16 2006 Sam Lantinga <slouken@libsdl.org>
- Removed support for Darwin, due to build problems on ps2linux
* Mon Jan 03 2004 Anders Bjorklund <afb@algonet.se>
* Sat Jan 03 2004 Anders Bjorklund <afb@algonet.se>
- Added support for Darwin, updated spec file
* Wed Jan 19 2000 Sam Lantinga <slouken@libsdl.org>

View file

@ -41,6 +41,10 @@ public class SDLActivity extends Activity {
/** If shared libraries (e.g. SDL or the native application) could not be loaded. */
public static boolean mBrokenLibraries;
// If we want to separate mouse and touch events.
// This is only toggled in native code when a hint is set!
public static boolean mSeparateMouseAndTouch;
// Main components
protected static SDLActivity mSingleton;
protected static SDLSurface mSurface;
@ -81,7 +85,6 @@ public class SDLActivity extends Activity {
}
/**
* This method is called by SDL using JNI.
* This method is called by SDL before starting the native application thread.
* It can be overridden to provide the arguments after the application name.
* The default implementation returns an empty array. It never returns null.
@ -402,6 +405,7 @@ public class SDLActivity extends Activity {
public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode);
public static native void onNativeKeyboardFocusLost();
public static native void onNativeMouse(int button, int action, float x, float y);
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
int action, float x,
float y, float p);
@ -1089,7 +1093,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
// Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
// So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD
if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */
if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 ||
(event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
@ -1126,50 +1130,65 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int mouseButton;
int i = -1;
float x,y,p;
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
// !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
if (Build.VERSION.SDK_INT < 14) {
mouseButton = 1; // For Android==12 all mouse buttons are the left button
} else {
try {
mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event);
} catch(Exception e) {
mouseButton = 1; // oh well.
}
}
SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
} else {
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
}
break;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_POINTER_DOWN:
// Non primary pointer up/down
if (i == -1) {
i = event.getActionIndex();
}
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i) / mWidth;
y = event.getY(i) / mHeight;
p = event.getPressure(i);
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
}
break;
default:
break;
default:
break;
}
}
return true;
@ -1500,9 +1519,44 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler {
class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
// Generic Motion (mouse hover, joystick...) events go here
// We only have joysticks yet
@Override
public boolean onGenericMotion(View v, MotionEvent event) {
return SDLActivity.handleJoystickMotionEvent(event);
float x, y;
int mouseButton;
int action;
switch ( event.getSource() ) {
case InputDevice.SOURCE_JOYSTICK:
case InputDevice.SOURCE_GAMEPAD:
case InputDevice.SOURCE_DPAD:
SDLActivity.handleJoystickMotionEvent(event);
return true;
case InputDevice.SOURCE_MOUSE:
action = event.getActionMasked();
switch(event.getActionMasked()) {
case MotionEvent.ACTION_SCROLL:
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
SDLActivity.onNativeMouse(0, action, x, y);
return true;
case MotionEvent.ACTION_HOVER_MOVE:
x = event.getX(0);
y = event.getY(0);
SDLActivity.onNativeMouse(0, action, x, y);
return true;
default:
break;
}
default:
break;
}
// Event was not managed
return false;
}
}

View file

@ -505,8 +505,13 @@ macro(CheckX11)
endif()
endmacro()
# Requires:
# - EGL
# - PkgCheckModules
# Optional:
# - MIR_SHARED opt
# - HAVE_DLOPEN opt
macro(CheckMir)
# !!! FIXME: hook up dynamic loading here.
if(VIDEO_MIR)
find_library(MIR_LIB mirclient mircommon egl)
pkg_check_modules(MIR_TOOLKIT mirclient mircommon)
@ -522,15 +527,31 @@ macro(CheckMir)
set(SDL_VIDEO_DRIVER_MIR 1)
list(APPEND EXTRA_CFLAGS ${MIR_TOOLKIT_CFLAGS} ${EGL_CLFAGS} ${XKB_CLFLAGS})
list(APPEND EXTRA_LDFLAGS ${MIR_TOOLKIT_LDFLAGS} ${EGL_LDLAGS} ${XKB_LDLAGS})
endif (MIR_LIB AND MIR_TOOLKIT_FOUND AND EGL_FOUND AND XKB_FOUND)
if(MIR_SHARED)
if(NOT HAVE_DLOPEN)
message_warn("You must have SDL_LoadObject() support for dynamic Mir loading")
else()
FindLibraryAndSONAME(mirclient)
FindLibraryAndSONAME(xkbcommon)
set(SDL_VIDEO_DRIVER_MIR_DYNAMIC "\"${MIRCLIENT_LIB_SONAME}\"")
set(SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"")
set(HAVE_MIR_SHARED TRUE)
endif()
else()
set(EXTRA_LIBS ${MIR_TOOLKIT_LIBRARIES} ${EXTRA_LIBS})
endif()
endif()
endif()
endmacro()
# Requires:
# - EGL
# - PkgCheckModules
# Optional:
# - WAYLAND_SHARED opt
# - HAVE_DLOPEN opt
macro(CheckWayland)
# !!! FIXME: hook up dynamic loading here.
if(VIDEO_WAYLAND)
pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon)
if(WAYLAND_FOUND)
@ -540,12 +561,34 @@ macro(CheckWayland)
include_directories(
${WAYLAND_INCLUDE_DIRS}
)
set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
set(HAVE_VIDEO_WAYLAND TRUE)
set(HAVE_SDL_VIDEO TRUE)
file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
if(VIDEO_WAYLAND_QT_TOUCH)
set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
endif()
if(WAYLAND_SHARED)
if(NOT HAVE_DLOPEN)
message_warn("You must have SDL_LoadObject() support for dynamic Wayland loading")
else()
FindLibraryAndSONAME(wayland-client)
FindLibraryAndSONAME(wayland-egl)
FindLibraryAndSONAME(wayland-cursor)
FindLibraryAndSONAME(xkbcommon)
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC "\"${WAYLAND_CLIENT_LIB_SONAME}\"")
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL "\"${WAYLAND_EGL_LIB_SONAME}\"")
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR "\"${WAYLAND_CURSOR_LIB_SONAME}\"")
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"")
set(HAVE_WAYLAND_SHARED TRUE)
endif()
else()
set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
endif()
set(SDL_VIDEO_DRIVER_WAYLAND 1)
endif()
endif()
@ -682,7 +725,7 @@ macro(CheckOpenGLESX11)
endif()
endmacro()
# Rquires:
# Requires:
# - nada
# Optional:
# - THREADS opt
@ -733,13 +776,17 @@ macro(CheckPTHREAD)
# Run some tests
set(CMAKE_REQUIRED_FLAGS "${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
check_c_source_runs("
if(CMAKE_CROSSCOMPILING)
set(HAVE_PTHREADS 1)
else()
check_c_source_runs("
#include <pthread.h>
int main(int argc, char** argv) {
pthread_attr_t type;
pthread_attr_init(&type);
return 0;
}" HAVE_PTHREADS)
endif()
if(HAVE_PTHREADS)
set(SDL_THREAD_PTHREAD 1)
list(APPEND EXTRA_CFLAGS ${PTHREAD_CFLAGS})
@ -788,8 +835,8 @@ macro(CheckPTHREAD)
#include <pthread.h>
#include <pthread_np.h>
int main(int argc, char** argv) { return 0; }" HAVE_PTHREAD_NP_H)
check_function_exists(pthread_setname_np HAVE_PTHREAD_setNAME_NP)
check_function_exists(pthread_set_name_np HAVE_PTHREAD_set_NAME_NP)
check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP)
set(CMAKE_REQUIRED_FLAGS)
set(SOURCE_FILES ${SOURCE_FILES}

27
configure vendored
View file

@ -21916,6 +21916,7 @@ $as_echo_n "checking for recursive mutexes... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _GNU_SOURCE 1
#include <pthread.h>
int
@ -21929,7 +21930,7 @@ main ()
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"; then :
has_recursive_mutexes=yes
@ -21937,12 +21938,14 @@ $as_echo "#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
if test x$has_recursive_mutexes = xno; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define _GNU_SOURCE 1
#include <pthread.h>
int
@ -21956,7 +21959,7 @@ main ()
return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
if ac_fn_c_try_link "$LINENO"; then :
has_recursive_mutexes=yes
@ -21964,7 +21967,8 @@ $as_echo "#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1" >>confdefs.h
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_recursive_mutexes" >&5
$as_echo "$has_recursive_mutexes" >&6; }
@ -23091,11 +23095,22 @@ $as_echo "#define SDL_POWER_ANDROID 1" >>confdefs.h
fi
# Set up files for the filesystem library
if test x$enable_filesystem = xyes; then
case $ARCH in
android)
$as_echo "#define SDL_FILESYSTEM_ANDROID 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c"
have_filesystem=yes
;;
*)
$as_echo "#define SDL_FILESYSTEM_UNIX 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
have_filesystem=yes
SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
have_filesystem=yes
;;
esac
fi
# Set up files for the timer library
if test x$enable_timers = xyes; then

View file

@ -2424,7 +2424,8 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]])
AC_MSG_CHECKING(for recursive mutexes)
has_recursive_mutexes=no
if test x$has_recursive_mutexes = xno; then
AC_TRY_COMPILE([
AC_TRY_LINK([
#define _GNU_SOURCE 1
#include <pthread.h>
],[
pthread_mutexattr_t attr;
@ -2435,7 +2436,8 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]])
])
fi
if test x$has_recursive_mutexes = xno; then
AC_TRY_COMPILE([
AC_TRY_LINK([
#define _GNU_SOURCE 1
#include <pthread.h>
],[
pthread_mutexattr_t attr;
@ -2971,9 +2973,18 @@ case "$host" in
fi
# Set up files for the filesystem library
if test x$enable_filesystem = xyes; then
AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ])
SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
have_filesystem=yes
case $ARCH in
android)
AC_DEFINE(SDL_FILESYSTEM_ANDROID, 1, [ ])
SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c"
have_filesystem=yes
;;
*)
AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ])
SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
have_filesystem=yes
;;
esac
fi
# Set up files for the timer library
if test x$enable_timers = xyes; then

View file

@ -1,34 +1,8 @@
Platforms
=========
We maintain the list of supported platforms on our wiki now, and how to
build and install SDL for those platforms:
This is a list of the platforms SDL supports, and who maintains them.
https://wiki.libsdl.org/Installation
Officially supported platforms
==============================
(code compiles, and thoroughly tested for release)
==============================
* Windows XP/Vista/7/8
* Mac OS X 10.5+
* Linux 2.6+
* iOS 5.1.1+
* Android 2.3.3+
Unofficially supported platforms
================================
(code compiles, but not thoroughly tested)
================================
* FreeBSD
* NetBSD
* OpenBSD
* Solaris
Platforms supported by volunteers
=================================
* Haiku - maintained by Axel Dörfler <axeld@pinc-software.de>
* PSP - maintained by 527721088@qq.com
* Pandora - maintained by Scott Smith <pickle136@sbcglobal.net>
* NaCl - maintained by Gabriel Jacobo <gabomdq@gmail.com>
Platforms that need maintainers
===============================

View file

@ -15,7 +15,7 @@ There are two basic ways of building SDL at the moment:
If you have a GNUish system, then you might try this. Edit configure.in,
take a look at the large section labelled:
"Set up the configuration based on the target platform!"
"Set up the configuration based on the host platform!"
Add a section for your platform, and then re-run autogen.sh and build!
2. Using an IDE:

View file

@ -90,10 +90,12 @@ Here is a rough list of what works, and what doens't:
* keyboard input. Most of WinRT's documented virtual keys are supported, as
well as many keys with documented hardware scancodes.
* OpenGL. Experimental support for OpenGL ES 2 is available via the ANGLE
project, using either MS Open Technologies' repository, at
https://github.com/msopentech/angle (both the "winrt" and "future-dev"
branches are supported), or the official ANGLE repository, at
https://chromium.googlesource.com/angle/angle
project, using either:
* MS Open Technologies' "ms-master" repository, at https://github.com/MSOpenTech/angle
(for use with Windows 8.1+ or Windows Phone 8.1+)
* MS Open Technologies' "angle-win8.0" repository, at https://github.com/MSOpenTech/angle-win8.0
(for Windows 8.0 only!)
* Google's main ANGLE repository, at https://chromium.googlesource.com/angle/angle
* SDLmain. WinRT uses a different signature for each app's main() function.
SDL-based apps that use this port must compile in SDL_winrt_main_NonXAML.cpp
(in `SDL\src\main\winrt\`) directly in order for their C-style main()
@ -112,6 +114,11 @@ Here is a rough list of what works, and what doens't:
supported by WinRT itself.
* joysticks and game controllers that aren't supported by Microsoft's XInput
API.
* turning off VSync when rendering on Windows Phone. Attempts to turn VSync
off on Windows Phone result either in Direct3D not drawing anything, or it
forcing VSync back on. As such, SDL_RENDERER_PRESENTVSYNC will always get
turned-on on Windows Phone. This limitation is not present in non-Phone
WinRT (such as Windows 8.x), where turning off VSync appears to work.
* probably anything else that's not listed as supported

View file

@ -102,9 +102,9 @@ typedef enum
SDL_ASSERTION_ABORT, /**< Terminate the program. */
SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
} SDL_assert_state;
} SDL_AssertState;
typedef struct SDL_assert_data
typedef struct SDL_AssertData
{
int always_ignore;
unsigned int trigger_count;
@ -112,13 +112,13 @@ typedef struct SDL_assert_data
const char *filename;
int linenum;
const char *function;
const struct SDL_assert_data *next;
} SDL_assert_data;
const struct SDL_AssertData *next;
} SDL_AssertData;
#if (SDL_ASSERT_LEVEL > 0)
/* Never call this directly. Use the SDL_assert* macros. */
extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
const char *,
const char *, int)
#if defined(__clang__)
@ -141,10 +141,10 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
#define SDL_enabled_assert(condition) \
do { \
while ( !(condition) ) { \
static struct SDL_assert_data sdl_assert_data = { \
static struct SDL_AssertData sdl_assert_data = { \
0, 0, #condition, 0, 0, 0, 0 \
}; \
const SDL_assert_state sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
continue; /* go again. */ \
} else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
@ -181,8 +181,8 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
#define SDL_assert_always(condition) SDL_enabled_assert(condition)
typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
const SDL_assert_data* data, void* userdata);
typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
const SDL_AssertData* data, void* userdata);
/**
* \brief Set an application-defined assertion handler.
@ -199,7 +199,7 @@ typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
*
* This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
*
* \return SDL_assert_state value of how to handle the assertion failure.
* \return SDL_AssertState value of how to handle the assertion failure.
*
* \param handler Callback function, called when an assertion fails.
* \param userdata A pointer passed to the callback as-is.
@ -246,7 +246,7 @@ extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puse
* The proper way to examine this data looks something like this:
*
* <code>
* const SDL_assert_data *item = SDL_GetAssertionReport();
* const SDL_AssertData *item = SDL_GetAssertionReport();
* while (item) {
* printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
* item->condition, item->function, item->filename,
@ -259,7 +259,7 @@ extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puse
* \return List of all assertions.
* \sa SDL_ResetAssertionReport
*/
extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
/**
* \brief Reset the list of all assertion failures.
@ -270,6 +270,12 @@ extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
*/
extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
/* these had wrong naming conventions until 2.0.4. Please update your app! */
#define SDL_assert_state SDL_AssertState
#define SDL_assert_data SDL_AssertData
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}

View file

@ -269,14 +269,11 @@
#cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
#cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
#if 0
/* !!! FIXME: in configure script version, missing here: */
#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
#endif
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
#cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
#cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@

View file

@ -349,6 +349,7 @@
#undef SDL_FILESYSTEM_UNIX
#undef SDL_FILESYSTEM_WINDOWS
#undef SDL_FILESYSTEM_NACL
#undef SDL_FILESYSTEM_ANDROID
#undef SDL_FILESYSTEM_EMSCRIPTEN
/* Enable assembly routines */

View file

@ -134,6 +134,10 @@ typedef enum
/* Drag and drop events */
SDL_DROPFILE = 0x1000, /**< The system requests a file open */
/* Audio hotplug events */
SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */
/* Render events */
SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
@ -382,6 +386,20 @@ typedef struct SDL_ControllerDeviceEvent
Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
} SDL_ControllerDeviceEvent;
/**
* \brief Audio device event structure (event.adevice.*)
*/
typedef struct SDL_AudioDeviceEvent
{
Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
Uint32 timestamp;
Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
Uint8 padding1;
Uint8 padding2;
Uint8 padding3;
} SDL_AudioDeviceEvent;
/**
* \brief Touch finger event structure (event.tfinger.*)
@ -422,7 +440,7 @@ typedef struct SDL_MultiGestureEvent
*/
typedef struct SDL_DollarGestureEvent
{
Uint32 type; /**< ::SDL_DOLLARGESTURE */
Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
Uint32 timestamp;
SDL_TouchID touchId; /**< The touch device id */
SDL_GestureID gestureId;
@ -516,6 +534,7 @@ typedef union SDL_Event
SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
SDL_AudioDeviceEvent adevice; /**< Audio device event data */
SDL_QuitEvent quit; /**< Quit request event data */
SDL_UserEvent user; /**< Custom event data */
SDL_SysWMEvent syswm; /**< System dependent window event data */

View file

@ -241,7 +241,8 @@ SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller,
/**
* Get the current state of an axis control on a game controller.
*
* The state is a value ranging from -32768 to 32767.
* The state is a value ranging from -32768 to 32767 (except for the triggers,
* which range from 0 to 32767).
*
* The axis indices start at index 0.
*/

View file

@ -533,6 +533,18 @@ extern "C" {
*/
#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
/**
* \brief A variable to control whether mouse and touch events are to be treated together or separately
*
* The variable can be set to the following values:
* "0" - Mouse events will be handled as touch events, and touch will raise fake mouse
* events. This is the behaviour of SDL <= 2.0.3. (default)
* "1" - Mouse events will be handled separately from pure touch events.
*
* The value of this hint is used at runtime, so it can be changed at any time.
*/
#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"
/**
* \brief override the binding element for keyboard inputs for Emscripten builds
*
@ -547,6 +559,18 @@ extern "C" {
*/
#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
/**
* \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
*
* This hint only applies to Unix-like platforms.
*
* The variable can be set to the following values:
* "0" - SDL will install a SIGINT and SIGTERM handler, and when it
* catches a signal, convert it into an SDL_QUIT event.
* "1" - SDL will not install a signal handler at all.
*/
#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS"
/**
* \brief An enumeration of hint priorities
*/

View file

@ -2988,6 +2988,11 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program);
#define GL_ARB_framebuffer_sRGB 1
#endif /* GL_ARB_framebuffer_sRGB */
#ifndef GL_KHR_context_flush_control
#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
#endif /* GL_KHR_context_flush_control */
#ifndef GL_ARB_geometry_shader4
#define GL_ARB_geometry_shader4 1
#define GL_LINES_ADJACENCY_ARB 0x000A

View file

@ -81,8 +81,8 @@ typedef struct SDL_RendererInfo
Uint32 flags; /**< Supported ::SDL_RendererFlags */
Uint32 num_texture_formats; /**< The number of available texture formats */
Uint32 texture_formats[16]; /**< The available texture formats */
int max_texture_width; /**< The maximimum texture width */
int max_texture_height; /**< The maximimum texture height */
int max_texture_width; /**< The maximum texture width */
int max_texture_height; /**< The maximum texture height */
} SDL_RendererInfo;
/**
@ -792,7 +792,7 @@ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,
* \param dstrect A pointer to the destination rectangle, or NULL for the
* entire rendering target.
* \param angle An angle in degrees that indicates the rotation that will be applied to dstrect
* \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2)
* \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2).
* \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture
*
* \return 0 on success, or -1 on error

View file

@ -173,6 +173,8 @@ typedef uint64_t Uint64;
#define SDL_PRIs64 PRIs64
#elif defined(__WIN32__)
#define SDL_PRIs64 "I64d"
#elif defined(__LINUX__) && defined(__LP64__)
#define SDL_PRIs64 "ld"
#else
#define SDL_PRIs64 "lld"
#endif
@ -182,6 +184,8 @@ typedef uint64_t Uint64;
#define SDL_PRIu64 PRIu64
#elif defined(__WIN32__)
#define SDL_PRIu64 "I64u"
#elif defined(__LINUX__) && defined(__LP64__)
#define SDL_PRIu64 "lu"
#else
#define SDL_PRIu64 "llu"
#endif
@ -191,6 +195,8 @@ typedef uint64_t Uint64;
#define SDL_PRIx64 PRIx64
#elif defined(__WIN32__)
#define SDL_PRIx64 "I64x"
#elif defined(__LINUX__) && defined(__LP64__)
#define SDL_PRIx64 "lx"
#else
#define SDL_PRIx64 "llx"
#endif
@ -200,6 +206,8 @@ typedef uint64_t Uint64;
#define SDL_PRIX64 PRIX64
#elif defined(__WIN32__)
#define SDL_PRIX64 "I64X"
#elif defined(__LINUX__) && defined(__LP64__)
#define SDL_PRIX64 "lX"
#else
#define SDL_PRIX64 "llX"
#endif

View file

@ -186,6 +186,7 @@ struct SDL_SysWMinfo
struct
{
HWND window; /**< The window handle */
HDC hdc; /**< The window device context */
} win;
#endif
#if defined(SDL_VIDEO_DRIVER_WINRT)

View file

@ -189,7 +189,8 @@ typedef enum
SDL_GL_CONTEXT_FLAGS,
SDL_GL_CONTEXT_PROFILE_MASK,
SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
SDL_GL_FRAMEBUFFER_SRGB_CAPABLE
SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
SDL_GL_CONTEXT_RELEASE_BEHAVIOR
} SDL_GLattr;
typedef enum
@ -207,6 +208,12 @@ typedef enum
SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008
} SDL_GLcontextFlag;
typedef enum
{
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000,
SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001
} SDL_GLcontextReleaseFlag;
/* Function prototypes */
@ -715,6 +722,9 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
* \param window The window for which the input grab mode should be set.
* \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input.
*
* If the caller enables a grab while another window is currently grabbed,
* the other window loses its grab in favor of the caller's window.
*
* \sa SDL_GetWindowGrab()
*/
extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
@ -729,6 +739,15 @@ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
*/
extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
/**
* \brief Get the window that currently has an input grab enabled.
*
* \return This returns the window if input is grabbed, and NULL otherwise.
*
* \sa SDL_SetWindowGrab()
*/
extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void);
/**
* \brief Set the brightness (gamma correction) for a window.
*

View file

@ -405,6 +405,8 @@ SDL_GetPlatform()
return "BSDI";
#elif __DREAMCAST__
return "Dreamcast";
#elif __EMSCRIPTEN__
return "Emscripten";
#elif __FREEBSD__
return "FreeBSD";
#elif __HAIKU__

View file

@ -120,7 +120,7 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
so that it supports internationalization and thread-safe errors.
*/
static char *
SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
SDL_GetErrorMsg(char *errstr, int maxlen)
{
SDL_error *error;
@ -163,37 +163,55 @@ SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
len =
SDL_snprintf(msg, maxlen, tmp,
error->args[argi++].value_i);
msg += len;
maxlen -= len;
if (len > 0) {
msg += len;
maxlen -= len;
}
break;
case 'f':
len =
SDL_snprintf(msg, maxlen, tmp,
error->args[argi++].value_f);
msg += len;
maxlen -= len;
if (len > 0) {
msg += len;
maxlen -= len;
}
break;
case 'p':
len =
SDL_snprintf(msg, maxlen, tmp,
error->args[argi++].value_ptr);
msg += len;
maxlen -= len;
if (len > 0) {
msg += len;
maxlen -= len;
}
break;
case 's':
len =
SDL_snprintf(msg, maxlen, tmp,
SDL_LookupString(error->args[argi++].
buf));
msg += len;
maxlen -= len;
if (len > 0) {
msg += len;
maxlen -= len;
}
break;
}
} else {
*msg++ = *fmt++;
maxlen -= 1;
}
}
/* slide back if we've overshot the end of our buffer. */
if (maxlen < 0) {
msg -= (-maxlen) + 1;
}
*msg = 0; /* NULL terminate the string */
}
return (errstr);

View file

@ -51,9 +51,7 @@ extern AudioBootStrap QSAAUDIO_bootstrap;
extern AudioBootStrap SUNAUDIO_bootstrap;
extern AudioBootStrap ARTS_bootstrap;
extern AudioBootStrap ESD_bootstrap;
#if SDL_AUDIO_DRIVER_NACL
extern AudioBootStrap NACLAUD_bootstrap;
#endif
extern AudioBootStrap NAS_bootstrap;
extern AudioBootStrap XAUDIO2_bootstrap;
extern AudioBootStrap DSOUND_bootstrap;
@ -163,8 +161,16 @@ get_audio_device(SDL_AudioDeviceID id)
/* stubs for audio drivers that don't need a specific entry point... */
static void
SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
{ /* no-op. */
SDL_AudioDetectDevices_Default(void)
{
/* you have to write your own implementation if these assertions fail. */
SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
if (current_audio.impl.HasCaptureSupport) {
SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
}
}
static void
@ -209,10 +215,16 @@ SDL_AudioDeinitialize_Default(void)
{ /* no-op. */
}
static void
SDL_AudioFreeDeviceHandle_Default(void *handle)
{ /* no-op. */
}
static int
SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
{
return -1;
return SDL_Unsupported();
}
static SDL_INLINE SDL_bool
@ -269,71 +281,139 @@ finalize_audio_entry_points(void)
FILL_STUB(CloseDevice);
FILL_STUB(LockDevice);
FILL_STUB(UnlockDevice);
FILL_STUB(FreeDeviceHandle);
FILL_STUB(Deinitialize);
#undef FILL_STUB
}
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
/* Streaming functions (for when the input and output buffer sizes are different) */
/* Write [length] bytes from buf into the streamer */
static void
SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
{
int i;
for (i = 0; i < length; ++i) {
stream->buffer[stream->write_pos] = buf[i];
++stream->write_pos;
}
}
/* Read [length] bytes out of the streamer into buf */
static void
SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
{
int i;
for (i = 0; i < length; ++i) {
buf[i] = stream->buffer[stream->read_pos];
++stream->read_pos;
}
}
/* device hotplug support... */
static int
SDL_StreamLength(SDL_AudioStreamer * stream)
add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
{
return (stream->write_pos - stream->read_pos) % stream->max_len;
}
/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
#if 0
static int
SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
{
/* First try to allocate the buffer */
stream->buffer = (Uint8 *) SDL_malloc(max_len);
if (stream->buffer == NULL) {
int retval = -1;
const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
if (item == NULL) {
return -1;
}
stream->max_len = max_len;
stream->read_pos = 0;
stream->write_pos = 0;
SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
/* Zero out the buffer */
SDL_memset(stream->buffer, silence, max_len);
item->handle = handle;
SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
return 0;
SDL_LockMutex(current_audio.detectionLock);
item->next = *devices;
*devices = item;
retval = (*devCount)++;
SDL_UnlockMutex(current_audio.detectionLock);
return retval;
}
#endif
/* Deinitialize the stream simply by freeing the buffer */
static void
SDL_StreamDeinit(SDL_AudioStreamer * stream)
static SDL_INLINE int
add_capture_device(const char *name, void *handle)
{
SDL_free(stream->buffer);
/* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
}
#endif
static SDL_INLINE int
add_output_device(const char *name, void *handle)
{
return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
}
static void
free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
{
SDL_AudioDeviceItem *item, *next;
for (item = *devices; item != NULL; item = next) {
next = item->next;
if (item->handle != NULL) {
current_audio.impl.FreeDeviceHandle(item->handle);
}
SDL_free(item);
}
*devices = NULL;
*devCount = 0;
}
/* The audio backends call this when a new device is plugged in. */
void
SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
{
const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
if (device_index != -1) {
/* Post the event, if desired */
if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
SDL_Event event;
SDL_zero(event);
event.adevice.type = SDL_AUDIODEVICEADDED;
event.adevice.which = device_index;
event.adevice.iscapture = iscapture;
SDL_PushEvent(&event);
}
}
}
/* The audio backends call this when a currently-opened device is lost. */
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
{
SDL_assert(get_audio_device(device->id) == device);
if (!device->enabled) {
return;
}
/* Ends the audio callback and mark the device as STOPPED, but the
app still needs to close the device to free resources. */
current_audio.impl.LockDevice(device);
device->enabled = 0;
current_audio.impl.UnlockDevice(device);
/* Post the event, if desired */
if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
SDL_Event event;
SDL_zero(event);
event.adevice.type = SDL_AUDIODEVICEREMOVED;
event.adevice.which = device->id;
event.adevice.iscapture = device->iscapture ? 1 : 0;
SDL_PushEvent(&event);
}
}
static void
mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
{
SDL_AudioDeviceItem *item;
SDL_assert(handle != NULL);
for (item = devices; item != NULL; item = item->next) {
if (item->handle == handle) {
item->handle = NULL;
*removedFlag = SDL_TRUE;
return;
}
}
}
/* The audio backends call this when a device is removed from the system. */
void
SDL_RemoveAudioDevice(const int iscapture, void *handle)
{
SDL_LockMutex(current_audio.detectionLock);
if (iscapture) {
mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
} else {
mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
}
SDL_UnlockMutex(current_audio.detectionLock);
current_audio.impl.FreeDeviceHandle(handle);
}
/* buffer queueing support... */
@ -510,26 +590,17 @@ SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
}
#if defined(__ANDROID__)
#include <android/log.h>
#endif
/* The general mixing thread function */
int SDLCALL
SDL_RunAudio(void *devicep)
{
SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
const int silence = (int) device->spec.silence;
const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
Uint8 *stream;
int stream_len;
void *udata;
void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
Uint32 delay;
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
/* For streaming when the buffer sizes don't match up */
Uint8 *istream;
int istream_len = 0;
#endif
void *udata = device->spec.userdata;
void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
/* The audio mixing is always a high priority thread */
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
@ -538,197 +609,60 @@ SDL_RunAudio(void *devicep)
device->threadid = SDL_ThreadID();
current_audio.impl.ThreadInit(device);
/* Set up the mixing function */
fill = device->spec.callback;
udata = device->spec.userdata;
/* By default do not stream */
device->use_streamer = 0;
if (device->convert.needed) {
#if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
/* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
/* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
stream_max_len = 2 * device->spec.size;
if (device->convert.len_mult > device->convert.len_div) {
stream_max_len *= device->convert.len_mult;
stream_max_len /= device->convert.len_div;
}
if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
0)
return -1;
device->use_streamer = 1;
/* istream_len should be the length of what we grab from the callback and feed to conversion,
so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
*/
istream_len =
device->spec.size * device->convert.len_div /
device->convert.len_mult;
/* Loop, filling the audio buffers */
while (!device->shutdown) {
/* Fill the current buffer with sound */
if (device->convert.needed) {
stream = device->convert.buf;
} else if (device->enabled) {
stream = current_audio.impl.GetDeviceBuf(device);
} else {
/* if the device isn't enabled, we still write to the
fake_stream, so the app's callback will fire with
a regular frequency, in case they depend on that
for timing or progress. They can use hotplug
now to know if the device failed. */
stream = NULL;
}
#endif
stream_len = device->convert.len;
} else {
stream_len = device->spec.size;
}
/* Calculate the delay while paused */
delay = ((device->spec.samples * 1000) / device->spec.freq);
/* Determine if the streamer is necessary here */
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
if (device->use_streamer == 1) {
/* This code is almost the same as the old code. The difference is, instead of reading
directly from the callback into "stream", then converting and sending the audio off,
we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
However, reading and writing with streamer are done separately:
- We only call the callback and write to the streamer when the streamer does not
contain enough samples to output to the device.
- We only read from the streamer and tell the device to play when the streamer
does have enough samples to output.
This allows us to perform resampling in the conversion step, where the output of the
resampling process can be any number. We will have to see what a good size for the
stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
*/
while (device->enabled) {
if (device->paused) {
SDL_Delay(delay);
continue;
}
/* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
if (SDL_StreamLength(&device->streamer) < stream_len) {
/* Set up istream */
if (device->convert.needed) {
if (device->convert.buf) {
istream = device->convert.buf;
} else {
continue;
}
} else {
/* FIXME: Ryan, this is probably wrong. I imagine we don't want to get
* a device buffer both here and below in the stream output.
*/
istream = current_audio.impl.GetDeviceBuf(device);
if (istream == NULL) {
istream = device->fake_stream;
}
}
/* Read from the callback into the _input_ stream */
SDL_LockMutex(device->mixer_lock);
(*fill) (udata, istream, istream_len);
SDL_UnlockMutex(device->mixer_lock);
/* Convert the audio if necessary and write to the streamer */
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
if (istream == NULL) {
istream = device->fake_stream;
}
/* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
SDL_StreamWrite(&device->streamer, device->convert.buf,
device->convert.len_cvt);
} else {
SDL_StreamWrite(&device->streamer, istream, istream_len);
}
}
/* Only output audio if the streamer has enough to output */
if (SDL_StreamLength(&device->streamer) >= stream_len) {
/* Set up the output stream */
if (device->convert.needed) {
if (device->convert.buf) {
stream = device->convert.buf;
} else {
continue;
}
} else {
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
}
/* Now read from the streamer */
SDL_StreamRead(&device->streamer, stream, stream_len);
/* Ready current buffer for play and change current buffer */
if (stream != device->fake_stream) {
current_audio.impl.PlayDevice(device);
/* Wait for an audio buffer to become available */
current_audio.impl.WaitDevice(device);
} else {
SDL_Delay(delay);
}
}
if (stream == NULL) {
stream = device->fake_stream;
}
} else
#endif
{
/* Otherwise, do not use the streamer. This is the old code. */
const int silence = (int) device->spec.silence;
/* Loop, filling the audio buffers */
while (device->enabled) {
/* !!! FIXME: this should be LockDevice. */
SDL_LockMutex(device->mixer_lock);
if (device->paused) {
SDL_memset(stream, silence, stream_len);
} else {
(*fill) (udata, stream, stream_len);
}
SDL_UnlockMutex(device->mixer_lock);
/* Fill the current buffer with sound */
if (device->convert.needed) {
if (device->convert.buf) {
stream = device->convert.buf;
} else {
continue;
}
/* Convert the audio if necessary */
if (device->enabled && device->convert.needed) {
SDL_ConvertAudio(&device->convert);
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
} else {
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
}
SDL_LockMutex(device->mixer_lock);
if (device->paused) {
SDL_memset(stream, silence, stream_len);
} else {
(*fill) (udata, stream, stream_len);
}
SDL_UnlockMutex(device->mixer_lock);
/* Convert the audio if necessary */
if (device->convert.needed) {
SDL_ConvertAudio(&device->convert);
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
stream = device->fake_stream;
}
SDL_memcpy(stream, device->convert.buf,
device->convert.len_cvt);
}
}
/* Ready current buffer for play and change current buffer */
if (stream != device->fake_stream) {
current_audio.impl.PlayDevice(device);
/* Wait for an audio buffer to become available */
current_audio.impl.WaitDevice(device);
} else {
SDL_Delay(delay);
}
/* Ready current buffer for play and change current buffer */
if (stream == device->fake_stream) {
SDL_Delay(delay);
} else {
current_audio.impl.PlayDevice(device);
current_audio.impl.WaitDevice(device);
}
}
/* Wait for the audio to drain.. */
/* Wait for the audio to drain. */
current_audio.impl.WaitDone(device);
/* If necessary, deinit the streamer */
#if 0 /* !!! FIXME: rewrite/remove this streamer code. */
if (device->use_streamer == 1)
SDL_StreamDeinit(&device->streamer);
#endif
return (0);
return 0;
}
@ -761,16 +695,16 @@ SDL_ParseAudioFormat(const char *string)
int
SDL_GetNumAudioDrivers(void)
{
return (SDL_arraysize(bootstrap) - 1);
return SDL_arraysize(bootstrap) - 1;
}
const char *
SDL_GetAudioDriver(int index)
{
if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
return (bootstrap[index]->name);
return bootstrap[index]->name;
}
return (NULL);
return NULL;
}
int
@ -784,8 +718,8 @@ SDL_AudioInit(const char *driver_name)
SDL_AudioQuit(); /* shutdown driver if already running. */
}
SDL_memset(&current_audio, '\0', sizeof(current_audio));
SDL_memset(open_devices, '\0', sizeof(open_devices));
SDL_zero(current_audio);
SDL_zero(open_devices);
/* Select the proper audio driver */
if (driver_name == NULL) {
@ -801,7 +735,7 @@ SDL_AudioInit(const char *driver_name)
}
tried_to_init = 1;
SDL_memset(&current_audio, 0, sizeof(current_audio));
SDL_zero(current_audio);
current_audio.name = backend->name;
current_audio.desc = backend->desc;
initialized = backend->init(&current_audio.impl);
@ -817,13 +751,18 @@ SDL_AudioInit(const char *driver_name)
}
}
SDL_memset(&current_audio, 0, sizeof(current_audio));
return (-1); /* No driver was available, so fail. */
SDL_zero(current_audio);
return -1; /* No driver was available, so fail. */
}
current_audio.detectionLock = SDL_CreateMutex();
finalize_audio_entry_points();
return (0);
/* Make sure we have a list of devices available at startup. */
current_audio.impl.DetectDevices();
return 0;
}
/*
@ -835,50 +774,32 @@ SDL_GetCurrentAudioDriver()
return current_audio.name;
}
/* Clean out devices that we've removed but had to keep around for stability. */
static void
free_device_list(char ***devices, int *devCount)
clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
{
int i = *devCount;
if ((i > 0) && (*devices != NULL)) {
while (i--) {
SDL_free((*devices)[i]);
SDL_AudioDeviceItem *item = *devices;
SDL_AudioDeviceItem *prev = NULL;
int total = 0;
while (item) {
SDL_AudioDeviceItem *next = item->next;
if (item->handle != NULL) {
total++;
prev = item;
} else {
if (prev) {
prev->next = next;
} else {
*devices = next;
}
SDL_free(item);
}
item = next;
}
SDL_free(*devices);
*devices = NULL;
*devCount = 0;
}
static
void SDL_AddCaptureAudioDevice(const char *_name)
{
char *name = NULL;
void *ptr = SDL_realloc(current_audio.inputDevices,
(current_audio.inputDeviceCount+1) * sizeof(char*));
if (ptr == NULL) {
return; /* oh well. */
}
current_audio.inputDevices = (char **) ptr;
name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
}
static
void SDL_AddOutputAudioDevice(const char *_name)
{
char *name = NULL;
void *ptr = SDL_realloc(current_audio.outputDevices,
(current_audio.outputDeviceCount+1) * sizeof(char*));
if (ptr == NULL) {
return; /* oh well. */
}
current_audio.outputDevices = (char **) ptr;
name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
*devCount = total;
*removedFlag = SDL_FALSE;
}
@ -891,29 +812,18 @@ SDL_GetNumAudioDevices(int iscapture)
return -1;
}
if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
return 0;
SDL_LockMutex(current_audio.detectionLock);
if (iscapture && current_audio.captureDevicesRemoved) {
clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
}
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
return 1;
if (!iscapture && current_audio.outputDevicesRemoved) {
clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
current_audio.outputDevicesRemoved = SDL_FALSE;
}
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
return 1;
}
if (iscapture) {
free_device_list(&current_audio.inputDevices,
&current_audio.inputDeviceCount);
current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
retval = current_audio.inputDeviceCount;
} else {
free_device_list(&current_audio.outputDevices,
&current_audio.outputDeviceCount);
current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
retval = current_audio.outputDeviceCount;
}
retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
SDL_UnlockMutex(current_audio.detectionLock);
return retval;
}
@ -922,6 +832,8 @@ SDL_GetNumAudioDevices(int iscapture)
const char *
SDL_GetAudioDeviceName(int index, int iscapture)
{
const char *retval = NULL;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
SDL_SetError("Audio subsystem is not initialized");
return NULL;
@ -932,39 +844,28 @@ SDL_GetAudioDeviceName(int index, int iscapture)
return NULL;
}
if (index < 0) {
goto no_such_device;
if (index >= 0) {
SDL_AudioDeviceItem *item;
int i;
SDL_LockMutex(current_audio.detectionLock);
item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
if (index < i) {
for (i--; i > index; i--, item = item->next) {
SDL_assert(item != NULL);
}
SDL_assert(item != NULL);
retval = item->name;
}
SDL_UnlockMutex(current_audio.detectionLock);
}
if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
if (index > 0) {
goto no_such_device;
}
return DEFAULT_INPUT_DEVNAME;
if (retval == NULL) {
SDL_SetError("No such device");
}
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
if (index > 0) {
goto no_such_device;
}
return DEFAULT_OUTPUT_DEVNAME;
}
if (iscapture) {
if (index >= current_audio.inputDeviceCount) {
goto no_such_device;
}
return current_audio.inputDevices[index];
} else {
if (index >= current_audio.outputDeviceCount) {
goto no_such_device;
}
return current_audio.outputDevices[index];
}
no_such_device:
SDL_SetError("No such device");
return NULL;
return retval;
}
@ -972,6 +873,7 @@ static void
close_audio_device(SDL_AudioDevice * device)
{
device->enabled = 0;
device->shutdown = 1;
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
@ -1065,6 +967,8 @@ open_audio_device(const char *devname, int iscapture,
SDL_AudioSpec _obtained;
SDL_AudioDevice *device;
SDL_bool build_cvt;
void *handle = NULL;
Uint32 stream_len;
int i = 0;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
@ -1077,6 +981,18 @@ open_audio_device(const char *devname, int iscapture,
return 0;
}
/* Find an available device ID... */
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
if (open_devices[id] == NULL) {
break;
}
}
if (id == SDL_arraysize(open_devices)) {
SDL_SetError("Too many open audio devices");
return 0;
}
if (!obtained) {
obtained = &_obtained;
}
@ -1112,9 +1028,7 @@ open_audio_device(const char *devname, int iscapture,
return 0;
}
}
}
if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
} else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
SDL_SetError("No such device");
return 0;
@ -1127,6 +1041,30 @@ open_audio_device(const char *devname, int iscapture,
return 0;
}
}
} else if (devname != NULL) {
/* if the app specifies an exact string, we can pass the backend
an actual device handle thingey, which saves them the effort of
figuring out what device this was (such as, reenumerating
everything again to find the matching human-readable name).
It might still need to open a device based on the string for,
say, a network audio server, but this optimizes some cases. */
SDL_AudioDeviceItem *item;
SDL_LockMutex(current_audio.detectionLock);
for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
handle = item->handle;
break;
}
}
SDL_UnlockMutex(current_audio.detectionLock);
}
if (!current_audio.impl.AllowsArbitraryDeviceNames) {
/* has to be in our device list, or the default device. */
if ((handle == NULL) && (devname != NULL)) {
SDL_SetError("No such device.");
return 0;
}
}
device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
@ -1135,12 +1073,13 @@ open_audio_device(const char *devname, int iscapture,
return 0;
}
SDL_zerop(device);
device->id = id + 1;
device->spec = *obtained;
device->enabled = 1;
device->paused = 1;
device->iscapture = iscapture;
/* Create a semaphore for locking the sound buffers */
/* Create a mutex for locking the sound buffers */
if (!current_audio.impl.SkipMixerLock) {
device->mixer_lock = SDL_CreateMutex();
if (device->mixer_lock == NULL) {
@ -1150,26 +1089,12 @@ open_audio_device(const char *devname, int iscapture,
}
}
/* force a device detection if we haven't done one yet. */
if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
((!iscapture) && (current_audio.outputDevices == NULL)) ) {
SDL_GetNumAudioDevices(iscapture);
}
if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
close_audio_device(device);
return 0;
}
device->opened = 1;
/* Allocate a fake audio memory buffer */
device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
if (device->fake_stream == NULL) {
close_audio_device(device);
SDL_OutOfMemory();
return 0;
}
/* See if we need to do any conversion */
build_cvt = SDL_FALSE;
if (obtained->freq != device->spec.freq) {
@ -1228,6 +1153,19 @@ open_audio_device(const char *devname, int iscapture,
}
}
/* Allocate a fake audio memory buffer */
stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
if (device->spec.size > stream_len) {
stream_len = device->spec.size;
}
SDL_assert(stream_len > 0);
device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
if (device->fake_stream == NULL) {
close_audio_device(device);
SDL_OutOfMemory();
return 0;
}
if (device->spec.callback == NULL) { /* use buffer queueing? */
/* pool a few packets to start. Enough for two callbacks. */
const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
@ -1247,25 +1185,14 @@ open_audio_device(const char *devname, int iscapture,
device->spec.userdata = device;
}
/* Find an available device ID and store the structure... */
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
if (open_devices[id] == NULL) {
open_devices[id] = device;
break;
}
}
if (id == SDL_arraysize(open_devices)) {
SDL_SetError("Too many open audio devices");
close_audio_device(device);
return 0;
}
/* add it to our list of open devices. */
open_devices[id] = device;
/* Start the audio thread if necessary */
if (!current_audio.impl.ProvidesOwnCallbackThread) {
/* Start the audio thread */
char name[64];
SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
/* !!! FIXME: this is nasty. */
#if defined(__WIN32__) && !defined(HAVE_LIBC)
#undef SDL_CreateThread
@ -1278,13 +1205,13 @@ open_audio_device(const char *devname, int iscapture,
device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
#endif
if (device->thread == NULL) {
SDL_CloseAudioDevice(id + 1);
SDL_CloseAudioDevice(device->id);
SDL_SetError("Couldn't create audio thread");
return 0;
}
}
return id + 1;
return device->id;
}
@ -1296,14 +1223,14 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
/* Start up the audio driver, if necessary. This is legacy behaviour! */
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
return (-1);
return -1;
}
}
/* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
if (open_devices[0] != NULL) {
SDL_SetError("Audio device is already opened");
return (-1);
return -1;
}
if (obtained) {
@ -1314,7 +1241,7 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
}
SDL_assert((id == 0) || (id == 1));
return ((id == 0) ? -1 : 0);
return (id == 0) ? -1 : 0;
}
SDL_AudioDeviceID
@ -1338,7 +1265,7 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
status = SDL_AUDIO_PLAYING;
}
}
return (status);
return status;
}
@ -1429,14 +1356,16 @@ SDL_AudioQuit(void)
}
}
free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
/* Free the driver data */
current_audio.impl.Deinitialize();
free_device_list(&current_audio.outputDevices,
&current_audio.outputDeviceCount);
free_device_list(&current_audio.inputDevices,
&current_audio.inputDeviceCount);
SDL_memset(&current_audio, '\0', sizeof(current_audio));
SDL_memset(open_devices, '\0', sizeof(open_devices));
SDL_DestroyMutex(current_audio.detectionLock);
SDL_zero(current_audio);
SDL_zero(open_devices);
}
#define NUM_FORMATS 10
@ -1474,16 +1403,16 @@ SDL_FirstAudioFormat(SDL_AudioFormat format)
}
}
format_idx_sub = 0;
return (SDL_NextAudioFormat());
return SDL_NextAudioFormat();
}
SDL_AudioFormat
SDL_NextAudioFormat(void)
{
if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
return (0);
return 0;
}
return (format_list[format_idx][format_idx_sub++]);
return format_list[format_idx][format_idx_sub++];
}
void

View file

@ -46,18 +46,21 @@
#define _PATH_DEV_AUDIO "/dev/audio"
#endif
static SDL_INLINE void
test_device(const char *fname, int flags, int (*test) (int fd),
SDL_AddAudioDevice addfn)
static void
test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd))
{
struct stat sb;
if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
const int audio_fd = open(fname, flags, 0);
if (audio_fd >= 0) {
if (test(audio_fd)) {
addfn(fname);
}
const int okay = test(audio_fd);
close(audio_fd);
if (okay) {
static size_t dummyhandle = 0;
dummyhandle++;
SDL_assert(dummyhandle != 0);
SDL_AddAudioDevice(iscapture, fname, (void *) dummyhandle);
}
}
}
}
@ -68,11 +71,10 @@ test_stub(int fd)
return 1;
}
void
SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
SDL_AddAudioDevice addfn)
static void
SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int))
{
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
const char *audiodev;
char audiopath[1024];
@ -97,17 +99,25 @@ SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
}
}
}
test_device(audiodev, flags, test, addfn);
test_device(iscapture, audiodev, flags, test);
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, addfn);
test_device(iscapture, audiopath, flags, test);
}
}
}
void
SDL_EnumUnixAudioDevices(const int classic, int (*test)(int))
{
SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test);
SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
}
#endif /* Audio driver selection */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -33,7 +33,6 @@
#define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
#endif
void SDL_EnumUnixAudioDevices(int iscapture, int classic,
int (*test) (int fd), SDL_AddAudioDevice addfn);
extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -30,8 +30,21 @@
typedef struct SDL_AudioDevice SDL_AudioDevice;
#define _THIS SDL_AudioDevice *_this
/* Used by audio targets during DetectDevices() */
typedef void (*SDL_AddAudioDevice)(const char *name);
/* Audio targets should call this as devices are added to the system (such as
a USB headset being plugged in), and should also be called for
for every device found during DetectDevices(). */
extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle);
/* Audio targets should call this as devices are removed, so SDL can update
its list of available devices. */
extern void SDL_RemoveAudioDevice(const int iscapture, void *handle);
/* Audio targets should call this if an opened audio device is lost while
being used. This can happen due to i/o errors, or a device being unplugged,
etc. If the device is totally gone, please also call SDL_RemoveAudioDevice()
as appropriate so SDL's list of devices is accurate. */
extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
/* This is the size of a packet when using SDL_QueueAudio(). We allocate
these as necessary and pool them, under the assumption that we'll
@ -55,8 +68,8 @@ typedef struct SDL_AudioBufferQueue
typedef struct SDL_AudioDriverImpl
{
void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
int (*OpenDevice) (_THIS, const char *devname, int iscapture);
void (*DetectDevices) (void);
int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
void (*ThreadInit) (_THIS); /* Called by audio thread at start */
void (*WaitDevice) (_THIS);
void (*PlayDevice) (_THIS);
@ -66,19 +79,34 @@ typedef struct SDL_AudioDriverImpl
void (*CloseDevice) (_THIS);
void (*LockDevice) (_THIS);
void (*UnlockDevice) (_THIS);
void (*FreeDeviceHandle) (void *handle); /**< SDL is done with handle from SDL_AddAudioDevice() */
void (*Deinitialize) (void);
/* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
/* Some flags to push duplicate code into the core and reduce #ifdefs. */
/* !!! FIXME: these should be SDL_bool */
int ProvidesOwnCallbackThread;
int SkipMixerLock; /* !!! FIXME: do we need this anymore? */
int HasCaptureSupport;
int OnlyHasDefaultOutputDevice;
int OnlyHasDefaultInputDevice;
int AllowsArbitraryDeviceNames;
} SDL_AudioDriverImpl;
typedef struct SDL_AudioDeviceItem
{
void *handle;
struct SDL_AudioDeviceItem *next;
#if (defined(__GNUC__) && (__GNUC__ <= 2))
char name[1]; /* actually variable length. */
#else
char name[];
#endif
} SDL_AudioDeviceItem;
typedef struct SDL_AudioDriver
{
/* * * */
@ -91,11 +119,14 @@ typedef struct SDL_AudioDriver
SDL_AudioDriverImpl impl;
char **outputDevices;
/* A mutex for device detection */
SDL_mutex *detectionLock;
SDL_bool captureDevicesRemoved;
SDL_bool outputDevicesRemoved;
int outputDeviceCount;
char **inputDevices;
int inputDeviceCount;
SDL_AudioDeviceItem *outputDevices;
SDL_AudioDeviceItem *inputDevices;
} SDL_AudioDriver;
@ -113,6 +144,7 @@ struct SDL_AudioDevice
{
/* * * */
/* Data common to all devices */
SDL_AudioDeviceID id;
/* The current audio specification (shared with audio thread) */
SDL_AudioSpec spec;
@ -125,15 +157,17 @@ struct SDL_AudioDevice
SDL_AudioStreamer streamer;
/* Current state flags */
/* !!! FIXME: should be SDL_bool */
int iscapture;
int enabled;
int enabled; /* true if device is functioning and connected. */
int shutdown; /* true if we are signaling the play thread to end. */
int paused;
int opened;
/* Fake audio buffer for when the audio hardware is busy */
Uint8 *fake_stream;
/* A semaphore for locking the mixing buffers */
/* A mutex for locking the mixing buffers */
SDL_mutex *mixer_lock;
/* A thread to feed the audio device */

View file

@ -320,7 +320,7 @@ ALSA_PlayDevice(_THIS)
/* Hmm, not much we can do - abort */
fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
ALSA_snd_strerror(status));
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
return;
}
continue;
@ -465,7 +465,7 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override)
}
static int
ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int status = 0;
snd_pcm_t *pcm_handle = NULL;

View file

@ -35,7 +35,7 @@
static SDL_AudioDevice* audioDevice = NULL;
static int
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;

View file

@ -151,7 +151,7 @@ ARTS_WaitDevice(_THIS)
/* Check every 10 loops */
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
@ -179,7 +179,7 @@ ARTS_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
@ -229,7 +229,7 @@ ARTS_Suspend(void)
}
static int
ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int rc = 0;
int bits = 0, frag_spec = 0;

View file

@ -51,9 +51,9 @@
static void
BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
BSDAUDIO_DetectDevices(void)
{
SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
SDL_EnumUnixAudioDevices(0, NULL);
}
@ -150,7 +150,7 @@ BSDAUDIO_WaitDevice(_THIS)
the user know what happened.
*/
fprintf(stderr, "SDL: %s\n", message);
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
/* Don't try to close - may hang */
this->hidden->audio_fd = -1;
#ifdef DEBUG_AUDIO
@ -195,7 +195,7 @@ BSDAUDIO_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
@ -224,7 +224,7 @@ BSDAUDIO_CloseDevice(_THIS)
}
static int
BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
SDL_AudioFormat format = 0;
@ -348,6 +348,8 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
impl->CloseDevice = BSDAUDIO_CloseDevice;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
}

View file

@ -19,6 +19,9 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_COREAUDIO
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
@ -37,31 +40,48 @@ static void COREAUDIO_CloseDevice(_THIS);
}
#if MACOSX_COREAUDIO
typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data);
static const AudioObjectPropertyAddress devlist_address = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
static void
addToDevList(const char *name, AudioDeviceID devId, void *data)
typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data);
typedef struct AudioDeviceList
{
SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
addfn(name);
AudioDeviceID devid;
SDL_bool alive;
struct AudioDeviceList *next;
} AudioDeviceList;
static AudioDeviceList *output_devs = NULL;
static AudioDeviceList *capture_devs = NULL;
static SDL_bool
add_to_internal_dev_list(const int iscapture, AudioDeviceID devId)
{
AudioDeviceList *item = (AudioDeviceList *) SDL_malloc(sizeof (AudioDeviceList));
if (item == NULL) {
return SDL_FALSE;
}
item->devid = devId;
item->alive = SDL_TRUE;
item->next = iscapture ? capture_devs : output_devs;
if (iscapture) {
capture_devs = item;
} else {
output_devs = item;
}
return SDL_TRUE;
}
typedef struct
{
const char *findname;
AudioDeviceID devId;
int found;
} FindDevIdData;
static void
findDevId(const char *name, AudioDeviceID devId, void *_data)
addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
{
FindDevIdData *data = (FindDevIdData *) _data;
if (!data->found) {
if (SDL_strcmp(name, data->findname) == 0) {
data->found = 1;
data->devId = devId;
}
if (add_to_internal_dev_list(iscapture, devId)) {
SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
}
}
@ -74,14 +94,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
UInt32 i = 0;
UInt32 max = 0;
AudioObjectPropertyAddress addr = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
0, NULL, &size);
result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
&devlist_address, 0, NULL, &size);
if (result != kAudioHardwareNoError)
return;
@ -89,8 +103,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
if (devs == NULL)
return;
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
0, NULL, &size, devs);
result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
&devlist_address, 0, NULL, &size, devs);
if (result != kAudioHardwareNoError)
return;
@ -102,10 +116,17 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
AudioBufferList *buflist = NULL;
int usable = 0;
CFIndex len = 0;
const AudioObjectPropertyAddress addr = {
kAudioDevicePropertyStreamConfiguration,
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
kAudioDevicePropertyScopeOutput;
addr.mSelector = kAudioDevicePropertyStreamConfiguration;
const AudioObjectPropertyAddress nameaddr = {
kAudioObjectPropertyName,
iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};
result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size);
if (result != noErr)
@ -133,9 +154,9 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
if (!usable)
continue;
addr.mSelector = kAudioObjectPropertyName;
size = sizeof (CFStringRef);
result = AudioObjectGetPropertyData(dev, &addr, 0, NULL, &size, &cfstr);
result = AudioObjectGetPropertyData(dev, &nameaddr, 0, NULL, &size, &cfstr);
if (result != kAudioHardwareNoError)
continue;
@ -166,79 +187,84 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
((iscapture) ? "capture" : "output"),
(int) *devCount, ptr, (int) dev);
#endif
addfn(ptr, dev, addfndata);
addfn(ptr, iscapture, dev, addfndata);
}
SDL_free(ptr); /* addfn() would have copied the string. */
}
}
static void
COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
free_audio_device_list(AudioDeviceList **list)
{
build_device_list(iscapture, addToDevList, addfn);
AudioDeviceList *item = *list;
while (item) {
AudioDeviceList *next = item->next;
SDL_free(item);
item = next;
}
*list = NULL;
}
static int
find_device_by_name(_THIS, const char *devname, int iscapture)
static void
COREAUDIO_DetectDevices(void)
{
AudioDeviceID devid = 0;
OSStatus result = noErr;
UInt32 size = 0;
UInt32 alive = 0;
pid_t pid = 0;
build_device_list(SDL_TRUE, addToDevList, NULL);
build_device_list(SDL_FALSE, addToDevList, NULL);
}
AudioObjectPropertyAddress addr = {
0,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
if (devname == NULL) {
size = sizeof (AudioDeviceID);
addr.mSelector =
((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
kAudioHardwarePropertyDefaultOutputDevice);
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
0, NULL, &size, &devid);
CHECK_RESULT("AudioHardwareGetProperty (default device)");
} else {
FindDevIdData data;
SDL_zero(data);
data.findname = devname;
build_device_list(iscapture, findDevId, &data);
if (!data.found) {
SDL_SetError("CoreAudio: No such audio device.");
return 0;
static void
build_device_change_list(const char *name, const int iscapture, AudioDeviceID devId, void *data)
{
AudioDeviceList **list = (AudioDeviceList **) data;
AudioDeviceList *item;
for (item = *list; item != NULL; item = item->next) {
if (item->devid == devId) {
item->alive = SDL_TRUE;
return;
}
devid = data.devId;
}
addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
kAudioDevicePropertyScopeOutput;
add_to_internal_dev_list(iscapture, devId); /* new device, add it. */
SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
}
size = sizeof (alive);
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
CHECK_RESULT
("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
if (!alive) {
SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
return 0;
static void
reprocess_device_list(const int iscapture, AudioDeviceList **list)
{
AudioDeviceList *item;
AudioDeviceList *prev = NULL;
for (item = *list; item != NULL; item = item->next) {
item->alive = SDL_FALSE;
}
addr.mSelector = kAudioDevicePropertyHogMode;
size = sizeof (pid);
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
build_device_list(iscapture, build_device_change_list, list);
/* 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;
/* free items in the list that aren't still alive. */
item = *list;
while (item != NULL) {
AudioDeviceList *next = item->next;
if (item->alive) {
prev = item;
} else {
SDL_RemoveAudioDevice(iscapture, (void *) ((size_t) item->devid));
if (prev) {
prev->next = item->next;
} else {
*list = item->next;
}
SDL_free(item);
}
item = next;
}
}
this->hidden->deviceID = devid;
return 1;
/* this is called when the system's list of available audio devices changes. */
static OSStatus
device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
{
reprocess_device_list(SDL_TRUE, &capture_devs);
reprocess_device_list(SDL_FALSE, &output_devs);
return 0;
}
#endif
@ -314,11 +340,54 @@ inputCallback(void *inRefCon,
}
#if MACOSX_COREAUDIO
static const AudioObjectPropertyAddress alive_address =
{
kAudioDevicePropertyDeviceIsAlive,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
static OSStatus
device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
{
SDL_AudioDevice *this = (SDL_AudioDevice *) data;
SDL_bool dead = SDL_FALSE;
UInt32 isAlive = 1;
UInt32 size = sizeof (isAlive);
OSStatus error;
if (!this->enabled) {
return 0; /* already known to be dead. */
}
error = AudioObjectGetPropertyData(this->hidden->deviceID, &alive_address,
0, NULL, &size, &isAlive);
if (error == kAudioHardwareBadDeviceError) {
dead = SDL_TRUE; /* device was unplugged. */
} else if ((error == kAudioHardwareNoError) && (!isAlive)) {
dead = SDL_TRUE; /* device died in some other way. */
}
if (dead) {
SDL_OpenedAudioDeviceDisconnected(this);
}
return 0;
}
#endif
static void
COREAUDIO_CloseDevice(_THIS)
{
if (this->hidden != NULL) {
if (this->hidden->audioUnitOpened) {
#if MACOSX_COREAUDIO
/* Unregister our disconnect callback. */
AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
#endif
AURenderCallbackStruct callback;
const AudioUnitElement output_bus = 0;
const AudioUnitElement input_bus = 1;
@ -352,9 +421,63 @@ COREAUDIO_CloseDevice(_THIS)
}
}
#if MACOSX_COREAUDIO
static int
prepare_device(_THIS, void *handle, int iscapture)
{
AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
OSStatus result = noErr;
UInt32 size = 0;
UInt32 alive = 0;
pid_t pid = 0;
AudioObjectPropertyAddress addr = {
0,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
if (handle == NULL) {
size = sizeof (AudioDeviceID);
addr.mSelector =
((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
kAudioHardwarePropertyDefaultOutputDevice);
result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
0, NULL, &size, &devid);
CHECK_RESULT("AudioHardwareGetProperty (default device)");
}
addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
kAudioDevicePropertyScopeOutput;
size = sizeof (alive);
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
CHECK_RESULT
("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
if (!alive) {
SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
return 0;
}
addr.mSelector = kAudioDevicePropertyHogMode;
size = sizeof (pid);
result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &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;
}
#endif
static int
prepare_audiounit(_THIS, const char *devname, int iscapture,
prepare_audiounit(_THIS, void *handle, int iscapture,
const AudioStreamBasicDescription * strdesc)
{
OSStatus result = noErr;
@ -373,8 +496,7 @@ prepare_audiounit(_THIS, const char *devname, int iscapture,
kAudioUnitScope_Input);
#if MACOSX_COREAUDIO
if (!find_device_by_name(this, devname, iscapture)) {
SDL_SetError("Couldn't find requested CoreAudio device");
if (!prepare_device(this, handle, iscapture)) {
return 0;
}
#endif
@ -451,13 +573,18 @@ prepare_audiounit(_THIS, const char *devname, int iscapture,
result = AudioOutputUnitStart(this->hidden->audioUnit);
CHECK_RESULT("AudioOutputUnitStart");
#if MACOSX_COREAUDIO
/* Fire a callback if the device stops being "alive" (disconnected, etc). */
AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
#endif
/* We're running! */
return 1;
}
static int
COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
AudioStreamBasicDescription strdesc;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
@ -516,7 +643,7 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
strdesc.mBytesPerPacket =
strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
COREAUDIO_CloseDevice(this);
return -1; /* prepare_audiounit() will call SDL_SetError()... */
}
@ -524,15 +651,27 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
return 0; /* good to go. */
}
static void
COREAUDIO_Deinitialize(void)
{
#if MACOSX_COREAUDIO
AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
free_audio_device_list(&capture_devs);
free_audio_device_list(&output_devs);
#endif
}
static int
COREAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->OpenDevice = COREAUDIO_OpenDevice;
impl->CloseDevice = COREAUDIO_CloseDevice;
impl->Deinitialize = COREAUDIO_Deinitialize;
#if MACOSX_COREAUDIO
impl->DetectDevices = COREAUDIO_DetectDevices;
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
#else
impl->OnlyHasDefaultOutputDevice = 1;
@ -554,4 +693,6 @@ AudioBootStrap COREAUDIO_bootstrap = {
"coreaudio", "CoreAudio", COREAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_COREAUDIO */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -144,15 +144,22 @@ SetDSerror(const char *function, int code)
return SDL_SetError("%s", errbuf);
}
static void
DSOUND_FreeDeviceHandle(void *handle)
{
SDL_free(handle);
}
static BOOL CALLBACK
FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
{
SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
const int iscapture = (int) ((size_t) data);
if (guid != NULL) { /* skip default device */
char *str = WIN_StringToUTF8(desc);
if (str != NULL) {
addfn(str);
LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
SDL_memcpy(cpyguid, guid, sizeof (GUID));
SDL_AddAudioDevice(iscapture, str, cpyguid);
SDL_free(str); /* addfn() makes a copy of this string. */
}
}
@ -160,13 +167,10 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
}
static void
DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
DSOUND_DetectDevices(void)
{
if (iscapture) {
pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
} else {
pDirectSoundEnumerateW(FindAllDevs, addfn);
}
pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1));
pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0));
}
@ -419,53 +423,14 @@ CreateSecondary(_THIS, HWND focus)
return (numchunks);
}
typedef struct FindDevGUIDData
{
const char *devname;
GUID guid;
int found;
} FindDevGUIDData;
static BOOL CALLBACK
FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
{
if (guid != NULL) { /* skip the default device. */
FindDevGUIDData *data = (FindDevGUIDData *) _data;
char *str = WIN_StringToUTF8(desc);
const int match = (SDL_strcmp(str, data->devname) == 0);
SDL_free(str);
if (match) {
data->found = 1;
SDL_memcpy(&data->guid, guid, sizeof (data->guid));
return FALSE; /* found it! stop enumerating. */
}
}
return TRUE; /* keep enumerating. */
}
static int
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
HRESULT result;
SDL_bool valid_format = SDL_FALSE;
SDL_bool tried_format = SDL_FALSE;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
FindDevGUIDData devguid;
LPGUID guid = NULL;
if (devname != NULL) {
devguid.found = 0;
devguid.devname = devname;
if (iscapture)
pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
else
pDirectSoundEnumerateW(FindDevGUID, &devguid);
if (!devguid.found) {
return SDL_SetError("DirectSound: Requested device not found");
}
guid = &devguid.guid;
}
LPGUID guid = (LPGUID) handle;
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
@ -536,6 +501,8 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
impl->WaitDone = DSOUND_WaitDone;
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
impl->CloseDevice = DSOUND_CloseDevice;
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
impl->Deinitialize = DSOUND_Deinitialize;
return 1; /* this audio target is available. */

View file

@ -71,7 +71,7 @@ DISKAUD_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (written != this->hidden->mixlen) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
@ -100,7 +100,7 @@ DISKAUD_CloseDevice(_THIS)
}
static int
DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
const char *fname = DISKAUD_GetOutputFilename(devname);
@ -151,6 +151,8 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
impl->CloseDevice = DISKAUD_CloseDevice;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
}

View file

@ -51,9 +51,9 @@
static void
DSP_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
DSP_DetectDevices(void)
{
SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
SDL_EnumUnixAudioDevices(0, NULL);
}
@ -74,7 +74,7 @@ DSP_CloseDevice(_THIS)
static int
DSP_OpenDevice(_THIS, const char *devname, int iscapture)
DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
int format;
@ -270,7 +270,7 @@ DSP_PlayDevice(_THIS)
const int mixlen = this->hidden->mixlen;
if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
perror("Audio write");
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
@ -293,6 +293,8 @@ DSP_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = DSP_GetDeviceBuf;
impl->CloseDevice = DSP_CloseDevice;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
}

View file

@ -27,7 +27,7 @@
#include "SDL_dummyaudio.h"
static int
DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
return 0; /* always succeeds. */
}

View file

@ -151,12 +151,13 @@ Emscripten_CloseDevice(_THIS)
}
static int
Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_bool valid_format = SDL_FALSE;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int i;
float f;
int result;
while ((!valid_format) && (test_format)) {
switch (test_format) {
@ -185,7 +186,7 @@ Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
/* based on parts of library_sdl.js */
/* create context (TODO: this puts stuff in the global namespace...)*/
EM_ASM({
result = EM_ASM_INT_V({
if(typeof(SDL2) === 'undefined')
SDL2 = {};
@ -198,10 +199,14 @@ Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
} else if (typeof(webkitAudioContext) !== 'undefined') {
SDL2.audioContext = new webkitAudioContext();
} else {
throw 'Web Audio API is not available!';
return -1;
}
}
return 0;
});
if (result < 0) {
return SDL_SetError("Web Audio API is not available!");
}
/* limit to native freq */
int sampleRate = EM_ASM_INT_V({

View file

@ -129,7 +129,7 @@ ESD_WaitDevice(_THIS)
/* Check every 10 loops */
if (this->hidden->parent && (((++cnt) % 10) == 0)) {
if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
@ -161,7 +161,7 @@ ESD_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
}
@ -215,7 +215,7 @@ get_progname(void)
static int
ESD_OpenDevice(_THIS, const char *devname, int iscapture)
ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
esd_format_t format = (ESD_STREAM | ESD_PLAY);
SDL_AudioFormat test_format = 0;

View file

@ -143,7 +143,7 @@ SDL_FS_PlayDevice(_THIS)
this->hidden->mixsamples);
/* If we couldn't write, assume fatal error for now */
if (ret) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
@ -186,7 +186,7 @@ SDL_FS_CloseDevice(_THIS)
static int
SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int bytes;
SDL_AudioFormat test_format = 0, format = 0;

View file

@ -111,7 +111,7 @@ UnmaskSignals(sigset_t * omask)
static int
HAIKUAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int valid_datatype = 0;
media_raw_audio_format format;

View file

@ -20,6 +20,9 @@
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_NACL
#include "SDL_naclaudio.h"
#include "SDL_audio.h"
@ -40,7 +43,7 @@
#define SAMPLE_FRAME_COUNT 4096
/* Audio driver functions */
static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture);
static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
static void NACLAUD_CloseDevice(_THIS);
static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
@ -82,7 +85,7 @@ static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
}
static int
NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) {
NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
PP_Instance instance = PSGetInstanceId();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
@ -127,9 +130,7 @@ NACLAUD_Init(SDL_AudioDriverImpl * impl)
/* Set the function pointers */
impl->OpenDevice = NACLAUD_OpenDevice;
impl->CloseDevice = NACLAUD_CloseDevice;
impl->HasCaptureSupport = 0;
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultInputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
/*
* impl->WaitDevice = NACLAUD_WaitDevice;
@ -145,3 +146,7 @@ AudioBootStrap NACLAUD_bootstrap = {
NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
NACLAUD_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_NACL */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -276,7 +276,7 @@ find_device(_THIS, int nch)
}
static int
NAS_OpenDevice(_THIS, const char *devname, int iscapture)
NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
AuElement elms[3];
int buffer_size;

View file

@ -176,7 +176,7 @@ PAUDIO_WaitDevice(_THIS)
* the user know what happened.
*/
fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message);
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
/* Don't try to close - may hang */
this->hidden->audio_fd = -1;
#ifdef DEBUG_AUDIO
@ -212,7 +212,7 @@ PAUDIO_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
@ -241,7 +241,7 @@ PAUDIO_CloseDevice(_THIS)
}
static int
PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
char audiodev[1024];

View file

@ -18,6 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_PSP
#include <stdio.h>
#include <string.h>
@ -40,7 +43,7 @@
#define PSPAUD_DRIVER_NAME "psp"
static int
PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int format, mixlen, i;
this->hidden = (struct SDL_PrivateAudioData *)
@ -191,5 +194,6 @@ AudioBootStrap PSPAUD_bootstrap = {
/* SDL_AUDI */
#endif /* SDL_AUDIO_DRIVER_PSP */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -24,7 +24,7 @@
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the video functions */
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
#define NUM_BUFFERS 2

View file

@ -26,6 +26,7 @@
Stéphan Kochen: stephan .a.t. kochen.nl
*/
#include "../../SDL_internal.h"
#include "SDL_assert.h"
#if SDL_AUDIO_DRIVER_PULSEAUDIO
@ -38,7 +39,6 @@
#include <sys/types.h>
#include <errno.h>
#include <pulse/pulseaudio.h>
#include <pulse/simple.h>
#include "SDL_timer.h"
#include "SDL_audio.h"
@ -66,16 +66,14 @@ static SDL_INLINE int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
static const char *(*PULSEAUDIO_pa_get_library_version) (void);
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 int (*PULSEAUDIO_pa_mainloop_run) (pa_mainloop *, int *);
static void (*PULSEAUDIO_pa_mainloop_quit) (pa_mainloop *, int);
static void (*PULSEAUDIO_pa_mainloop_free) (pa_mainloop *);
static pa_operation_state_t (*PULSEAUDIO_pa_operation_get_state) (
@ -87,7 +85,13 @@ 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_operation * (*PULSEAUDIO_pa_context_get_sink_info_list) (pa_context *, pa_sink_info_cb_t, void *);
static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list) (pa_context *, pa_source_info_cb_t, void *);
static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_by_index) (pa_context *, uint32_t, pa_sink_info_cb_t, void *);
static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_by_index) (pa_context *, uint32_t, pa_source_info_cb_t, void *);
static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *);
static pa_operation * (*PULSEAUDIO_pa_context_subscribe) (pa_context *, pa_subscription_mask_t, pa_context_success_cb_t, void *);
static void (*PULSEAUDIO_pa_context_set_subscribe_callback) (pa_context *, pa_context_subscribe_cb_t, void *);
static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *);
static void (*PULSEAUDIO_pa_context_unref) (pa_context *);
@ -179,18 +183,24 @@ static int
load_pulseaudio_syms(void)
{
SDL_PULSEAUDIO_SYM(pa_get_library_version);
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_run);
SDL_PULSEAUDIO_SYM(pa_mainloop_quit);
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_sink_info_list);
SDL_PULSEAUDIO_SYM(pa_context_get_source_info_list);
SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_by_index);
SDL_PULSEAUDIO_SYM(pa_context_get_source_info_by_index);
SDL_PULSEAUDIO_SYM(pa_context_get_state);
SDL_PULSEAUDIO_SYM(pa_context_subscribe);
SDL_PULSEAUDIO_SYM(pa_context_set_subscribe_callback);
SDL_PULSEAUDIO_SYM(pa_context_disconnect);
SDL_PULSEAUDIO_SYM(pa_context_unref);
SDL_PULSEAUDIO_SYM(pa_stream_new);
@ -206,122 +216,6 @@ load_pulseaudio_syms(void)
return 0;
}
/* Check to see if we can connect to PulseAudio */
static SDL_bool
CheckPulseAudioAvailable()
{
pa_simple *s;
pa_sample_spec ss;
ss.format = PA_SAMPLE_S16NE;
ss.channels = 1;
ss.rate = 22050;
s = PULSEAUDIO_pa_simple_new(NULL, "SDL", PA_STREAM_PLAYBACK, NULL,
"Test", &ss, NULL, NULL, NULL);
if (s) {
PULSEAUDIO_pa_simple_free(s);
return SDL_TRUE;
} else {
return SDL_FALSE;
}
}
/* 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) {
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 SDL_INLINE int
squashVersion(const int major, const int minor, const int patch)
{
@ -344,8 +238,193 @@ getAppName(void)
return "SDL Application"; /* oh well. */
}
static void
WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
{
/* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */
if (mainloop && o) {
SDL_bool okay = SDL_TRUE;
while (okay && (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING)) {
okay = (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) >= 0);
}
PULSEAUDIO_pa_operation_unref(o);
}
}
static void
DisconnectFromPulseServer(pa_mainloop *mainloop, pa_context *context)
{
if (context) {
PULSEAUDIO_pa_context_disconnect(context);
PULSEAUDIO_pa_context_unref(context);
}
if (mainloop != NULL) {
PULSEAUDIO_pa_mainloop_free(mainloop);
}
}
static int
PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
ConnectToPulseServer_Internal(pa_mainloop **_mainloop, pa_context **_context)
{
pa_mainloop *mainloop = NULL;
pa_context *context = NULL;
pa_mainloop_api *mainloop_api = NULL;
int state = 0;
*_mainloop = NULL;
*_context = NULL;
/* Set up a new main loop */
if (!(mainloop = PULSEAUDIO_pa_mainloop_new())) {
return SDL_SetError("pa_mainloop_new() failed");
}
*_mainloop = mainloop;
mainloop_api = PULSEAUDIO_pa_mainloop_get_api(mainloop);
SDL_assert(mainloop_api); /* this never fails, right? */
context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName());
if (!context) {
return SDL_SetError("pa_context_new() failed");
}
*_context = context;
/* Connect to the PulseAudio server */
if (PULSEAUDIO_pa_context_connect(context, NULL, 0, NULL) < 0) {
return SDL_SetError("Could not setup connection to PulseAudio");
}
do {
if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) {
return SDL_SetError("pa_mainloop_iterate() failed");
}
state = PULSEAUDIO_pa_context_get_state(context);
if (!PA_CONTEXT_IS_GOOD(state)) {
return SDL_SetError("Could not connect to PulseAudio");
}
} while (state != PA_CONTEXT_READY);
return 0; /* connected and ready! */
}
static int
ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context)
{
const int retval = ConnectToPulseServer_Internal(_mainloop, _context);
if (retval < 0) {
DisconnectFromPulseServer(*_mainloop, *_context);
}
return retval;
}
/* 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 (this->enabled) {
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) {
SDL_OpenedAudioDeviceDisconnected(this);
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 (this->enabled) {
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
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)
{
if (this->enabled) {
struct SDL_PrivateAudioData *h = this->hidden;
pa_operation *o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
if (o) {
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) {
SDL_FreeAudioMem(this->hidden->mixbuf);
SDL_free(this->hidden->device_name);
if (this->hidden->stream) {
PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
PULSEAUDIO_pa_stream_unref(this->hidden->stream);
}
DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
SDL_free(this->hidden);
this->hidden = NULL;
}
}
static void
DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
{
if (i) {
char **devname = (char **) data;
*devname = SDL_strdup(i->name);
}
}
static SDL_bool
FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
{
const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
if (handle == NULL) { /* NULL == default device. */
return SDL_TRUE;
}
WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name));
return (h->device_name != NULL);
}
static int
PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
struct SDL_PrivateAudioData *h = NULL;
Uint16 test_format = 0;
@ -442,42 +521,21 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
paattr.minreq = h->mixlen;
#endif
if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not connect to PulseAudio server");
}
if (!FindDeviceName(h, handle)) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Requested PulseAudio sink missing?");
}
/* 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);
return SDL_SetError("pa_mainloop_new() failed");
}
h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName());
if (!h->context) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("pa_context_new() failed");
}
/* Connect to the PulseAudio server */
if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not setup connection to PulseAudio");
}
do {
if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("pa_mainloop_iterate() failed");
}
state = PULSEAUDIO_pa_context_get_state(h->context);
if (!PA_CONTEXT_IS_GOOD(state)) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not connect to PulseAudio");
}
} while (state != PA_CONTEXT_READY);
h->stream = PULSEAUDIO_pa_stream_new(
h->context,
"Simple DirectMedia Layer", /* stream description */
@ -490,7 +548,13 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
return SDL_SetError("Could not set up PulseAudio stream");
}
if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags,
/* now that we have multi-device support, don't move a stream from
a device that was unplugged to something else, unless we're default. */
if (h->device_name != NULL) {
flags |= PA_STREAM_DONT_MOVE;
}
if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags,
NULL, NULL) < 0) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not connect PulseAudio stream");
@ -504,7 +568,7 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
state = PULSEAUDIO_pa_stream_get_state(h->stream);
if (!PA_STREAM_IS_GOOD(state)) {
PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not create to PulseAudio stream");
return SDL_SetError("Could not connect PulseAudio stream");
}
} while (state != PA_STREAM_READY);
@ -512,10 +576,92 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
return 0;
}
static pa_mainloop *hotplug_mainloop = NULL;
static pa_context *hotplug_context = NULL;
static SDL_Thread *hotplug_thread = NULL;
/* device handles are device index + 1, cast to void*, so we never pass a NULL. */
/* This is called when PulseAudio adds an output ("sink") device. */
static void
SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
{
if (i) {
SDL_AddAudioDevice(SDL_FALSE, i->description, (void *) ((size_t) i->index+1));
}
}
/* This is called when PulseAudio adds a capture ("source") device. */
static void
SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
{
if (i) {
/* Skip "monitor" sources. These are just output from other sinks. */
if (i->monitor_of_sink == PA_INVALID_INDEX) {
SDL_AddAudioDevice(SDL_TRUE, i->description, (void *) ((size_t) i->index+1));
}
}
}
/* This is called when PulseAudio has a device connected/removed/changed. */
static void
HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data)
{
const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW);
const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE);
if (added || removed) { /* we only care about add/remove events. */
const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK);
const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
/* adds need sink details from the PulseAudio server. Another callback... */
if (added && sink) {
PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, NULL);
} else if (added && source) {
PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, NULL);
} else if (removed && (sink || source)) {
/* removes we can handle just with the device index. */
SDL_RemoveAudioDevice(source != 0, (void *) ((size_t) idx+1));
}
}
}
/* this runs as a thread while the Pulse target is initialized to catch hotplug events. */
static int SDLCALL
HotplugThread(void *data)
{
pa_operation *o;
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
PULSEAUDIO_pa_context_set_subscribe_callback(hotplug_context, HotplugCallback, NULL);
o = PULSEAUDIO_pa_context_subscribe(hotplug_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, NULL, NULL);
PULSEAUDIO_pa_operation_unref(o); /* don't wait for it, just do our thing. */
PULSEAUDIO_pa_mainloop_run(hotplug_mainloop, NULL);
return 0;
}
static void
PULSEAUDIO_DetectDevices()
{
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, NULL));
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL));
/* ok, we have a sane list, let's set up hotplug notifications now... */
hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL);
}
static void
PULSEAUDIO_Deinitialize(void)
{
if (hotplug_thread) {
PULSEAUDIO_pa_mainloop_quit(hotplug_mainloop, 0);
SDL_WaitThread(hotplug_thread, NULL);
hotplug_thread = NULL;
}
DisconnectFromPulseServer(hotplug_mainloop, hotplug_context);
hotplug_mainloop = NULL;
hotplug_context = NULL;
UnloadPulseAudioLibrary();
}
@ -526,12 +672,13 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
return 0;
}
if (!CheckPulseAudioAvailable()) {
if (ConnectToPulseServer(&hotplug_mainloop, &hotplug_context) < 0) {
UnloadPulseAudioLibrary();
return 0;
}
/* Set the function pointers */
impl->DetectDevices = PULSEAUDIO_DetectDevices;
impl->OpenDevice = PULSEAUDIO_OpenDevice;
impl->PlayDevice = PULSEAUDIO_PlayDevice;
impl->WaitDevice = PULSEAUDIO_WaitDevice;
@ -539,12 +686,10 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
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", "PulseAudio", PULSEAUDIO_Init, 0
};

View file

@ -32,9 +32,10 @@
struct SDL_PrivateAudioData
{
char *device_name;
/* pulseaudio structures */
pa_mainloop *mainloop;
pa_mainloop_api *mainloop_api;
pa_context *context;
pa_stream *stream;

View file

@ -19,6 +19,15 @@
3. This notice may not be removed or altered from any source distribution.
*/
/*
* !!! FIXME: streamline this a little by removing all the
* !!! FIXME: if (capture) {} else {} sections that are identical
* !!! FIXME: except for one flag.
*/
/* !!! FIXME: can this target support hotplugging? */
/* !!! FIXME: ...does SDL2 even support QNX? */
#include "../../SDL_internal.h"
#if SDL_AUDIO_DRIVER_QSA
@ -300,7 +309,7 @@ QSA_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if (towrite != 0) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
}
@ -337,8 +346,9 @@ QSA_CloseDevice(_THIS)
}
static int
QSA_OpenDevice(_THIS, const char *devname, int iscapture)
QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const QSA_Device *device = (const QSA_Device *) handle;
int status = 0;
int format = 0;
SDL_AudioFormat test_format = 0;
@ -363,80 +373,19 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture)
/* 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);
return SDL_SetError("No such playback device");
}
} 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);
return SDL_SetError("No such capture device");
}
} 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 {
if (device != NULL) {
/* 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);
}
this->hidden->deviceno = device->deviceno;
this->hidden->cardno = device->cardno;
status = snd_pcm_open(&this->hidden->audio_handle,
device->cardno, device->deviceno,
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
} else {
/* Open system default audio device */
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
&this->hidden->cardno,
&this->hidden->deviceno,
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
}
/* Check if requested device is opened */
@ -638,7 +587,7 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture)
}
static void
QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
QSA_DetectDevices(void)
{
uint32_t it;
uint32_t cards;
@ -656,8 +605,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
return;
}
/* !!! FIXME: code duplication */
/* Find requested devices by type */
if (!iscapture) {
{ /* output devices */
/* Playback devices enumeration requested */
for (it = 0; it < cards; it++) {
devices = 0;
@ -688,7 +638,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
devices;
status = snd_pcm_close(handle);
if (status == EOK) {
addfn(qsa_playback_device[qsa_playback_devices].name);
SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]);
qsa_playback_devices++;
}
} else {
@ -713,7 +663,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
break;
}
}
} else {
}
{ /* capture devices */
/* Capture devices enumeration requested */
for (it = 0; it < cards; it++) {
devices = 0;
@ -744,7 +696,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
devices;
status = snd_pcm_close(handle);
if (status == EOK) {
addfn(qsa_capture_device[qsa_capture_devices].name);
SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]);
qsa_capture_devices++;
}
} else {

View file

@ -158,7 +158,7 @@ SNDIO_PlayDevice(_THIS)
/* If we couldn't write, assume fatal error for now */
if ( written == 0 ) {
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
@ -193,7 +193,7 @@ SNDIO_CloseDevice(_THIS)
}
static int
SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
struct sio_par par;

View file

@ -56,9 +56,9 @@ static Uint8 snd2au(int sample);
/* Audio driver bootstrap functions */
static void
SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
SUNAUDIO_DetectDevices(void)
{
SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn);
SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL);
}
#ifdef DEBUG_AUDIO
@ -158,7 +158,7 @@ SUNAUDIO_PlayDevice(_THIS)
if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
this->hidden->fragsize) < 0) {
/* Assume fatal error, for now */
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
this->hidden->written += this->hidden->fragsize;
} else {
@ -168,7 +168,7 @@ SUNAUDIO_PlayDevice(_THIS)
if (write(this->hidden->audio_fd, this->hidden->mixbuf,
this->spec.size) < 0) {
/* Assume fatal error, for now */
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
this->hidden->written += this->hidden->fragsize;
}
@ -198,7 +198,7 @@ SUNAUDIO_CloseDevice(_THIS)
}
static int
SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
SDL_AudioFormat format = 0;
@ -414,6 +414,8 @@ SUNAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
impl->CloseDevice = SUNAUDIO_CloseDevice;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
}

View file

@ -36,8 +36,9 @@
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
#define DETECT_DEV_IMPL(typ, capstyp) \
static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
static void DetectWave##typ##Devs(void) { \
const UINT iscapture = iscap ? 1 : 0; \
const UINT devcount = wave##typ##GetNumDevs(); \
capstyp caps; \
UINT i; \
@ -45,24 +46,21 @@ static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
char *name = WIN_StringToUTF8(caps.szPname); \
if (name != NULL) { \
addfn(name); \
SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
SDL_free(name); \
} \
} \
} \
}
DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
DETECT_DEV_IMPL(In, WAVEINCAPS)
DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
static void
WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
WINMM_DetectDevices(void)
{
if (iscapture) {
DetectWaveInDevs(addfn);
} else {
DetectWaveOutDevs(addfn);
}
DetectWaveInDevs();
DetectWaveOutDevs();
}
static void CALLBACK
@ -220,48 +218,19 @@ PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
}
static int
WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
MMRESULT result;
WAVEFORMATEX waveformat;
UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */
char *utf8 = NULL;
UINT i;
if (devname != NULL) { /* specific device requested? */
if (iscapture) {
const UINT devcount = waveInGetNumDevs();
WAVEINCAPS caps;
for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
result = waveInGetDevCaps(i, &caps, sizeof (caps));
if (result != MMSYSERR_NOERROR)
continue;
else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
continue;
else if (SDL_strcmp(devname, utf8) == 0)
devId = i;
SDL_free(utf8);
}
} else {
const UINT devcount = waveOutGetNumDevs();
WAVEOUTCAPS caps;
for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
result = waveOutGetDevCaps(i, &caps, sizeof (caps));
if (result != MMSYSERR_NOERROR)
continue;
else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
continue;
else if (SDL_strcmp(devname, utf8) == 0)
devId = i;
SDL_free(utf8);
}
}
if (devId == WAVE_MAPPER) {
return SDL_SetError("Requested device not found");
}
if (handle != NULL) { /* specific device requested? */
/* -1 because we increment the original value to avoid NULL. */
const size_t val = ((size_t) handle) - 1;
devId = (UINT) val;
}
/* Initialize all variables that we clean on shutdown */
@ -279,10 +248,6 @@ WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
if (this->spec.channels > 2)
this->spec.channels = 2; /* !!! FIXME: is this right? */
/* 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;
while ((!valid_datatype) && (test_format)) {
switch (test_format) {
case AUDIO_U8:

View file

@ -126,16 +126,13 @@ struct SDL_PrivateAudioData
static void
XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
XAUDIO2_DetectDevices(void)
{
IXAudio2 *ixa2 = NULL;
UINT32 devcount = 0;
UINT32 i = 0;
if (iscapture) {
SDL_SetError("XAudio2: capture devices unsupported.");
return;
} else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
SDL_SetError("XAudio2: XAudio2Create() failed at detection.");
return;
} else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
@ -149,8 +146,8 @@ XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
char *str = WIN_StringToUTF8(details.DisplayName);
if (str != NULL) {
addfn(str);
SDL_free(str); /* addfn() made a copy of the string. */
SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i+1));
SDL_free(str); /* SDL_AddAudioDevice made a copy of the string. */
}
}
}
@ -169,8 +166,8 @@ VoiceCBOnBufferEnd(THIS_ void *data)
static void STDMETHODCALLTYPE
VoiceCBOnVoiceError(THIS_ void *data, HRESULT Error)
{
/* !!! FIXME: attempt to recover, or mark device disconnected. */
SDL_assert(0 && "write me!");
SDL_AudioDevice *this = (SDL_AudioDevice *) data;
SDL_OpenedAudioDeviceDisconnected(this);
}
/* no-op callbacks... */
@ -221,7 +218,7 @@ XAUDIO2_PlayDevice(_THIS)
if (result != S_OK) { /* uhoh, panic! */
IXAudio2SourceVoice_FlushSourceBuffers(source);
this->enabled = 0;
SDL_OpenedAudioDeviceDisconnected(this);
}
}
@ -289,7 +286,7 @@ XAUDIO2_CloseDevice(_THIS)
}
static int
XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
HRESULT result = S_OK;
WAVEFORMATEX waveformat;
@ -315,9 +312,17 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };
if (iscapture) {
return SDL_SetError("XAudio2: capture devices unsupported.");
} else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
#if defined(SDL_XAUDIO2_WIN8)
/* !!! FIXME: hook up hotplugging. */
#else
if (handle != NULL) { /* specific device requested? */
/* -1 because we increment the original value to avoid NULL. */
const size_t val = ((size_t) handle) - 1;
devId = (UINT32) val;
}
#endif
if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
return SDL_SetError("XAudio2: XAudio2Create() failed at open.");
}
@ -332,37 +337,6 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
ixa2->SetDebugConfiguration(&debugConfig);
*/
#if ! defined(__WINRT__)
if (devname != NULL) {
UINT32 devcount = 0;
UINT32 i = 0;
if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
IXAudio2_Release(ixa2);
return SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed.");
}
for (i = 0; i < devcount; i++) {
XAUDIO2_DEVICE_DETAILS details;
if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
char *str = WIN_StringToUTF8(details.DisplayName);
if (str != NULL) {
const int match = (SDL_strcmp(str, devname) == 0);
SDL_free(str);
if (match) {
devId = i;
break;
}
}
}
}
if (i == devcount) {
IXAudio2_Release(ixa2);
return SDL_SetError("XAudio2: Requested device not found.");
}
}
#endif
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
@ -529,6 +503,16 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
impl->CloseDevice = XAUDIO2_CloseDevice;
impl->Deinitialize = XAUDIO2_Deinitialize;
/* !!! FIXME: We can apparently use a C++ interface on Windows 8
* !!! FIXME: (Windows::Devices::Enumeration::DeviceInformation) for device
* !!! FIXME: detection, but it's not implemented here yet.
* !!! FIXME: see http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
* !!! FIXME: for now, force the default device.
*/
#if defined(SDL_XAUDIO2_WIN8) || defined(__WINRT__)
impl->OnlyHasDefaultOutputDevice = 1;
#endif
return 1; /* this audio target is available. */
#endif
}

View file

@ -32,6 +32,7 @@
#include "../../events/SDL_events_c.h"
#include "../../video/android/SDL_androidkeyboard.h"
#include "../../video/android/SDL_androidmouse.h"
#include "../../video/android/SDL_androidtouch.h"
#include "../../video/android/SDL_androidvideo.h"
#include "../../video/android/SDL_androidwindow.h"
@ -293,6 +294,14 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch(
Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
}
/* Mouse */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
JNIEnv* env, jclass jcls,
jint button, jint action, jfloat x, jfloat y)
{
Android_OnMouse(button, action, x, y);
}
/* Accelerometer */
JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jclass jcls,
@ -548,12 +557,12 @@ int Android_JNI_SetupThread(void)
* Audio support
*/
static jboolean audioBuffer16Bit = JNI_FALSE;
static jboolean audioBufferStereo = JNI_FALSE;
static jobject audioBuffer = NULL;
static void* audioBufferPinned = NULL;
int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
{
jboolean audioBufferStereo;
int audioBufferFrames;
JNIEnv *env = Android_JNI_GetEnv();
@ -1601,6 +1610,11 @@ const char * SDL_AndroidGetExternalStoragePath()
return s_AndroidExternalFilesPath;
}
jclass Android_JNI_GetActivityClass(void)
{
return mActivityClass;
}
#endif /* __ANDROID__ */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -78,6 +78,7 @@ int Android_JNI_GetTouchDeviceIds(int **ids);
#include <jni.h>
JNIEnv *Android_JNI_GetEnv(void);
int Android_JNI_SetupThread(void);
jclass Android_JNI_GetActivityClass(void);
/* Generic messages */
int Android_JNI_SendMessage(int command, int param);

View file

@ -462,6 +462,9 @@ SDL_IBus_Init(void)
ibus_addr_file = SDL_strdup(addr_file);
addr = IBus_ReadAddressFromFile(addr_file);
if (!addr) {
return SDL_FALSE;
}
if (inotify_fd < 0) {
inotify_fd = inotify_init();

View file

@ -350,17 +350,19 @@ guess_device_class(struct udev_device *dev)
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
} else if (test_bit(BTN_TOUCH, bitmask_key)) {
; /* ID_INPUT_TOUCHSCREEN */
} else if (test_bit(BTN_TRIGGER, bitmask_key) ||
test_bit(BTN_A, bitmask_key) ||
test_bit(BTN_1, bitmask_key) ||
test_bit(ABS_RX, bitmask_abs) ||
test_bit(ABS_RY, bitmask_abs) ||
test_bit(ABS_RZ, bitmask_abs) ||
test_bit(ABS_THROTTLE, bitmask_abs) ||
test_bit(ABS_RUDDER, bitmask_abs) ||
test_bit(ABS_WHEEL, bitmask_abs) ||
test_bit(ABS_GAS, bitmask_abs) ||
test_bit(ABS_BRAKE, bitmask_abs)) {
}
if (test_bit(BTN_TRIGGER, bitmask_key) ||
test_bit(BTN_A, bitmask_key) ||
test_bit(BTN_1, bitmask_key) ||
test_bit(ABS_RX, bitmask_abs) ||
test_bit(ABS_RY, bitmask_abs) ||
test_bit(ABS_RZ, bitmask_abs) ||
test_bit(ABS_THROTTLE, bitmask_abs) ||
test_bit(ABS_RUDDER, bitmask_abs) ||
test_bit(ABS_WHEEL, bitmask_abs) ||
test_bit(ABS_GAS, bitmask_abs) ||
test_bit(ABS_BRAKE, bitmask_abs)) {
devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */
}
}

View file

@ -49,7 +49,10 @@
#define SDL_DYNAMIC_API 0
#elif defined(__clang_analyzer__)
#define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */
#else /* everyone else. */
#endif
/* everyone else. This is where we turn on the API if nothing forced it off. */
#ifndef SDL_DYNAMIC_API
#define SDL_DYNAMIC_API 1
#endif

View file

@ -591,3 +591,4 @@
#define SDL_QueueAudio SDL_QueueAudio_REAL
#define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL
#define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL
#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL

View file

@ -623,3 +623,4 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return)
SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return)
SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),)
SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return)

View file

@ -75,12 +75,13 @@ static struct
SDL_mutex *lock;
volatile SDL_bool active;
volatile int count;
volatile int max_events_seen;
SDL_EventEntry *head;
SDL_EventEntry *tail;
SDL_EventEntry *free;
SDL_SysWMEntry *wmmsg_used;
SDL_SysWMEntry *wmmsg_free;
} SDL_EventQ = { NULL, SDL_TRUE };
} SDL_EventQ = { NULL, SDL_TRUE, 0, 0, NULL, NULL, NULL, NULL, NULL };
/* Public functions */
@ -88,6 +89,7 @@ static struct
void
SDL_StopEventLoop(void)
{
const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
int i;
SDL_EventEntry *entry;
SDL_SysWMEntry *wmmsg;
@ -98,6 +100,11 @@ SDL_StopEventLoop(void)
SDL_EventQ.active = SDL_FALSE;
if (report && SDL_atoi(report)) {
SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
SDL_EventQ.max_events_seen);
}
/* Clean out EventQ */
for (entry = SDL_EventQ.head; entry; ) {
SDL_EventEntry *next = entry->next;
@ -119,7 +126,9 @@ SDL_StopEventLoop(void)
SDL_free(wmmsg);
wmmsg = next;
}
SDL_EventQ.count = 0;
SDL_EventQ.max_events_seen = 0;
SDL_EventQ.head = NULL;
SDL_EventQ.tail = NULL;
SDL_EventQ.free = NULL;
@ -218,6 +227,10 @@ SDL_AddEvent(SDL_Event * event)
}
++SDL_EventQ.count;
if (SDL_EventQ.count > SDL_EventQ.max_events_seen) {
SDL_EventQ.max_events_seen = SDL_EventQ.count;
}
return 1;
}

View file

@ -24,6 +24,7 @@
/* General mouse handling code for SDL */
#include "SDL_events.h"
#include "SDL_endian.h"
#include "SDL_events_c.h"
#include "SDL_gesture_c.h"
@ -114,14 +115,34 @@ static unsigned long SDL_HashDollar(SDL_FloatPoint* points)
static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops *dst)
{
if (dst == NULL) return 0;
if (dst == NULL) {
return 0;
}
/* No Longer storing the Hash, rehash on load */
/* if (SDL_RWops.write(dst, &(templ->hash), sizeof(templ->hash), 1) != 1) return 0; */
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
if (SDL_RWwrite(dst, templ->path,
sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
return 0;
}
#else
{
SDL_DollarTemplate copy = *templ;
SDL_FloatPoint *p = copy.path;
int i;
for (i = 0; i < DOLLARNPOINTS; i++, p++) {
p->x = SDL_SwapFloatLE(p->x);
p->y = SDL_SwapFloatLE(p->y);
}
if (SDL_RWwrite(dst, copy.path,
sizeof(copy.path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
return 0;
}
}
#endif
return 1;
}
@ -184,7 +205,7 @@ static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
int index = -1;
int i = 0;
if (inTouch == NULL) {
if (SDL_numGestureTouches == 0) return -1;
if (SDL_numGestureTouches == 0) return SDL_SetError("no gesture touch devices registered");
for (i = 0; i < SDL_numGestureTouches; i++) {
inTouch = &SDL_gestureTouch[i];
index = SDL_AddDollarGesture_one(inTouch, path);
@ -203,17 +224,33 @@ int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
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)
for (i = 0; i < SDL_numGestureTouches; i++) {
if (SDL_gestureTouch[i].id == touchId) {
touch = &SDL_gestureTouch[i];
if (touch == NULL) return -1;
}
}
if (touch == NULL) {
return SDL_SetError("given touch id not found");
}
}
while (1) {
SDL_DollarTemplate templ;
if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) <
DOLLARNPOINTS) break;
if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) {
if (loaded == 0) {
return SDL_SetError("could not read any dollar gesture from rwops");
}
break;
}
#if SDL_BYTEORDER != SDL_LIL_ENDIAN
for (i = 0; i < DOLLARNPOINTS; i++) {
SDL_FloatPoint *p = &templ.path[i];
p->x = SDL_SwapFloatLE(p->x);
p->y = SDL_SwapFloatLE(p->y);
}
#endif
if (touchId >= 0) {
/* printf("Adding loaded gesture to 1 touch\n"); */

View file

@ -293,9 +293,14 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
event.motion.yrel = yrel;
posted = (SDL_PushEvent(&event) > 0);
}
/* Use unclamped values if we're getting events outside the window */
mouse->last_x = x;
mouse->last_y = y;
if (relative) {
mouse->last_x = mouse->x;
mouse->last_y = mouse->y;
} else {
/* Use unclamped values if we're getting events outside the window */
mouse->last_x = x;
mouse->last_y = y;
}
return posted;
}
@ -303,10 +308,11 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
{
if (button >= mouse->num_clickstates) {
int i, count = button + 1;
mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
if (!mouse->clickstate) {
SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
if (!clickstate) {
return NULL;
}
mouse->clickstate = clickstate;
for (i = mouse->num_clickstates; i < count; ++i) {
SDL_zero(mouse->clickstate[i]);

View file

@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
#include "SDL_hints.h"
/* General quit handling code for SDL */
@ -30,6 +31,8 @@
#include "SDL_events_c.h"
static SDL_bool disable_signals = SDL_FALSE;
#ifdef HAVE_SIGNAL_H
static void
SDL_HandleSIG(int sig)
@ -43,8 +46,8 @@ SDL_HandleSIG(int sig)
#endif /* HAVE_SIGNAL_H */
/* Public functions */
int
SDL_QuitInit(void)
static int
SDL_QuitInit_Internal(void)
{
#ifdef HAVE_SIGACTION
struct sigaction action;
@ -80,11 +83,22 @@ SDL_QuitInit(void)
#endif /* HAVE_SIGNAL_H */
/* That's it! */
return (0);
return 0;
}
void
SDL_QuitQuit(void)
int
SDL_QuitInit(void)
{
const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS);
disable_signals = hint && (SDL_atoi(hint) == 1);
if (!disable_signals) {
return SDL_QuitInit_Internal();
}
return 0;
}
static void
SDL_QuitQuit_Internal(void)
{
#ifdef HAVE_SIGACTION
struct sigaction action;
@ -110,6 +124,14 @@ SDL_QuitQuit(void)
#endif /* HAVE_SIGNAL_H */
}
void
SDL_QuitQuit(void)
{
if (!disable_signals) {
SDL_QuitQuit_Internal();
}
}
/* This function returns 1 if it's okay to close the application window */
int
SDL_SendQuit(void)

View file

@ -38,4 +38,5 @@ SDL_GetPrefPath(const char *org, const char *app)
return NULL;
}
#endif /* __NACL__ */
#endif /* SDL_FILESYSTEM_NACL */

View file

@ -288,8 +288,7 @@ MaybeAddDevice(const char *path)
}
item->fname = SDL_strdup(path);
if ( (item->fname == NULL) ) {
SDL_free(item->fname);
if (item->fname == NULL) {
SDL_free(item);
return -1;
}

View file

@ -63,6 +63,8 @@ static const char *s_ControllerMappings [] =
"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
@ -73,12 +75,13 @@ static const char *s_ControllerMappings [] =
"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
#endif
#if defined(__ANDROID__)
"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
#endif
#if defined(SDL_JOYSTICK_EMSCRIPTEN)
"emscripten,Standard Gamepad,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,back:b8,start:b9,leftstick:b10,rightstick:b11,dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,guide:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
"emscripten,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
#endif
NULL
};

View file

@ -206,10 +206,6 @@ SDL_PrivateJoystickValid(SDL_Joystick * joystick)
valid = 1;
}
if (joystick && joystick->closed) {
valid = 0;
}
return valid;
}
@ -412,6 +408,7 @@ SDL_JoystickClose(SDL_Joystick * joystick)
}
SDL_SYS_JoystickClose(joystick);
joystick->hwdata = NULL;
joysticklist = SDL_joysticks;
joysticklistprev = NULL;
@ -668,7 +665,7 @@ SDL_JoystickUpdate(void)
SDL_SYS_JoystickUpdate(joystick);
if (joystick->closed && joystick->uncentered) {
if (joystick->force_recentering) {
int i;
/* Tell the app that everything is centered/unpressed... */
@ -681,7 +678,7 @@ SDL_JoystickUpdate(void)
for (i = 0; i < joystick->nhats; i++)
SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
joystick->uncentered = SDL_FALSE;
joystick->force_recentering = SDL_FALSE;
}
SDL_updating_joystick = NULL;

View file

@ -53,8 +53,7 @@ struct _SDL_Joystick
int ref_count; /* Reference count for multiple opens */
SDL_bool closed; /* SDL_TRUE if this device is no longer valid */
SDL_bool uncentered; /* SDL_TRUE if this device needs to have its state reset to 0 */
SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
};
@ -78,14 +77,14 @@ extern const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index);
extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index);
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index);
/* Function to query if the joystick is currently attached
* It returns 1 if attached, 0 otherwise.
* It returns SDL_TRUE if attached, SDL_FALSE otherwise.
*/
extern SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick);

View file

@ -467,7 +467,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -498,7 +498,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
/* Function to determine is this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return !joystick->closed && (joystick->hwdata != NULL);
return joystick->hwdata != NULL;
}
void
@ -529,11 +529,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
if (joystick->hwdata) {
((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
joystick->hwdata = NULL;
}
joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -19,7 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#include "../../SDL_internal.h"
#ifdef SDL_JOYSTICK_ANDROID
#include "../SDL_sysjoystick.h"

View file

@ -558,8 +558,6 @@ SDL_SYS_JoystickClose(SDL_Joystick * joy)
close(joy->hwdata->fd);
SDL_free(joy->hwdata->path);
SDL_free(joy->hwdata);
return;
}
void

View file

@ -138,7 +138,7 @@ static void
JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
{
recDevice *device = (recDevice *) ctx;
device->removed = 1;
device->removed = SDL_TRUE;
device->deviceRef = NULL; // deviceRef was invalidated due to the remove
#if SDL_HAPTIC_IOKIT
MacHaptic_MaybeRemoveDevice(device->ffservice);
@ -412,12 +412,12 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
/* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */
if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */
const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
#if SDL_HAPTIC_IOKIT
if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) {
device->ffservice = ioservice;
#if SDL_HAPTIC_IOKIT
MacHaptic_MaybeAddDevice(ioservice);
#endif
}
#endif
}
device->send_open_event = 1;
@ -446,9 +446,9 @@ ConfigHIDManager(CFArrayRef matchingArray)
return SDL_FALSE;
}
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
/* no-op. Callback fires once per existing device. */
@ -560,10 +560,6 @@ SDL_SYS_NumJoysticks()
void
SDL_SYS_JoystickDetect()
{
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
}
if (s_bDeviceAdded || s_bDeviceRemoved) {
recDevice *device = gpDeviceList;
s_bDeviceAdded = SDL_FALSE;
@ -613,6 +609,12 @@ SDL_SYS_JoystickDetect()
}
}
}
// run this after the checks above so we don't set device->removed and delete the device before
// SDL_SYS_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device
while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
}
}
/* Function to get the device-dependent name of a joystick */
@ -644,7 +646,7 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
* The joystick to open is specified by the index field of the joystick.
* The joystick to open is specified by the device index.
* This should fill the nbuttons and naxes fields of the joystick structure.
* It returns 0, or -1 if there is an error.
*/
@ -670,21 +672,12 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
}
/* Function to query if the joystick is currently attached
* It returns 1 if attached, 0 otherwise.
* It returns SDL_TRUE if attached, SDL_FALSE otherwise.
*/
SDL_bool
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
{
recDevice *device = gpDeviceList;
while (device) {
if (joystick->instance_id == device->instance_id) {
return SDL_TRUE;
}
device = device->pNext;
}
return SDL_FALSE;
return joystick->hwdata != NULL;
}
/* Function to update the state of a joystick - called as a device poll.
@ -705,9 +698,10 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
}
if (device->removed) { /* device was unplugged; ignore it. */
joystick->closed = 1;
joystick->uncentered = 1;
joystick->hwdata = NULL;
if (joystick->hwdata) {
joystick->force_recentering = SDL_TRUE;
joystick->hwdata = NULL;
}
return;
}
@ -795,7 +789,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -58,8 +58,7 @@ struct joystick_hwdata
recElement *firstButton;
recElement *firstHat;
int removed;
int uncentered;
SDL_bool removed;
int instance_id;
SDL_JoystickGUID guid;

View file

@ -34,7 +34,7 @@
int
SDL_SYS_JoystickInit(void)
{
return (0);
return 0;
}
int SDL_SYS_NumJoysticks()
@ -61,7 +61,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -85,21 +85,18 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
void
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
{
return;
}
/* Function to close a joystick after use */
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
return;
}
/* Function to perform any system-specific joystick related cleanup */
void
SDL_SYS_JoystickQuit(void)
{
return;
}
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )

View file

@ -46,7 +46,7 @@ static SDL_joylist_item *SDL_joylist_tail = NULL;
static int numjoysticks = 0;
static int instance_counter = 0;
int
EM_BOOL
Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
{
int i;
@ -105,12 +105,14 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa
}
++numjoysticks;
SDL_Log("%d",numjoysticks);
#ifdef DEBUG_JOYSTICK
SDL_Log("Number of joysticks is %d", numjoysticks);
#endif
#if !SDL_EVENTS_DISABLED
event.type = SDL_JOYDEVICEADDED;
if (SDL_GetEventState(event.type) == SDL_ENABLE) {
event.jdevice.which = item->device_instance - 1;
event.jdevice.which = numjoysticks - 1;
if ( (SDL_EventOK == NULL) ||
(*SDL_EventOK) (SDL_EventOKParam, &event) ) {
SDL_PushEvent(&event);
@ -118,12 +120,14 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa
}
#endif /* !SDL_EVENTS_DISABLED */
#ifdef DEBUG_JOYSTICK
SDL_Log("Added joystick with index %d", item->index);
#endif
return 1;
}
int
EM_BOOL
Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
{
SDL_joylist_item *item = SDL_joylist;
@ -144,7 +148,6 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam
return 1;
}
const int retval = item->device_instance;
if (item->joystick) {
item->joystick->hwdata = NULL;
}
@ -174,7 +177,9 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam
}
#endif /* !SDL_EVENTS_DISABLED */
SDL_Log("Removed joystick with index %d", retval);
#ifdef DEBUG_JOYSTICK
SDL_Log("Removed joystick with id %d", item->device_instance);
#endif
SDL_free(item->name);
SDL_free(item->mapping);
SDL_free(item);
@ -215,6 +220,7 @@ SDL_SYS_JoystickInit(void)
Emscripten_JoyStickConnected);
if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
SDL_SYS_JoystickQuit();
return -1;
}
@ -222,12 +228,28 @@ SDL_SYS_JoystickInit(void)
0,
Emscripten_JoyStickDisconnected);
if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
SDL_SYS_JoystickQuit();
return -1;
}
return 0;
}
/* Returns item matching given SDL device index. */
static SDL_joylist_item *
JoystickByDeviceIndex(int device_index)
{
SDL_joylist_item *item = SDL_joylist;
while (0 < device_index) {
--device_index;
item = item->next;
}
return item;
}
/* Returns item matching given HTML gamepad index. */
static SDL_joylist_item *
JoystickByIndex(int index)
{
@ -256,46 +278,28 @@ void SDL_SYS_JoystickDetect()
{
}
// we need to poll to see if the gamepad state has changed
SDL_bool SDL_SYS_JoystickNeedsPolling()
{
return SDL_TRUE;
}
/* Function to get the device-dependent name of a joystick */
const char *
SDL_SYS_JoystickNameForDeviceIndex(int index)
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
{
SDL_joylist_item *item = JoystickByIndex(index);
if (item == NULL) {
SDL_SetError("Joystick with index %d not found", index);
return NULL;
}
return item->name;
return JoystickByDeviceIndex(device_index)->name;
}
/* Function to perform the mapping from device index to the instance id for this index */
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
{
SDL_joylist_item *item = JoystickByIndex(index);
if (item == NULL) {
SDL_SetError("Joystick with index %d not found", index);
return 0;
}
return item->device_instance;
return JoystickByDeviceIndex(device_index)->device_instance;
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
int
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index)
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
{
SDL_joylist_item *item = JoystickByIndex(index);
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
if (item == NULL ) {
return SDL_SetError("No such device");
@ -322,7 +326,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index)
/* Function to determine is this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return !joystick->closed && (joystick->hwdata != NULL);
return joystick->hwdata != NULL;
}
/* Function to update the state of a joystick - called as a device poll.
@ -334,10 +338,10 @@ void
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
{
EmscriptenGamepadEvent gamepadState;
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
int i, result, buttonState;
while (item != NULL) {
if (item) {
result = emscripten_get_gamepad_status(item->index, &gamepadState);
if( result == EMSCRIPTEN_RESULT_SUCCESS) {
if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
@ -367,7 +371,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
}
}
}
item = item->next;
}
}
@ -375,11 +378,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
if (joystick->hwdata) {
((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
joystick->hwdata = NULL;
}
joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */
@ -400,20 +398,24 @@ SDL_SYS_JoystickQuit(void)
numjoysticks = 0;
instance_counter = 0;
emscripten_set_gamepadconnected_callback(NULL, 0, NULL);
emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL);
}
SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index)
SDL_JoystickGUID
SDL_SYS_JoystickGetDeviceGUID(int device_index)
{
SDL_JoystickGUID guid;
/* the GUID is just the first 16 chars of the name for now */
const char *name = SDL_SYS_JoystickNameForDeviceIndex(index);
const char *name = SDL_SYS_JoystickNameForDeviceIndex(device_index);
SDL_zero(guid);
SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
return guid;
}
SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
SDL_JoystickGUID
SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
{
SDL_JoystickGUID guid;
/* the GUID is just the first 16 chars of the name for now */

View file

@ -19,7 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#include "../../SDL_internal.h"
#ifdef SDL_JOYSTICK_EMSCRIPTEN
#include "../SDL_sysjoystick.h"

View file

@ -106,7 +106,7 @@ extern "C"
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -228,7 +228,6 @@ extern "C"
SDL_free(joystick->hwdata->new_hats);
SDL_free(joystick->hwdata->new_axes);
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}
}

View file

@ -77,7 +77,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -167,7 +167,6 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
@autoreleasepool {
[motionManager stopAccelerometerUpdates];
}
joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -142,13 +142,15 @@ IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *gui
#if SDL_USE_LIBUDEV
void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
{
if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
if (devpath == NULL) {
return;
}
switch( udev_type )
{
switch (udev_type) {
case SDL_UDEV_DEVICEADDED:
if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
return;
}
MaybeAddDevice(devpath);
break;
@ -335,13 +337,12 @@ JoystickInitWithoutUdev(void)
static int
JoystickInitWithUdev(void)
{
if (SDL_UDEV_Init() < 0) {
return SDL_SetError("Could not initialize UDEV");
}
/* Set up the udev callback */
if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
SDL_UDEV_Quit();
return SDL_SetError("Could not set up joystick <-> udev callback");
}
@ -565,7 +566,7 @@ ConfigJoystick(SDL_Joystick * joystick, int fd)
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -623,7 +624,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
/* Function to determine is this joystick is attached to the system right now */
SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return !joystick->closed && (joystick->hwdata->item != NULL);
return joystick->hwdata->item != NULL;
}
static SDL_INLINE void
@ -840,9 +841,7 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
SDL_free(joystick->hwdata->balls);
SDL_free(joystick->hwdata->fname);
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}
joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -18,6 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_JOYSTICK_PSP
/* This is the PSP implementation of the SDL joystick API */
#include <pspctrl.h>
@ -161,7 +164,7 @@ const char *SDL_SYS_JoystickName(int index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -179,12 +182,12 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
{
return SDL_TRUE;
}
/* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state.
*/
void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
{
int i;
@ -230,7 +233,6 @@ void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
/* Function to close a joystick after use */
void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
{
/* Do nothing. */
}
/* Function to perform any system-specific joystick related cleanup */
@ -262,5 +264,7 @@ SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
return guid;
}
#endif /* SDL_JOYSTICK_PSP */
/* vim: ts=4 sw=4
*/

View file

@ -210,7 +210,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -383,9 +383,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
/* free system specific hardware data */
SDL_free(joystick->hwdata);
joystick->hwdata = NULL;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -446,7 +446,7 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
The joystick to open is specified by the device index.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
@ -460,7 +460,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
/* allocate memory for system specific hardware data */
joystick->instance_id = joystickdevice->nInstanceID;
joystick->closed = SDL_FALSE;
joystick->hwdata =
(struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
if (joystick->hwdata == NULL) {
@ -480,13 +479,13 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
SDL_bool
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
{
return !joystick->closed && !joystick->hwdata->removed;
return joystick->hwdata && !joystick->hwdata->removed;
}
void
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
{
if (joystick->closed || !joystick->hwdata) {
if (!joystick->hwdata || joystick->hwdata->removed) {
return;
}
@ -497,8 +496,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
}
if (joystick->hwdata->removed) {
joystick->closed = SDL_TRUE;
joystick->uncentered = SDL_TRUE;
joystick->force_recentering = SDL_TRUE;
}
}
@ -512,10 +510,7 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
SDL_DINPUT_JoystickClose(joystick);
}
/* free system specific hardware data */
SDL_free(joystick->hwdata);
joystick->closed = SDL_TRUE;
}
/* Function to perform any system-specific joystick related cleanup */

View file

@ -1,6 +1,9 @@
/*
SDL_psp_main.c, placed in the public domain by Sam Lantinga 3/13/14
*/
#include "SDL_config.h"
#ifdef __PSP__
#include "SDL_main.h"
#include <pspkernel.h>
@ -61,3 +64,7 @@ int main(int argc, char *argv[])
(void)SDL_main(argc, argv);
return 0;
}
#endif /* __PSP__ */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -109,13 +109,16 @@ OutOfMemory(void)
}
#if defined(_MSC_VER)
/* The VC++ compiler needs main defined */
#define console_main main
/* The VC++ compiler needs main/wmain defined */
# define console_ansi_main main
# if UNICODE
# define console_wmain wmain
# endif
#endif
/* This is where execution begins [console apps] */
int
console_main(int argc, char *argv[])
/* WinMain, main, and wmain eventually call into here. */
static int
main_utf8(int argc, char *argv[])
{
SDL_SetMainReady();
@ -123,6 +126,37 @@ console_main(int argc, char *argv[])
return SDL_main(argc, argv);
}
/* This is where execution begins [console apps, ansi] */
int
console_ansi_main(int argc, char *argv[])
{
/* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
return main_utf8(argc, argv);
}
#if UNICODE
/* This is where execution begins [console apps, unicode] */
int
console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
{
int retval = 0;
char **argv = SDL_stack_alloc(char*, argc);
int i;
for (i = 0; i < argc; ++i) {
argv[i] = WIN_StringToUTF8(wargv[i]);
}
retval = main_utf8(argc, argv);
/* !!! FIXME: we are leaking all the elements of argv we allocated. */
SDL_stack_free(argv);
return retval;
}
#endif
/* This is where execution begins [windowed apps] */
int WINAPI
WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
@ -136,6 +170,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
#if UNICODE
cmdline = WIN_StringToUTF8(text);
#else
/* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
cmdline = SDL_strdup(text);
#endif
if (cmdline == NULL) {
@ -151,7 +186,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
ParseCommandLine(cmdline, argv);
/* Run the main program */
console_main(argc, argv);
main_utf8(argc, argv);
SDL_stack_free(argv);

View file

@ -829,9 +829,24 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->driverdata = data;
#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
/* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
* Failure to use it seems to either result in:
*
* - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
* off (framerate doesn't get capped), but nothing appears on-screen
*
* - with the D3D11 debug runtime turned ON, vsync gets automatically
* turned back on, and the following gets output to the debug console:
*
* DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ]
*/
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
#else
if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
#endif
/* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
* order to give init functions access to the underlying window handle:

View file

@ -342,9 +342,11 @@ GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GL
if (type == GL_DEBUG_TYPE_ERROR_ARB) {
/* Record this error */
++data->errors;
data->error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages));
if (data->error_messages) {
int errors = data->errors + 1;
char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
if (error_messages) {
data->errors = errors;
data->error_messages = error_messages;
data->error_messages[data->errors-1] = SDL_strdup(message);
}
}

View file

@ -1204,10 +1204,10 @@ SDLTest_PrintEvent(SDL_Event * event)
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
break;
case SDL_DOLLARGESTURE:
SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (long long) event->dgesture.gestureId);
SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
break;
case SDL_DOLLARRECORD:
SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (long long) event->dgesture.gestureId);
SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
break;
case SDL_MULTIGESTURE:
SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers);

View file

@ -20,6 +20,8 @@
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_PSP
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
@ -217,4 +219,6 @@ SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
#endif /* SDL_THREAD_PSP */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -20,6 +20,8 @@
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_PSP
/* An implementation of mutexes using semaphores */
#include "SDL_thread.h"
@ -129,4 +131,6 @@ SDL_mutexV(SDL_mutex * mutex)
#endif /* SDL_THREADS_DISABLED */
}
#endif /* SDL_THREAD_PSP */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -18,6 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_PSP
/* Semaphore functions for the PSP. */
@ -152,5 +155,7 @@ int SDL_SemPost(SDL_sem *sem)
return 0;
}
#endif /* SDL_THREAD_PSP */
/* vim: ts=4 sw=4
*/

View file

@ -18,7 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_THREAD_PSP
/* PSP thread management routines for SDL */
@ -104,5 +106,7 @@ int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
}
#endif /* SDL_THREAD_PSP */
/* vim: ts=4 sw=4
*/

View file

@ -18,6 +18,9 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#ifdef SDL_TIMERS_PSP
#include "SDL_thread.h"
#include "SDL_timer.h"
@ -82,5 +85,7 @@ void SDL_Delay(Uint32 ms)
sceKernelDelayThreadCB(ms * 1000);
}
#endif /* SDL_TIMERS_PSP */
/* vim: ts=4 sw=4
*/

View file

@ -306,16 +306,19 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc)
biClrUsed = 1 << biBitCount;
}
if ((int) biClrUsed > palette->ncolors) {
palette->ncolors = biClrUsed;
palette->colors =
SDL_Color *colors;
int ncolors = biClrUsed;
colors =
(SDL_Color *) SDL_realloc(palette->colors,
palette->ncolors *
ncolors *
sizeof(*palette->colors));
if (!palette->colors) {
if (!colors) {
SDL_OutOfMemory();
was_error = SDL_TRUE;
goto done;
}
palette->ncolors = ncolors;
palette->colors = colors;
} else if ((int) biClrUsed < palette->ncolors) {
palette->ncolors = biClrUsed;
}

View file

@ -29,6 +29,10 @@ SDL_SetClipboardText(const char *text)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
return SDL_SetError("Video subsystem must be initialized to set clipboard text");
}
if (!text) {
text = "";
}
@ -46,6 +50,11 @@ SDL_GetClipboardText(void)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
SDL_SetError("Video subsystem must be initialized to get clipboard text");
return SDL_strdup("");
}
if (_this->GetClipboardText) {
return _this->GetClipboardText(_this);
} else {
@ -62,6 +71,11 @@ SDL_HasClipboardText(void)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (!_this) {
SDL_SetError("Video subsystem must be initialized to check clipboard text");
return SDL_FALSE;
}
if (_this->HasClipboardText) {
return _this->HasClipboardText(_this);
} else {

View file

@ -251,6 +251,10 @@ SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color)
rect = &clipped;
} else {
rect = &dst->clip_rect;
/* Don't attempt to fill if the surface's clip_rect is empty */
if (SDL_RectEmpty(rect)) {
return 0;
}
}
/* Perform software fill */

View file

@ -274,6 +274,7 @@ struct SDL_VideoDevice
int num_displays;
SDL_VideoDisplay *displays;
SDL_Window *windows;
SDL_Window *grabbed_window;
Uint8 window_magic;
Uint32 next_object_id;
char * clipboard_text;
@ -303,6 +304,7 @@ struct SDL_VideoDevice
int flags;
int profile_mask;
int share_with_current_context;
int release_behavior;
int framebuffer_srgb_capable;
int retained_backing;
int driver_loaded;

View file

@ -46,6 +46,10 @@
#include "SDL_opengles2.h"
#endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
#ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR
#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
#endif
/* On Windows, windows.h defines CreateWindow */
#ifdef CreateWindow
#undef CreateWindow
@ -1612,13 +1616,14 @@ SDL_SetWindowPosition(SDL_Window * window, int x, int y)
CHECK_WINDOW_MAGIC(window,);
if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
int displayIndex;
int displayIndex = (x & 0xFFFF);
SDL_Rect bounds;
if (displayIndex > _this->num_displays) {
displayIndex = 0;
}
SDL_zero(bounds);
displayIndex = SDL_GetIndexOfDisplay(display);
SDL_GetDisplayBounds(displayIndex, &bounds);
if (SDL_WINDOWPOS_ISCENTERED(x)) {
x = bounds.x + (bounds.w - window->w) / 2;
@ -2114,6 +2119,7 @@ void
SDL_UpdateWindowGrab(SDL_Window * window)
{
if (_this->SetWindowGrab) {
SDL_Window *grabbed_window;
SDL_bool grabbed;
if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
(window->flags & SDL_WINDOW_INPUT_FOCUS)) {
@ -2121,6 +2127,19 @@ SDL_UpdateWindowGrab(SDL_Window * window)
} else {
grabbed = SDL_FALSE;
}
grabbed_window = _this->grabbed_window;
if (grabbed) {
if (grabbed_window && (grabbed_window != window)) {
/* stealing a grab from another window! */
grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
_this->SetWindowGrab(_this, grabbed_window, SDL_FALSE);
}
_this->grabbed_window = window;
} else if (grabbed_window == window) {
_this->grabbed_window = NULL; /* ungrabbing. */
}
_this->SetWindowGrab(_this, window, grabbed);
}
}
@ -2145,8 +2164,15 @@ SDL_bool
SDL_GetWindowGrab(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
return window == _this->grabbed_window;
}
return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
SDL_Window *
SDL_GetGrabbedWindow(void)
{
SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
return _this->grabbed_window;
}
void
@ -2639,6 +2665,7 @@ SDL_GL_ResetAttributes()
#endif
_this->gl_config.flags = 0;
_this->gl_config.framebuffer_srgb_capable = 0;
_this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
_this->gl_config.share_with_current_context = 0;
}
@ -2745,6 +2772,9 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value)
case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
_this->gl_config.framebuffer_srgb_capable = value;
break;
case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
_this->gl_config.release_behavior = value;
break;
default:
retval = SDL_SetError("Unknown OpenGL attribute");
break;
@ -2845,6 +2875,13 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value)
attrib = GL_SAMPLES_ARB;
#else
attrib = GL_SAMPLES;
#endif
break;
case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
#if SDL_VIDEO_OPENGL
attrib = GL_CONTEXT_RELEASE_BEHAVIOR;
#else
attrib = GL_CONTEXT_RELEASE_BEHAVIOR_KHR;
#endif
break;
case SDL_GL_BUFFER_SIZE:

View file

@ -32,8 +32,14 @@
void android_egl_context_backup();
void android_egl_context_restore();
#if SDL_AUDIO_DRIVER_ANDROID
void AndroidAUD_ResumeDevices(void);
void AndroidAUD_PauseDevices(void);
#else
static void AndroidAUD_ResumeDevices(void) {}
static void AndroidAUD_PauseDevices(void) {}
#endif
void
android_egl_context_restore()

View file

@ -18,7 +18,7 @@
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_internal.h"
#if SDL_VIDEO_DRIVER_ANDROID

View file

@ -0,0 +1,84 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_ANDROID
#include "SDL_androidmouse.h"
#include "SDL_events.h"
#include "../../events/SDL_mouse_c.h"
#include "../../core/android/SDL_android.h"
#define ACTION_DOWN 0
#define ACTION_UP 1
#define ACTION_HOVER_MOVE 7
#define ACTION_SCROLL 8
#define BUTTON_PRIMARY 1
#define BUTTON_SECONDARY 2
#define BUTTON_TERTIARY 4
void Android_OnMouse( int androidButton, int action, float x, float y) {
static Uint8 SDLButton;
if (!Android_Window) {
return;
}
switch(action) {
case ACTION_DOWN:
// Determine which button originated the event, and store it for ACTION_UP
SDLButton = SDL_BUTTON_LEFT;
if (androidButton == BUTTON_SECONDARY) {
SDLButton = SDL_BUTTON_RIGHT;
} else if (androidButton == BUTTON_TERTIARY) {
SDLButton = SDL_BUTTON_MIDDLE;
}
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, SDLButton);
break;
case ACTION_UP:
// Android won't give us the button that originated the ACTION_DOWN event, so we'll
// assume it's the one we stored
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, SDLButton);
break;
case ACTION_HOVER_MOVE:
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
break;
case ACTION_SCROLL:
SDL_SendMouseWheel(Android_Window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
break;
default:
break;
}
}
#endif /* SDL_VIDEO_DRIVER_ANDROID */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,31 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _SDL_androidmouse_h
#define _SDL_androidmouse_h
#include "SDL_androidvideo.h"
extern void Android_OnMouse( int button, int action, float x, float y);
#endif /* _SDL_androidmouse_h */
/* vi: set ts=4 sw=4 expandtab: */

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