--- a/CMakeLists.txt Sat Jan 24 23:58:07 2015 -0400
+++ b/CMakeLists.txt Mon Apr 06 15:26:37 2015 -0300
@@ -118,9 +118,9 @@
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 @@
# 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 @@
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 @@
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(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 @@
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 @@
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 @@
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()
--- a/SDL2.spec.in Sat Jan 24 23:58:07 2015 -0400
+++ b/SDL2.spec.in Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
%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 @@
%{_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>
--- a/android-project/src/org/libsdl/app/SDLActivity.java Sat Jan 24 23:58:07 2015 -0400
+++ b/android-project/src/org/libsdl/app/SDLActivity.java Mon Apr 06 15:26:37 2015 -0300
@@ -41,6 +41,10 @@
/** 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 @@
}
/**
- * 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 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);
@@ -1088,8 +1092,8 @@
// Dispatch the different events depending on where they come from
// 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 @@
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;
-
- 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();
- }
+ 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;
+ 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 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;
}
}
--- a/cmake/sdlchecks.cmake Sat Jan 24 23:58:07 2015 -0400
+++ b/cmake/sdlchecks.cmake Mon Apr 06 15:26:37 2015 -0300
@@ -505,8 +505,13 @@
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 @@
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 @@
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 @@
endif()
endmacro()
-# Rquires:
+# Requires:
# - nada
# Optional:
# - THREADS opt
@@ -733,13 +776,17 @@
# 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 @@
#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}
--- a/configure Sat Jan 24 23:58:07 2015 -0400
+++ b/configure Mon Apr 06 15:26:37 2015 -0300
@@ -21916,6 +21916,7 @@
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
+ #define _GNU_SOURCE 1
#include <pthread.h>
int
@@ -21929,7 +21930,7 @@
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 @@
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 @@
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 @@
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 @@
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
--- a/configure.in Sat Jan 24 23:58:07 2015 -0400
+++ b/configure.in Mon Apr 06 15:26:37 2015 -0300
@@ -2424,7 +2424,8 @@
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 @@
])
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 @@
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
--- a/docs/README-platforms.md Sat Jan 24 23:58:07 2015 -0400
+++ b/docs/README-platforms.md Mon Apr 06 15:26:37 2015 -0300
@@ -1,34 +1,8 @@
Platforms
=========
-
-This is a list of the platforms SDL supports, and who maintains them.
-
-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
-===============================
+We maintain the list of supported platforms on our wiki now, and how to
+build and install SDL for those platforms:
+
+ https://wiki.libsdl.org/Installation
+
--- a/docs/README-porting.md Sat Jan 24 23:58:07 2015 -0400
+++ b/docs/README-porting.md Mon Apr 06 15:26:37 2015 -0300
@@ -15,7 +15,7 @@
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:
--- a/docs/README-winrt.md Sat Jan 24 23:58:07 2015 -0400
+++ b/docs/README-winrt.md Mon Apr 06 15:26:37 2015 -0300
@@ -90,10 +90,12 @@
* 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 @@
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
--- a/include/SDL_assert.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_assert.h Mon Apr 06 15:26:37 2015 -0300
@@ -102,9 +102,9 @@
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 @@
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 @@
#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 @@
#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 @@
*
* 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 @@
* 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 @@
* \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 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
}
--- a/include/SDL_config.h.cmake Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_config.h.cmake Mon Apr 06 15:26:37 2015 -0300
@@ -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@
--- a/include/SDL_config.h.in Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_config.h.in Mon Apr 06 15:26:37 2015 -0300
@@ -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 */
--- a/include/SDL_events.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_events.h Mon Apr 06 15:26:37 2015 -0300
@@ -134,6 +134,10 @@
/* 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 @@
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_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 @@
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 */
--- a/include/SDL_gamecontroller.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_gamecontroller.h Mon Apr 06 15:26:37 2015 -0300
@@ -241,7 +241,8 @@
/**
* 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.
*/
--- a/include/SDL_hints.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_hints.h Mon Apr 06 15:26:37 2015 -0300
@@ -533,6 +533,18 @@
*/
#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
*
@@ -548,6 +560,18 @@
#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
*/
typedef enum
--- a/include/SDL_opengl_glext.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_opengl_glext.h Mon Apr 06 15:26:37 2015 -0300
@@ -2988,6 +2988,11 @@
#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
--- a/include/SDL_render.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_render.h Mon Apr 06 15:26:37 2015 -0300
@@ -81,8 +81,8 @@
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 @@
* \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
--- a/include/SDL_stdinc.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_stdinc.h Mon Apr 06 15:26:37 2015 -0300
@@ -173,6 +173,8 @@
#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 @@
#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 @@
#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 @@
#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
--- a/include/SDL_syswm.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_syswm.h Mon Apr 06 15:26:37 2015 -0300
@@ -186,6 +186,7 @@
struct
{
HWND window; /**< The window handle */
+ HDC hdc; /**< The window device context */
} win;
#endif
#if defined(SDL_VIDEO_DRIVER_WINRT)
--- a/include/SDL_video.h Sat Jan 24 23:58:07 2015 -0400
+++ b/include/SDL_video.h Mon Apr 06 15:26:37 2015 -0300
@@ -189,7 +189,8 @@
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 @@
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 @@
* \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,
@@ -730,6 +740,15 @@
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.
*
* \return 0 on success, or -1 if setting the brightness isn't supported.
--- a/src/SDL.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/SDL.c Mon Apr 06 15:26:37 2015 -0300
@@ -405,6 +405,8 @@
return "BSDI";
#elif __DREAMCAST__
return "Dreamcast";
+#elif __EMSCRIPTEN__
+ return "Emscripten";
#elif __FREEBSD__
return "FreeBSD";
#elif __HAIKU__
--- a/src/SDL_error.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/SDL_error.c Mon Apr 06 15:26:37 2015 -0300
@@ -120,7 +120,7 @@
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 @@
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);
--- a/src/audio/SDL_audio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/SDL_audio.c Mon Apr 06 15:26:37 2015 -0300
@@ -51,9 +51,7 @@
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 @@
/* 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 @@
{ /* 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 @@
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)
+
+/* device hotplug support... */
+
+static int
+add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
{
- int i;
+ int retval = -1;
+ const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
+ SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
+ if (item == NULL) {
+ return -1;
+ }
+
+ SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
+
+ item->handle = handle;
+ SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
- for (i = 0; i < length; ++i) {
- stream->buffer[stream->write_pos] = buf[i];
- ++stream->write_pos;
- }
+ SDL_LockMutex(current_audio.detectionLock);
+ item->next = *devices;
+ *devices = item;
+ retval = (*devCount)++;
+ SDL_UnlockMutex(current_audio.detectionLock);
+
+ return retval;
+}
+
+static SDL_INLINE int
+add_capture_device(const char *name, void *handle)
+{
+ /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
+ return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
}
-/* Read [length] bytes out of the streamer into buf */
+static SDL_INLINE int
+add_output_device(const char *name, void *handle)
+{
+ return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
+}
+
static void
-SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
+free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
{
- int i;
+ 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;
+}
+
- for (i = 0; i < length; ++i) {
- buf[i] = stream->buffer[stream->read_pos];
- ++stream->read_pos;
+/* 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);
+ }
}
}
-static int
-SDL_StreamLength(SDL_AudioStreamer * stream)
+/* The audio backends call this when a currently-opened device is lost. */
+void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
{
- return (stream->write_pos - stream->read_pos) % stream->max_len;
-}
+ SDL_assert(get_audio_device(device->id) == device);
-/* 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) {
- return -1;
+ if (!device->enabled) {
+ return;
}
- stream->max_len = max_len;
- stream->read_pos = 0;
- stream->write_pos = 0;
+ /* 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);
- /* Zero out the buffer */
- SDL_memset(stream->buffer, silence, max_len);
-
- return 0;
+ /* 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);
+ }
}
-#endif
-/* Deinitialize the stream simply by freeing the buffer */
static void
-SDL_StreamDeinit(SDL_AudioStreamer * stream)
+mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
{
- SDL_free(stream->buffer);
+ 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;
+ }
+ }
}
-#endif
+
+/* 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, ¤t_audio.captureDevicesRemoved);
+ } else {
+ mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
+ }
+ SDL_UnlockMutex(current_audio.detectionLock);
+ current_audio.impl.FreeDeviceHandle(handle);
+}
+
/* buffer queueing support... */
@@ -510,26 +590,17 @@
}
-#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 @@
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);
+ if (stream == NULL) {
+ stream = device->fake_stream;
+ }
- /* 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);
- }
- }
-
+ /* !!! 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);
}
- } 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) {
+ 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 @@
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_AudioQuit(); /* shutdown driver if already running. */
}
- SDL_memset(¤t_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 @@
}
tried_to_init = 1;
- SDL_memset(¤t_audio, 0, sizeof(current_audio));
+ SDL_zero(current_audio);
current_audio.name = backend->name;
current_audio.desc = backend->desc;
initialized = backend->init(¤t_audio.impl);
@@ -817,13 +751,18 @@
}
}
- SDL_memset(¤t_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 @@
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,30 +812,19 @@
return -1;
}
- if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
- return 0;
- }
-
- if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
- return 1;
- }
-
- if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
- return 1;
+ SDL_LockMutex(current_audio.detectionLock);
+ if (iscapture && current_audio.captureDevicesRemoved) {
+ clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved);
}
- if (iscapture) {
- free_device_list(¤t_audio.inputDevices,
- ¤t_audio.inputDeviceCount);
- current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
- retval = current_audio.inputDeviceCount;
- } else {
- free_device_list(¤t_audio.outputDevices,
- ¤t_audio.outputDeviceCount);
- current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
- retval = current_audio.outputDeviceCount;
+ if (!iscapture && current_audio.outputDevicesRemoved) {
+ clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
+ current_audio.outputDevicesRemoved = SDL_FALSE;
}
+ retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
+ SDL_UnlockMutex(current_audio.detectionLock);
+
return retval;
}
@@ -922,6 +832,8 @@
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 @@
return NULL;
}
- if (index < 0) {
- goto no_such_device;
- }
+ if (index >= 0) {
+ SDL_AudioDeviceItem *item;
+ int i;
- if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
- if (index > 0) {
- goto no_such_device;
+ 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;
}
- return DEFAULT_INPUT_DEVNAME;
+ SDL_UnlockMutex(current_audio.detectionLock);
}
- if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
- if (index > 0) {
- goto no_such_device;
- }
- return DEFAULT_OUTPUT_DEVNAME;
+ if (retval == NULL) {
+ SDL_SetError("No such device");
}
- 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- /* 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 @@
}
}
+ /* 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 @@
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 @@
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 @@
/* 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_assert((id == 0) || (id == 1));
- return ((id == 0) ? -1 : 0);
+ return (id == 0) ? -1 : 0;
}
SDL_AudioDeviceID
@@ -1338,7 +1265,7 @@
status = SDL_AUDIO_PLAYING;
}
}
- return (status);
+ return status;
}
@@ -1429,14 +1356,16 @@
}
}
+ free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
+ free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
+
/* Free the driver data */
current_audio.impl.Deinitialize();
- free_device_list(¤t_audio.outputDevices,
- ¤t_audio.outputDeviceCount);
- free_device_list(¤t_audio.inputDevices,
- ¤t_audio.inputDeviceCount);
- SDL_memset(¤t_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 @@
}
}
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
--- a/src/audio/SDL_audiodev.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/SDL_audiodev.c Mon Apr 06 15:26:37 2015 -0300
@@ -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);
}
- close(audio_fd);
}
}
}
@@ -68,11 +71,10 @@
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 @@
}
}
}
- 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: */
--- a/src/audio/SDL_audiodev_c.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/SDL_audiodev_c.h Mon Apr 06 15:26:37 2015 -0300
@@ -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: */
--- a/src/audio/SDL_sysaudio.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/SDL_sysaudio.h Mon Apr 06 15:26:37 2015 -0300
@@ -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_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 @@
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 @@
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 @@
{
/* * * */
/* Data common to all devices */
+ SDL_AudioDeviceID id;
/* The current audio specification (shared with audio thread) */
SDL_AudioSpec spec;
@@ -125,15 +157,17 @@
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 */
--- a/src/audio/alsa/SDL_alsa_audio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/alsa/SDL_alsa_audio.c Mon Apr 06 15:26:37 2015 -0300
@@ -320,7 +320,7 @@
/* 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 @@
}
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;
--- a/src/audio/android/SDL_androidaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/android/SDL_androidaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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;
--- a/src/audio/arts/SDL_artsaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/arts/SDL_artsaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -151,7 +151,7 @@
/* 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 @@
/* 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 @@
}
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;
--- a/src/audio/bsd/SDL_bsdaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/bsd/SDL_bsdaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
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 @@
/* 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 @@
}
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 @@
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
impl->CloseDevice = BSDAUDIO_CloseDevice;
+ impl->AllowsArbitraryDeviceNames = 1;
+
return 1; /* this audio target is available. */
}
--- a/src/audio/coreaudio/SDL_coreaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/coreaudio/SDL_coreaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
}
#if MACOSX_COREAUDIO
-typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data);
+static const AudioObjectPropertyAddress devlist_address = {
+ kAudioHardwarePropertyDevices,
+ kAudioObjectPropertyScopeGlobal,
+ kAudioObjectPropertyElementMaster
+};
+
+typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data);
+
+typedef struct AudioDeviceList
+{
+ AudioDeviceID devid;
+ SDL_bool alive;
+ struct AudioDeviceList *next;
+} AudioDeviceList;
+
+static AudioDeviceList *output_devs = NULL;
+static AudioDeviceList *capture_devs = NULL;
-static void
-addToDevList(const char *name, AudioDeviceID devId, void *data)
+static SDL_bool
+add_to_internal_dev_list(const int iscapture, AudioDeviceID devId)
{
- SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
- addfn(name);
+ 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
+static void
+addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
{
- const char *findname;
- AudioDeviceID devId;
- int found;
-} FindDevIdData;
-
-static void
-findDevId(const char *name, 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 @@
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 @@
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 @@
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 @@
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 @@
((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)
+{
+ AudioDeviceList *item = *list;
+ while (item) {
+ AudioDeviceList *next = item->next;
+ SDL_free(item);
+ item = next;
+ }
+ *list = NULL;
+}
+
+static void
+COREAUDIO_DetectDevices(void)
{
- build_device_list(iscapture, addToDevList, addfn);
+ build_device_list(SDL_TRUE, addToDevList, NULL);
+ build_device_list(SDL_FALSE, addToDevList, NULL);
+}
+
+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;
+ }
+ }
+
+ add_to_internal_dev_list(iscapture, devId); /* new device, add it. */
+ SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
}
-static int
-find_device_by_name(_THIS, const char *devname, int iscapture)
+static void
+reprocess_device_list(const int iscapture, AudioDeviceList **list)
{
- AudioDeviceID devid = 0;
- OSStatus result = noErr;
- UInt32 size = 0;
- UInt32 alive = 0;
- pid_t pid = 0;
-
- 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;
- }
- devid = data.devId;
+ AudioDeviceList *item;
+ AudioDeviceList *prev = NULL;
+ for (item = *list; item != NULL; item = item->next) {
+ item->alive = SDL_FALSE;
}
- addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
- addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
- kAudioDevicePropertyScopeOutput;
+ build_device_list(iscapture, build_device_change_list, list);
- 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;
+ /* 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;
}
-
- 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;
+/* 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 @@
}
+#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 @@
}
}
+#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 @@
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 @@
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 @@
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 @@
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 @@
"coreaudio", "CoreAudio", COREAUDIO_Init, 0
};
+#endif /* SDL_AUDIO_DRIVER_COREAUDIO */
+
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/directsound/SDL_directsound.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/directsound/SDL_directsound.c Mon Apr 06 15:26:37 2015 -0300
@@ -144,15 +144,22 @@
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 @@
}
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 @@
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 @@
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. */
--- a/src/audio/disk/SDL_diskaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/disk/SDL_diskaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -71,7 +71,7 @@
/* 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 @@
}
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 @@
impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
impl->CloseDevice = DISKAUD_CloseDevice;
+ impl->AllowsArbitraryDeviceNames = 1;
+
return 1; /* this audio target is available. */
}
--- a/src/audio/dsp/SDL_dspaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/dsp/SDL_dspaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
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 @@
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 @@
impl->GetDeviceBuf = DSP_GetDeviceBuf;
impl->CloseDevice = DSP_CloseDevice;
+ impl->AllowsArbitraryDeviceNames = 1;
+
return 1; /* this audio target is available. */
}
--- a/src/audio/dummy/SDL_dummyaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/dummy/SDL_dummyaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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. */
}
--- a/src/audio/emscripten/SDL_emscriptenaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/emscripten/SDL_emscriptenaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -151,12 +151,13 @@
}
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 @@
/* 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 @@
} 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({
--- a/src/audio/esd/SDL_esdaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/esd/SDL_esdaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -129,7 +129,7 @@
/* 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 @@
/* If we couldn't write, assume fatal error for now */
if (written < 0) {
- this->enabled = 0;
+ SDL_OpenedAudioDeviceDisconnected(this);
}
}
@@ -215,7 +215,7 @@
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;
--- a/src/audio/fusionsound/SDL_fsaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/fusionsound/SDL_fsaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -143,7 +143,7 @@
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 @@
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;
--- a/src/audio/haiku/SDL_haikuaudio.cc Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/haiku/SDL_haikuaudio.cc Mon Apr 06 15:26:37 2015 -0300
@@ -111,7 +111,7 @@
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;
--- a/src/audio/nacl/SDL_naclaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/nacl/SDL_naclaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 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 @@
/* 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 @@
NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
NACLAUD_Init, 0
};
+
+#endif /* SDL_AUDIO_DRIVER_NACL */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/nas/SDL_nasaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/nas/SDL_nasaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -276,7 +276,7 @@
}
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;
--- a/src/audio/paudio/SDL_paudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/paudio/SDL_paudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -176,7 +176,7 @@
* 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 @@
/* 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 @@
}
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];
--- a/src/audio/psp/SDL_pspaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/psp/SDL_pspaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
/* SDL_AUDI */
+#endif /* SDL_AUDIO_DRIVER_PSP */
-
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/audio/psp/SDL_pspaudio.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/psp/SDL_pspaudio.h Mon Apr 06 15:26:37 2015 -0300
@@ -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
--- a/src/audio/pulseaudio/SDL_pulseaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/pulseaudio/SDL_pulseaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
};
--- a/src/audio/pulseaudio/SDL_pulseaudio.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/pulseaudio/SDL_pulseaudio.h Mon Apr 06 15:26:37 2015 -0300
@@ -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;
--- a/src/audio/qsa/SDL_qsa_audio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/qsa/SDL_qsa_audio.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
/* If we couldn't write, assume fatal error for now */
if (towrite != 0) {
- this->enabled = 0;
+ SDL_OpenedAudioDeviceDisconnected(this);
}
}
@@ -337,8 +346,9 @@
}
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 @@
/* 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) {
+ if (device != NULL) {
+ /* Open requested audio device */
+ this->hidden->deviceno = device->deviceno;
+ this->hidden->cardno = device->cardno;
+ status = snd_pcm_open(&this->hidden->audio_handle,
+ device->cardno, device->deviceno,
+ iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
+ } else {
/* Open system default audio device */
- if (!this->hidden->iscapture) {
- status = snd_pcm_open_preferred(&this->hidden->audio_handle,
- &this->hidden->cardno,
- &this->hidden->deviceno,
- SND_PCM_OPEN_PLAYBACK);
- } else {
- status = snd_pcm_open_preferred(&this->hidden->audio_handle,
- &this->hidden->cardno,
- &this->hidden->deviceno,
- SND_PCM_OPEN_CAPTURE);
- }
- } else {
- /* Open requested audio device */
- if (!this->hidden->iscapture) {
- status =
- snd_pcm_open(&this->hidden->audio_handle,
- this->hidden->cardno, this->hidden->deviceno,
- SND_PCM_OPEN_PLAYBACK);
- } else {
- status =
- snd_pcm_open(&this->hidden->audio_handle,
- this->hidden->cardno, this->hidden->deviceno,
- SND_PCM_OPEN_CAPTURE);
- }
+ 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 @@
}
static void
-QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
+QSA_DetectDevices(void)
{
uint32_t it;
uint32_t cards;
@@ -656,8 +605,9 @@
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 @@
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 @@
break;
}
}
- } else {
+ }
+
+ { /* capture devices */
/* Capture devices enumeration requested */
for (it = 0; it < cards; it++) {
devices = 0;
@@ -744,7 +696,7 @@
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 {
--- a/src/audio/sndio/SDL_sndioaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/sndio/SDL_sndioaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -158,7 +158,7 @@
/* 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 @@
}
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;
--- a/src/audio/sun/SDL_sunaudio.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/sun/SDL_sunaudio.c Mon Apr 06 15:26:37 2015 -0300
@@ -56,9 +56,9 @@
/* 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 @@
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 @@
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 @@
}
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 @@
impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
impl->CloseDevice = SUNAUDIO_CloseDevice;
+ impl->AllowsArbitraryDeviceNames = 1;
+
return 1; /* this audio target is available. */
}
--- a/src/audio/winmm/SDL_winmm.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/winmm/SDL_winmm.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
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 @@
}
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 @@
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:
--- a/src/audio/xaudio2/SDL_xaudio2.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/audio/xaudio2/SDL_xaudio2.c Mon Apr 06 15:26:37 2015 -0300
@@ -126,16 +126,13 @@
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 @@
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 @@
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 @@
if (result != S_OK) { /* uhoh, panic! */
IXAudio2SourceVoice_FlushSourceBuffers(source);
- this->enabled = 0;
+ SDL_OpenedAudioDeviceDisconnected(this);
}
}
@@ -289,7 +286,7 @@
}
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 @@
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 @@
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 @@
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
}
--- a/src/core/android/SDL_android.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/core/android/SDL_android.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
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 @@
* 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 @@
return s_AndroidExternalFilesPath;
}
+jclass Android_JNI_GetActivityClass(void)
+{
+ return mActivityClass;
+}
+
#endif /* __ANDROID__ */
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/core/android/SDL_android.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/core/android/SDL_android.h Mon Apr 06 15:26:37 2015 -0300
@@ -78,6 +78,7 @@
#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);
--- a/src/core/linux/SDL_ibus.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/core/linux/SDL_ibus.c Mon Apr 06 15:26:37 2015 -0300
@@ -462,6 +462,9 @@
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();
--- a/src/core/linux/SDL_udev.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/core/linux/SDL_udev.c Mon Apr 06 15:26:37 2015 -0300
@@ -350,17 +350,19 @@
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 */
}
}
--- a/src/dynapi/SDL_dynapi.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/dynapi/SDL_dynapi.h Mon Apr 06 15:26:37 2015 -0300
@@ -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
--- a/src/dynapi/SDL_dynapi_overrides.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/dynapi/SDL_dynapi_overrides.h Mon Apr 06 15:26:37 2015 -0300
@@ -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
--- a/src/dynapi/SDL_dynapi_procs.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/dynapi/SDL_dynapi_procs.h Mon Apr 06 15:26:37 2015 -0300
@@ -623,3 +623,4 @@
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)
--- a/src/events/SDL_events.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/events/SDL_events.c Mon Apr 06 15:26:37 2015 -0300
@@ -75,12 +75,13 @@
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 @@
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_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_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_EventQ.count;
+ if (SDL_EventQ.count > SDL_EventQ.max_events_seen) {
+ SDL_EventQ.max_events_seen = SDL_EventQ.count;
+ }
+
return 1;
}
--- a/src/events/SDL_gesture.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/events/SDL_gesture.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 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 @@
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 @@
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"); */
--- a/src/events/SDL_mouse.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/events/SDL_mouse.c Mon Apr 06 15:26:37 2015 -0300
@@ -293,9 +293,14 @@
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 @@
{
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]);
--- a/src/events/SDL_quit.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/events/SDL_quit.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
#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 @@
#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 @@
#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)
--- a/src/filesystem/nacl/SDL_sysfilesystem.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/filesystem/nacl/SDL_sysfilesystem.c Mon Apr 06 15:26:37 2015 -0300
@@ -38,4 +38,5 @@
return NULL;
}
-#endif /* __NACL__ */
\ No newline at end of file
+#endif /* SDL_FILESYSTEM_NACL */
+
--- a/src/haptic/linux/SDL_syshaptic.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/haptic/linux/SDL_syshaptic.c Mon Apr 06 15:26:37 2015 -0300
@@ -288,8 +288,7 @@
}
item->fname = SDL_strdup(path);
- if ( (item->fname == NULL) ) {
- SDL_free(item->fname);
+ if (item->fname == NULL) {
SDL_free(item);
return -1;
}
--- a/src/joystick/SDL_gamecontrollerdb.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/SDL_gamecontrollerdb.h Mon Apr 06 15:26:37 2015 -0300
@@ -63,6 +63,8 @@
"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 @@
"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
};
--- a/src/joystick/SDL_joystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/SDL_joystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -206,10 +206,6 @@
valid = 1;
}
- if (joystick && joystick->closed) {
- valid = 0;
- }
-
return valid;
}
@@ -412,6 +408,7 @@
}
SDL_SYS_JoystickClose(joystick);
+ joystick->hwdata = NULL;
joysticklist = SDL_joysticks;
joysticklistprev = NULL;
@@ -668,7 +665,7 @@
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 @@
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;
--- a/src/joystick/SDL_sysjoystick.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/SDL_sysjoystick.h Mon Apr 06 15:26:37 2015 -0300
@@ -53,8 +53,7 @@
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 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);
--- a/src/joystick/android/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/android/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -467,7 +467,7 @@
}
/* 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 @@
/* 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 @@
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 */
--- a/src/joystick/android/SDL_sysjoystick_c.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/android/SDL_sysjoystick_c.h Mon Apr 06 15:26:37 2015 -0300
@@ -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"
--- a/src/joystick/bsd/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/bsd/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -558,8 +558,6 @@
close(joy->hwdata->fd);
SDL_free(joy->hwdata->path);
SDL_free(joy->hwdata);
-
- return;
}
void
--- a/src/joystick/darwin/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/darwin/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -138,7 +138,7 @@
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 @@
/* 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
- }
}
device->send_open_event = 1;
@@ -446,9 +446,9 @@
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 @@
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 @@
}
}
}
+
+ // 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 @@
}
/* 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 @@
}
/* 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 @@
}
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 @@
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
- joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */
--- a/src/joystick/darwin/SDL_sysjoystick_c.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/darwin/SDL_sysjoystick_c.h Mon Apr 06 15:26:37 2015 -0300
@@ -58,8 +58,7 @@
recElement *firstButton;
recElement *firstHat;
- int removed;
- int uncentered;
+ SDL_bool removed;
int instance_id;
SDL_JoystickGUID guid;
--- a/src/joystick/dummy/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/dummy/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -34,7 +34,7 @@
int
SDL_SYS_JoystickInit(void)
{
- return (0);
+ return 0;
}
int SDL_SYS_NumJoysticks()
@@ -61,7 +61,7 @@
}
/* 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 @@
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 )
--- a/src/joystick/emscripten/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/emscripten/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -46,7 +46,7 @@
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 @@
}
++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 @@
}
#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 @@
return 1;
}
- const int retval = item->device_instance;
if (item->joystick) {
item->joystick->hwdata = NULL;
}
@@ -174,7 +177,9 @@
}
#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 @@
Emscripten_JoyStickConnected);
if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
+ SDL_SYS_JoystickQuit();
return -1;
}
@@ -222,12 +228,28 @@
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 @@
{
}
-// 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 @@
/* 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 @@
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 @@
}
}
}
- item = item->next;
}
}
@@ -375,11 +378,6 @@
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 @@
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 */
--- a/src/joystick/emscripten/SDL_sysjoystick_c.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/emscripten/SDL_sysjoystick_c.h Mon Apr 06 15:26:37 2015 -0300
@@ -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"
--- a/src/joystick/haiku/SDL_haikujoystick.cc Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/haiku/SDL_haikujoystick.cc Mon Apr 06 15:26:37 2015 -0300
@@ -106,7 +106,7 @@
}
/* 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 @@
SDL_free(joystick->hwdata->new_hats);
SDL_free(joystick->hwdata->new_axes);
SDL_free(joystick->hwdata);
- joystick->hwdata = NULL;
}
}
--- a/src/joystick/iphoneos/SDL_sysjoystick.m Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/iphoneos/SDL_sysjoystick.m Mon Apr 06 15:26:37 2015 -0300
@@ -77,7 +77,7 @@
}
/* 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 @@
@autoreleasepool {
[motionManager stopAccelerometerUpdates];
}
- joystick->closed = 1;
}
/* Function to perform any system-specific joystick related cleanup */
--- a/src/joystick/linux/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/linux/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -142,13 +142,15 @@
#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 @@
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 @@
/* 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 @@
/* 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_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 */
--- a/src/joystick/psp/SDL_sysjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/psp/SDL_sysjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
}
/* 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 @@
{
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 @@
/* 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 @@
return guid;
}
+#endif /* SDL_JOYSTICK_PSP */
+
/* vim: ts=4 sw=4
*/
--- a/src/joystick/windows/SDL_mmjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/windows/SDL_mmjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -210,7 +210,7 @@
}
/* 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 @@
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 */
--- a/src/joystick/windows/SDL_windowsjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/joystick/windows/SDL_windowsjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -446,7 +446,7 @@
}
/* 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 @@
/* 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_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 @@
}
if (joystick->hwdata->removed) {
- joystick->closed = SDL_TRUE;
- joystick->uncentered = SDL_TRUE;
+ joystick->force_recentering = SDL_TRUE;
}
}
@@ -512,10 +510,7 @@
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 */
--- a/src/main/psp/SDL_psp_main.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/main/psp/SDL_psp_main.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
(void)SDL_main(argc, argv);
return 0;
}
+
+#endif /* __PSP__ */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/main/windows/SDL_windows_main.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/main/windows/SDL_windows_main.c Mon Apr 06 15:26:37 2015 -0300
@@ -109,13 +109,16 @@
}
#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 @@
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 @@
#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 @@
ParseCommandLine(cmdline, argv);
/* Run the main program */
- console_main(argc, argv);
+ main_utf8(argc, argv);
SDL_stack_free(argv);
--- a/src/render/direct3d11/SDL_render_d3d11.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/render/direct3d11/SDL_render_d3d11.c Mon Apr 06 15:26:37 2015 -0300
@@ -829,9 +829,24 @@
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:
--- a/src/render/opengl/SDL_render_gl.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/render/opengl/SDL_render_gl.c Mon Apr 06 15:26:37 2015 -0300
@@ -342,9 +342,11 @@
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);
}
}
--- a/src/test/SDL_test_common.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/test/SDL_test_common.c Mon Apr 06 15:26:37 2015 -0300
@@ -1204,10 +1204,10 @@
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);
--- a/src/thread/psp/SDL_syscond.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/thread/psp/SDL_syscond.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
+#endif /* SDL_THREAD_PSP */
+
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/thread/psp/SDL_sysmutex.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/thread/psp/SDL_sysmutex.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
#endif /* SDL_THREADS_DISABLED */
}
+#endif /* SDL_THREAD_PSP */
+
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/thread/psp/SDL_syssem.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/thread/psp/SDL_syssem.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
return 0;
}
+#endif /* SDL_THREAD_PSP */
+
/* vim: ts=4 sw=4
*/
--- a/src/thread/psp/SDL_systhread.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/thread/psp/SDL_systhread.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
}
+#endif /* SDL_THREAD_PSP */
+
/* vim: ts=4 sw=4
*/
--- a/src/timer/psp/SDL_systimer.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/timer/psp/SDL_systimer.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
sceKernelDelayThreadCB(ms * 1000);
}
+#endif /* SDL_TIMERS_PSP */
+
/* vim: ts=4 sw=4
*/
--- a/src/video/SDL_bmp.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/SDL_bmp.c Mon Apr 06 15:26:37 2015 -0300
@@ -306,16 +306,19 @@
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;
}
--- a/src/video/SDL_clipboard.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/SDL_clipboard.c Mon Apr 06 15:26:37 2015 -0300
@@ -29,6 +29,10 @@
{
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_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_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 {
--- a/src/video/SDL_fillrect.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/SDL_fillrect.c Mon Apr 06 15:26:37 2015 -0300
@@ -251,6 +251,10 @@
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 */
--- a/src/video/SDL_sysvideo.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/SDL_sysvideo.h Mon Apr 06 15:26:37 2015 -0300
@@ -274,6 +274,7 @@
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 @@
int flags;
int profile_mask;
int share_with_current_context;
+ int release_behavior;
int framebuffer_srgb_capable;
int retained_backing;
int driver_loaded;
--- a/src/video/SDL_video.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/SDL_video.c Mon Apr 06 15:26:37 2015 -0300
@@ -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 @@
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 @@
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 @@
} 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_GetWindowGrab(SDL_Window * window)
{
CHECK_WINDOW_MAGIC(window, SDL_FALSE);
-
- return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
+ SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
+ return window == _this->grabbed_window;
+}
+
+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 @@
#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 @@
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;
@@ -2847,6 +2877,13 @@
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:
{
GLint bits = 0;
--- a/src/video/android/SDL_androidevents.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/android/SDL_androidevents.c Mon Apr 06 15:26:37 2015 -0300
@@ -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()
--- a/src/video/android/SDL_androidmessagebox.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/android/SDL_androidmessagebox.c Mon Apr 06 15:26:37 2015 -0300
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/android/SDL_androidmouse.c Mon Apr 06 15:26:37 2015 -0300
@@ -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: */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/android/SDL_androidmouse.h Mon Apr 06 15:26:37 2015 -0300
@@ -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: */
--- a/src/video/android/SDL_androidtouch.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/android/SDL_androidtouch.c Mon Apr 06 15:26:37 2015 -0300
@@ -24,13 +24,12 @@
#include <android/log.h>
+#include "SDL_hints.h"
#include "SDL_events.h"
+#include "SDL_log.h"
+#include "SDL_androidtouch.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
-#include "SDL_log.h"
-
-#include "SDL_androidtouch.h"
-
#include "../../core/android/SDL_android.h"
#define ACTION_DOWN 0
@@ -51,11 +50,29 @@
*window_y = (int)(y * window_h);
}
+static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE;
+
+static void
+SeparateEventsHintWatcher(void *userdata, const char *name,
+ const char *oldValue, const char *newValue)
+{
+ jclass mActivityClass = Android_JNI_GetActivityClass();
+ JNIEnv *env = Android_JNI_GetEnv();
+ jfieldID fid = (*env)->GetStaticFieldID(env, mActivityClass, "mSeparateMouseAndTouch", "Z");
+
+ separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0));
+ (*env)->SetStaticBooleanField(env, mActivityClass, fid, separate_mouse_and_touch ? JNI_TRUE : JNI_FALSE);
+}
+
void Android_InitTouch(void)
{
int i;
int* ids;
- int number = Android_JNI_GetTouchDeviceIds(&ids);
+ const int number = Android_JNI_GetTouchDeviceIds(&ids);
+
+ SDL_AddHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
+ SeparateEventsHintWatcher, NULL);
+
if (0 < number) {
for (i = 0; i < number; ++i) {
SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
@@ -64,6 +81,13 @@
}
}
+void Android_QuitTouch(void)
+{
+ SDL_DelHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
+ SeparateEventsHintWatcher, NULL);
+ separate_mouse_and_touch = SDL_FALSE;
+}
+
void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
{
SDL_TouchID touchDeviceId = 0;
@@ -85,36 +109,41 @@
case ACTION_DOWN:
/* Primary pointer down */
Android_GetWindowCoordinates(x, y, &window_x, &window_y);
- /* send moved event */
- SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
- /* send mouse down event */
- SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
+ if (!separate_mouse_and_touch) {
+ /* send moved event */
+ SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
+ /* send mouse down event */
+ SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
+ }
pointerFingerID = fingerId;
case ACTION_POINTER_DOWN:
/* Non primary pointer down */
SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
break;
-
+
case ACTION_MOVE:
if (!pointerFingerID) {
Android_GetWindowCoordinates(x, y, &window_x, &window_y);
-
- /* send moved event */
- SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
+ if (!separate_mouse_and_touch) {
+ /* send moved event */
+ SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
+ }
}
SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
break;
-
+
case ACTION_UP:
/* Primary pointer up */
- /* send mouse up */
- pointerFingerID = (SDL_FingerID) 0;
- SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
+ if (!separate_mouse_and_touch) {
+ /* send mouse up */
+ pointerFingerID = (SDL_FingerID) 0;
+ SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
+ }
case ACTION_POINTER_UP:
/* Non primary pointer up */
SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
break;
-
+
default:
break;
}
--- a/src/video/android/SDL_androidtouch.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/android/SDL_androidtouch.h Mon Apr 06 15:26:37 2015 -0300
@@ -23,6 +23,7 @@
#include "SDL_androidvideo.h"
extern void Android_InitTouch(void);
+extern void Android_QuitTouch(void);
extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/android/SDL_androidvideo.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/android/SDL_androidvideo.c Mon Apr 06 15:26:37 2015 -0300
@@ -86,6 +86,7 @@
static void
Android_DeleteDevice(SDL_VideoDevice * device)
{
+ SDL_free(device->driverdata);
SDL_free(device);
}
@@ -187,6 +188,7 @@
void
Android_VideoQuit(_THIS)
{
+ Android_QuitTouch();
}
/* This function gets called before VideoInit() */
--- a/src/video/cocoa/SDL_cocoaevents.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/cocoa/SDL_cocoaevents.h Mon Apr 06 15:26:37 2015 -0300
@@ -25,6 +25,7 @@
extern void Cocoa_RegisterApp(void);
extern void Cocoa_PumpEvents(_THIS);
+extern void Cocoa_SuspendScreenSaver(_THIS);
#endif /* _SDL_cocoaevents_h */
--- a/src/video/cocoa/SDL_cocoaevents.m Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/cocoa/SDL_cocoaevents.m Mon Apr 06 15:26:37 2015 -0300
@@ -27,6 +27,11 @@
#include "../../events/SDL_events_c.h"
#include "SDL_assert.h"
+/* This define was added in the 10.9 SDK. */
+#ifndef kIOPMAssertPreventUserIdleDisplaySleep
+#define kIOPMAssertPreventUserIdleDisplaySleep kIOPMAssertionTypePreventUserIdleDisplaySleep
+#endif
+
@interface SDLApplication : NSApplication
- (void)terminate:(id)sender;
@@ -61,11 +66,19 @@
{
self = [super init];
if (self) {
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
seenFirstActivate = NO;
- [[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(focusSomeWindow:)
- name:NSApplicationDidBecomeActiveNotification
- object:nil];
+
+ [center addObserver:self
+ selector:@selector(windowWillClose:)
+ name:NSWindowWillCloseNotification
+ object:nil];
+
+ [center addObserver:self
+ selector:@selector(focusSomeWindow:)
+ name:NSApplicationDidBecomeActiveNotification
+ object:nil];
}
return self;
@@ -73,16 +86,65 @@
- (void)dealloc
{
- [[NSNotificationCenter defaultCenter] removeObserver:self];
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ [center removeObserver:self name:NSWindowWillCloseNotification object:nil];
+ [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
+
[super dealloc];
}
+- (void)windowWillClose:(NSNotification *)notification;
+{
+ NSWindow *win = (NSWindow*)[notification object];
+
+ if (![win isKeyWindow]) {
+ return;
+ }
+
+ /* HACK: Make the next window in the z-order key when the key window is
+ * closed. The custom event loop and/or windowing code we have seems to
+ * prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825
+ */
+
+ /* +[NSApp orderedWindows] never includes the 'About' window, but we still
+ * want to try its list first since the behavior in other apps is to only
+ * make the 'About' window key if no other windows are on-screen.
+ */
+ for (NSWindow *window in [NSApp orderedWindows]) {
+ if (window != win && [window canBecomeKeyWindow]) {
+ if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
+ if (![window isOnActiveSpace]) {
+ continue;
+ }
+ }
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+
+ /* If a window wasn't found above, iterate through all visible windows
+ * (including the 'About' window, if it's shown) and make the first one key.
+ * Note that +[NSWindow windowNumbersWithOptions:] was added in 10.6.
+ */
+ if ([NSWindow respondsToSelector:@selector(windowNumbersWithOptions:)]) {
+ /* Get all visible windows in the active Space, in z-order. */
+ for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
+ NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
+ if (window && window != win && [window canBecomeKeyWindow]) {
+ [window makeKeyAndOrderFront:self];
+ return;
+ }
+ }
+ }
+}
+
- (void)focusSomeWindow:(NSNotification *)aNotification
{
/* HACK: Ignore the first call. The application gets a
* applicationDidBecomeActive: a little bit after the first window is
* created, and if we don't ignore it, a window that has been created with
- * SDL_WINDOW_MINIZED will ~immediately be restored.
+ * SDL_WINDOW_MINIMIZED will ~immediately be restored.
*/
if (!seenFirstActivate) {
seenFirstActivate = YES;
@@ -251,17 +313,24 @@
{ @autoreleasepool
{
/* This can get called more than once! Be careful what you initialize! */
- ProcessSerialNumber psn;
-
- if (!GetCurrentProcess(&psn)) {
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- SetFrontProcess(&psn);
- }
if (NSApp == nil) {
[SDLApplication sharedApplication];
SDL_assert(NSApp != nil);
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+ if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) {
+#endif
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
+ } else {
+ ProcessSerialNumber psn = {0, kCurrentProcess};
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ }
+#endif
+
+ [NSApp activateIgnoringOtherApps:YES];
+
if ([NSApp mainMenu] == nil) {
CreateApplicationMenus();
}
@@ -293,8 +362,8 @@
{ @autoreleasepool
{
/* Update activity every 30 seconds to prevent screensaver */
- if (_this->suspend_screensaver) {
- SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+ SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+ if (_this->suspend_screensaver && !data->screensaver_use_iopm) {
Uint32 now = SDL_GetTicks();
if (!data->screensaver_activity ||
SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
@@ -336,6 +405,35 @@
}
}}
+void
+Cocoa_SuspendScreenSaver(_THIS)
+{ @autoreleasepool
+{
+ SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
+
+ if (!data->screensaver_use_iopm) {
+ return;
+ }
+
+ if (data->screensaver_assertion) {
+ IOPMAssertionRelease(data->screensaver_assertion);
+ data->screensaver_assertion = 0;
+ }
+
+ if (_this->suspend_screensaver) {
+ /* FIXME: this should ideally describe the real reason why the game
+ * called SDL_DisableScreenSaver. Note that the name is only meant to be
+ * seen by OS X power users. there's an additional optional human-readable
+ * (localized) reason parameter which we don't set.
+ */
+ NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"];
+ IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep,
+ (CFStringRef) name,
+ NULL, NULL, NULL, 0, NULL,
+ &data->screensaver_assertion);
+ }
+}}
+
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/cocoa/SDL_cocoavideo.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/cocoa/SDL_cocoavideo.h Mon Apr 06 15:26:37 2015 -0300
@@ -26,6 +26,7 @@
#include "SDL_opengl.h"
#include <ApplicationServices/ApplicationServices.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
#include <Cocoa/Cocoa.h>
#include "SDL_keycode.h"
@@ -51,6 +52,9 @@
SDLTranslatorResponder *fieldEdit;
NSInteger clipboard_count;
Uint32 screensaver_activity;
+ BOOL screensaver_use_iopm;
+ IOPMAssertionID screensaver_assertion;
+
} SDL_VideoData;
/* Utility functions */
--- a/src/video/cocoa/SDL_cocoavideo.m Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/cocoa/SDL_cocoavideo.m Mon Apr 06 15:26:37 2015 -0300
@@ -76,6 +76,7 @@
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;
+ device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
device->CreateWindow = Cocoa_CreateWindow;
device->CreateWindowFrom = Cocoa_CreateWindowFrom;
@@ -148,6 +149,9 @@
const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES);
data->allow_spaces = ( (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && (!hint || (*hint != '0')) );
+ /* The IOPM assertion API can disable the screensaver as of 10.7. */
+ data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+
return 0;
}
--- a/src/video/cocoa/SDL_cocoawindow.m Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/cocoa/SDL_cocoawindow.m Mon Apr 06 15:26:37 2015 -0300
@@ -374,7 +374,6 @@
NSNotificationCenter *center;
NSWindow *window = _data->nswindow;
NSView *view = [window contentView];
- NSArray *windows = nil;
center = [NSNotificationCenter defaultCenter];
@@ -402,25 +401,6 @@
if ([view nextResponder] == self) {
[view setNextResponder:nil];
}
-
- /* Make the next window in the z-order Key. If we weren't the foreground
- when closed, this is a no-op.
- !!! FIXME: Note that this is a hack, and there are corner cases where
- !!! FIXME: this fails (such as the About box). The typical nib+RunLoop
- !!! FIXME: handles this for Cocoa apps, but we bypass all that in SDL.
- !!! FIXME: We should remove this code when we find a better way to
- !!! FIXME: have the system do this for us. See discussion in
- !!! FIXME: http://bugzilla.libsdl.org/show_bug.cgi?id=1825
- */
- windows = [NSApp orderedWindows];
- for (NSWindow *win in windows) {
- if (win == window) {
- continue;
- }
-
- [win makeKeyAndOrderFront:self];
- break;
- }
}
- (BOOL)isMoving
--- a/src/video/dummy/SDL_nullvideo.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/dummy/SDL_nullvideo.c Mon Apr 06 15:26:37 2015 -0300
@@ -82,7 +82,6 @@
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_OutOfMemory();
- SDL_free(device);
return (0);
}
--- a/src/video/emscripten/SDL_emscriptenevents.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/emscripten/SDL_emscriptenevents.c Mon Apr 06 15:26:37 2015 -0300
@@ -296,7 +296,7 @@
return SDL_TRUE;
}
-int
+EM_BOOL
Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -322,7 +322,7 @@
return 0;
}
-int
+EM_BOOL
Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -344,7 +344,7 @@
return 1;
}
-int
+EM_BOOL
Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -352,7 +352,7 @@
return 1;
}
-int
+EM_BOOL
Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -360,7 +360,7 @@
return 1;
}
-int
+EM_BOOL
Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -368,7 +368,7 @@
return 1;
}
-int
+EM_BOOL
Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
/*SDL_WindowData *window_data = userData;*/
@@ -404,7 +404,7 @@
return 1;
}
-int
+EM_BOOL
Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
{
Uint32 scancode;
@@ -443,16 +443,17 @@
|| keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
}
-int
+EM_BOOL
Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
{
char text[5];
- Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text);
- SDL_SendKeyboardText(text);
+ if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) {
+ SDL_SendKeyboardText(text);
+ }
return 1;
}
-int
+EM_BOOL
Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
{
/*make sure this is actually our element going fullscreen*/
@@ -514,7 +515,7 @@
return 0;
}
-int
+EM_BOOL
Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -554,7 +555,7 @@
return 0;
}
-int
+EM_BOOL
Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
{
SDL_WindowData *window_data = userData;
@@ -621,10 +622,15 @@
emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL);
emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL);
- emscripten_set_keydown_callback("#window", NULL, 0, NULL);
- emscripten_set_keyup_callback("#window", NULL, 0, NULL);
+ const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
+ if (!target) {
+ target = "#window";
+ }
- emscripten_set_keypress_callback("#window", NULL, 0, NULL);
+ emscripten_set_keydown_callback(target, NULL, 0, NULL);
+ emscripten_set_keyup_callback(target, NULL, 0, NULL);
+
+ emscripten_set_keypress_callback(target, NULL, 0, NULL);
emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL);
--- a/src/video/emscripten/SDL_emscriptenframebuffer.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/emscripten/SDL_emscriptenframebuffer.c Mon Apr 06 15:26:37 2015 -0300
@@ -63,7 +63,7 @@
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
surface = data->surface;
if (!surface) {
- return SDL_SetError("Couldn't find dummy surface for window");
+ return SDL_SetError("Couldn't find framebuffer surface for window");
}
/* Send the data to the display */
--- a/src/video/nacl/SDL_naclevents.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/nacl/SDL_naclevents.c Mon Apr 06 15:26:37 2015 -0300
@@ -20,6 +20,8 @@
*/
#include "../../SDL_internal.h"
+#if SDL_VIDEO_DRIVER_NACL
+
#include "SDL.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
@@ -430,3 +432,7 @@
}
}
}
+
+#endif /* SDL_VIDEO_DRIVER_NACL */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/psp/SDL_pspevents.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/psp/SDL_pspevents.c Mon Apr 06 15:26:37 2015 -0300
@@ -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_VIDEO_DRIVER_PSP
/* Being a null driver, there's no event stream. We just define stubs for
most of the API. */
@@ -282,3 +285,6 @@
/* end of SDL_pspevents.c ... */
+#endif /* SDL_VIDEO_DRIVER_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/psp/SDL_pspgl.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/psp/SDL_pspgl.c Mon Apr 06 15:26:37 2015 -0300
@@ -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_VIDEO_DRIVER_PSP
#include <stdlib.h>
#include <string.h>
@@ -203,3 +206,6 @@
return;
}
+#endif /* SDL_VIDEO_DRIVER_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/psp/SDL_pspmouse.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/psp/SDL_pspmouse.c Mon Apr 06 15:26:37 2015 -0300
@@ -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_VIDEO_DRIVER_PSP
#include <stdio.h>
@@ -33,3 +35,7 @@
struct WMcursor {
int unused;
};
+
+#endif /* SDL_VIDEO_DRIVER_PSP */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/psp/SDL_pspvideo.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/psp/SDL_pspvideo.c Mon Apr 06 15:26:37 2015 -0300
@@ -66,7 +66,7 @@
SDL_GLDriverData *gldata;
int status;
- /* Check if pandora could be initialized */
+ /* Check if PSP could be initialized */
status = PSP_Available();
if (status == 0) {
/* PSP could not be used */
@@ -80,7 +80,7 @@
return NULL;
}
- /* Initialize internal Pandora specific data */
+ /* Initialize internal PSP specific data */
phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
if (phdata == NULL) {
SDL_OutOfMemory();
--- a/src/video/psp/SDL_pspvideo.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/psp/SDL_pspvideo.h Mon Apr 06 15:26:37 2015 -0300
@@ -19,8 +19,8 @@
3. This notice may not be removed or altered from any source distribution.
*/
-#ifndef __SDL_PANDORA_H__
-#define __SDL_PANDORA_H__
+#ifndef _SDL_pspvideo_h
+#define _SDL_pspvideo_h
#include <GLES/egl.h>
@@ -97,6 +97,6 @@
void PSP_HideScreenKeyboard(_THIS, SDL_Window *window);
SDL_bool PSP_IsScreenKeyboardShown(_THIS, SDL_Window *window);
-#endif /* __SDL_PANDORA_H__ */
+#endif /* _SDL_pspvideo_h */
/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/wayland/SDL_waylandwindow.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/wayland/SDL_waylandwindow.c Mon Apr 06 15:26:37 2015 -0300
@@ -29,6 +29,7 @@
#include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandtouch.h"
+#include "SDL_waylanddyn.h"
static void
handle_ping(void *data, struct wl_shell_surface *shell_surface,
--- a/src/video/windows/SDL_windowsevents.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/windows/SDL_windowsevents.c Mon Apr 06 15:26:37 2015 -0300
@@ -559,10 +559,11 @@
GetKeyboardState(keyboardState);
if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
- WORD repetition;
- for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
- WIN_ConvertUTF32toUTF8(utf32, text);
- SDL_SendKeyboardText(text);
+ if (WIN_ConvertUTF32toUTF8(utf32, text)) {
+ WORD repetition;
+ for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
+ SDL_SendKeyboardText(text);
+ }
}
}
}
--- a/src/video/windows/SDL_windowsopengl.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/windows/SDL_windowsopengl.c Mon Apr 06 15:26:37 2015 -0300
@@ -74,6 +74,13 @@
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
#endif
+#ifndef WGL_ARB_context_flush_control
+#define WGL_ARB_context_flush_control
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif
+
typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
HGLRC
hShareContext,
@@ -405,6 +412,11 @@
_this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE;
}
+ /* Check for GLX_ARB_context_flush_control */
+ if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
+ _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
+ }
+
_this->gl_data->wglMakeCurrent(hdc, NULL);
_this->gl_data->wglDeleteContext(hglrc);
ReleaseDC(hwnd, hdc);
@@ -648,8 +660,8 @@
SDL_SetError("GL 3.x is not supported");
context = temp_context;
} else {
- /* max 8 attributes plus terminator */
- int attribs[9] = {
+ /* max 10 attributes plus terminator */
+ int attribs[11] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
0
@@ -668,6 +680,14 @@
attribs[iattr++] = _this->gl_config.flags;
}
+ /* only set if wgl extension is available */
+ if( _this->gl_data->HAS_WGL_ARB_context_flush_control ) {
+ attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
+ attribs[iattr++] = _this->gl_config.release_behavior ?
+ WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
+ WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
+ }
+
attribs[iattr++] = 0;
/* Create the GL 3.x context */
--- a/src/video/windows/SDL_windowsopengl.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/windows/SDL_windowsopengl.h Mon Apr 06 15:26:37 2015 -0300
@@ -30,6 +30,7 @@
SDL_bool HAS_WGL_ARB_pixel_format;
SDL_bool HAS_WGL_EXT_swap_control_tear;
SDL_bool HAS_WGL_EXT_create_context_es2_profile;
+ SDL_bool HAS_WGL_ARB_context_flush_control;
void *(WINAPI * wglGetProcAddress) (const char *proc);
HGLRC(WINAPI * wglCreateContext) (HDC hdc);
--- a/src/video/windows/SDL_windowswindow.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/windows/SDL_windowswindow.c Mon Apr 06 15:26:37 2015 -0300
@@ -643,10 +643,11 @@
SDL_bool
WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
{
- HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
if (info->version.major <= SDL_MAJOR_VERSION) {
info->subsystem = SDL_SYSWM_WINDOWS;
- info->info.win.window = hwnd;
+ info->info.win.window = data->hwnd;
+ info->info.win.hdc = data->hdc;
return SDL_TRUE;
} else {
SDL_SetError("Application not compiled with SDL %d.%d\n",
--- a/src/video/winrt/SDL_winrtopengles.cpp Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/winrt/SDL_winrtopengles.cpp Mon Apr 06 15:26:37 2015 -0300
@@ -36,10 +36,17 @@
/* ANGLE/WinRT constants */
static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
-#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
-#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
-#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
+
+#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B
+
/*
* SDL/EGL top-level implementation
@@ -80,11 +87,40 @@
Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
_this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
if (!_this->egl_data->egl_display) {
- return SDL_SetError("Could not get EGL display");
+ return SDL_SetError("Could not get Windows 8.0 EGL display");
+ }
+
+ if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+ return SDL_SetError("Could not initialize Windows 8.0 EGL");
}
} else {
- const EGLint displayAttributes[] = {
+ /* Declare some ANGLE/EGL initialization property-sets, as suggested by
+ * MSOpenTech's ANGLE-for-WinRT template apps:
+ */
+ const EGLint defaultDisplayAttributes[] =
+ {
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
+
+ const EGLint fl9_3DisplayAttributes[] =
+ {
EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
+ };
+
+ const EGLint warpDisplayAttributes[] =
+ {
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
+ EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
EGL_NONE,
};
@@ -99,14 +135,41 @@
return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)");
}
- _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes);
+#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+ /* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not
+ * supported on WinPhone 8.x.
+ */
+ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
if (!_this->egl_data->egl_display) {
- return SDL_SetError("Could not get EGL display");
+ return SDL_SetError("Could not get 10_0+ EGL display");
}
- }
+
+ if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE)
+#endif
+ {
+ /* Try initializing EGL at D3D11 Feature Level 9_3, in case the
+ * 10_0 init fails, or we're on Windows Phone (which only supports
+ * 9_3).
+ */
+ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
+ if (!_this->egl_data->egl_display) {
+ return SDL_SetError("Could not get 9_3 EGL display");
+ }
- if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
- return SDL_SetError("Could not initialize EGL");
+ if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+ /* Try initializing EGL at D3D11 Feature Level 11_0 on WARP
+ * (a Windows-provided, software rasterizer) if all else fails.
+ */
+ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
+ if (!_this->egl_data->egl_display) {
+ return SDL_SetError("Could not get WARP EGL display");
+ }
+
+ if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+ return SDL_SetError("Could not initialize WinRT 8.x+ EGL");
+ }
+ }
+ }
}
return 0;
--- a/src/video/x11/SDL_x11events.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11events.c Mon Apr 06 15:26:37 2015 -0300
@@ -677,8 +677,17 @@
data->window == SDL_GetKeyboardFocus()) {
ReconcileKeyboardState(_this, data);
}
- data->pending_focus = PENDING_FOCUS_IN;
- data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;
+ if (!videodata->last_mode_change_deadline) /* no recent mode changes */
+ {
+ data->pending_focus = PENDING_FOCUS_NONE;
+ data->pending_focus_time = 0;
+ X11_DispatchFocusIn(data);
+ }
+ else
+ {
+ data->pending_focus = PENDING_FOCUS_IN;
+ data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
+ }
}
break;
@@ -701,8 +710,17 @@
#ifdef DEBUG_XEVENTS
printf("window %p: FocusOut!\n", data);
#endif
- data->pending_focus = PENDING_FOCUS_OUT;
- data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
+ if (!videodata->last_mode_change_deadline) /* no recent mode changes */
+ {
+ data->pending_focus = PENDING_FOCUS_NONE;
+ data->pending_focus_time = 0;
+ X11_DispatchFocusOut(data);
+ }
+ else
+ {
+ data->pending_focus = PENDING_FOCUS_OUT;
+ data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
+ }
}
break;
@@ -1090,15 +1108,25 @@
without ever mapping / unmapping them, so we handle that here,
because they use the NETWM protocol to notify us of changes.
*/
- Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
- if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN ||
- (flags^data->window->flags) & SDL_WINDOW_FULLSCREEN ) {
- if (flags & SDL_WINDOW_HIDDEN) {
- X11_DispatchUnmapNotify(data);
- } else {
- X11_DispatchMapNotify(data);
+ const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
+ const Uint32 changed = flags ^ data->window->flags;
+
+ if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
+ if (flags & SDL_WINDOW_HIDDEN) {
+ X11_DispatchUnmapNotify(data);
+ } else {
+ X11_DispatchMapNotify(data);
}
}
+
+ if (changed & SDL_WINDOW_MAXIMIZED) {
+ if (flags & SDL_WINDOW_MAXIMIZED) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+ } else {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+ }
+ }
+
}
}
break;
@@ -1283,9 +1311,15 @@
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ if (data->last_mode_change_deadline) {
+ if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
+ data->last_mode_change_deadline = 0; /* assume we're done. */
+ }
+ }
+
/* Update activity every 30 seconds to prevent screensaver */
if (_this->suspend_screensaver) {
- Uint32 now = SDL_GetTicks();
+ const Uint32 now = SDL_GetTicks();
if (!data->screensaver_activity ||
SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
X11_XResetScreenSaver(data->display);
--- a/src/video/x11/SDL_x11messagebox.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11messagebox.c Mon Apr 06 15:26:37 2015 -0300
@@ -31,8 +31,8 @@
#include <locale.h>
-#define SDL_FORK_MESSAGEBOX 0
-#define SDL_SET_LOCALE 0
+#define SDL_FORK_MESSAGEBOX 1
+#define SDL_SET_LOCALE 1
#if SDL_FORK_MESSAGEBOX
#include <sys/types.h>
@@ -366,6 +366,7 @@
int x, y;
XSizeHints *sizehints;
XSetWindowAttributes wnd_attr;
+ Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG;
Display *display = data->display;
SDL_WindowData *windowdata = NULL;
const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
@@ -401,6 +402,13 @@
X11_XStoreName( display, data->window, messageboxdata->title );
+ /* Let the window manager know this is a dialog box */
+ _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
+ _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
+ X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1);
+
/* Allow the window to be deleted by the window manager */
data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False );
data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False );
@@ -710,9 +718,6 @@
int fds[2];
int status = 0;
- /* Need to flush here in case someone has turned grab off and it hasn't gone through yet, etc. */
- X11_XFlush(data->display);
-
if (pipe(fds) == -1) {
return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
}
--- a/src/video/x11/SDL_x11modes.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11modes.c Mon Apr 06 15:26:37 2015 -0300
@@ -24,6 +24,7 @@
#include "SDL_hints.h"
#include "SDL_x11video.h"
+#include "SDL_timer.h"
#include "edid.h"
/* #define X11MODES_DEBUG */
@@ -813,10 +814,13 @@
int
X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
{
- Display *display = ((SDL_VideoData *) _this->driverdata)->display;
+ SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
+ Display *display = viddata->display;
SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
+ viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
+
#if SDL_VIDEO_DRIVER_X11_XRANDR
if (data->use_xrandr) {
XRRScreenResources *res;
--- a/src/video/x11/SDL_x11opengl.c Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11opengl.c Mon Apr 06 15:26:37 2015 -0300
@@ -122,6 +122,13 @@
#define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
#endif
+#ifndef GLX_ARB_context_flush_control
+#define GLX_ARB_context_flush_control
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif
+
#define OPENGL_REQUIRES_DLOPEN
#if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
#include <dlfcn.h>
@@ -279,14 +286,14 @@
const char *start;
const char *where, *terminator;
+ if (!extensions)
+ return SDL_FALSE;
+
/* Extension names should not have spaces. */
where = SDL_strchr(extension, ' ');
if (where || *extension == '\0')
return SDL_FALSE;
- if (!extensions)
- return SDL_FALSE;
-
/* It takes a bit of care to be fool-proof about parsing the
* OpenGL extensions string. Don't be fooled by sub-strings,
* etc. */
@@ -312,32 +319,10 @@
X11_GL_InitExtensions(_THIS)
{
Display *display = ((SDL_VideoData *) _this->driverdata)->display;
- int screen = DefaultScreen(display);
- XVisualInfo *vinfo;
- XSetWindowAttributes xattr;
- Window w;
- GLXContext context;
+ const int screen = DefaultScreen(display);
const char *(*glXQueryExtensionsStringFunc) (Display *, int);
const char *extensions;
- vinfo = X11_GL_GetVisual(_this, display, screen);
- if (!vinfo) {
- return;
- }
- xattr.background_pixel = 0;
- xattr.border_pixel = 0;
- xattr.colormap =
- X11_XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
- AllocNone);
- w = X11_XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
- vinfo->depth, InputOutput, vinfo->visual,
- (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
- context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
- if (context) {
- _this->gl_data->glXMakeCurrent(display, w, context);
- }
- X11_XFree(vinfo);
-
glXQueryExtensionsStringFunc =
(const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
"glXQueryExtensionsString");
@@ -373,6 +358,16 @@
(int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
}
+ /* Check for GLX_ARB_create_context */
+ if (HasExtension("GLX_ARB_create_context", extensions)) {
+ _this->gl_data->glXCreateContextAttribsARB =
+ (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
+ X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
+ _this->gl_data->glXChooseFBConfig =
+ (GLXFBConfig *(*)(Display *, int, const int *, int *))
+ X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
+ }
+
/* Check for GLX_EXT_visual_rating */
if (HasExtension("GLX_EXT_visual_rating", extensions)) {
_this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
@@ -388,18 +383,16 @@
_this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE;
}
- if (context) {
- _this->gl_data->glXMakeCurrent(display, None, NULL);
- _this->gl_data->glXDestroyContext(display, context);
+ /* Check for GLX_ARB_context_flush_control */
+ if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
+ _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
}
- X11_XDestroyWindow(display, w);
- X11_PumpEvents(_this);
}
/* glXChooseVisual and glXChooseFBConfig have some small differences in
* the attribute encoding, it can be chosen with the for_FBConfig parameter.
*/
-int
+static int
X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
{
int i = 0;
@@ -481,9 +474,7 @@
if (_this->gl_config.framebuffer_srgb_capable) {
attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
- if( for_FBConfig ) {
- attribs[i++] = True;
- }
+ attribs[i++] = True; /* always needed, for_FBConfig or not! */
}
if (_this->gl_config.accelerated >= 0 &&
@@ -576,7 +567,6 @@
XVisualInfo v, *vinfo;
int n;
GLXContext context = NULL, share_context;
- PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL;
if (_this->gl_config.share_with_current_context) {
share_context = (GLXContext)SDL_GL_GetCurrentContext();
@@ -601,78 +591,61 @@
context =
_this->gl_data->glXCreateContext(display, vinfo, share_context, True);
} else {
- /* If we want a GL 3.0 context or later we need to get a temporary
- context to grab the new context creation function */
- GLXContext temp_context =
- _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
- if (temp_context) {
- /* max 8 attributes plus terminator */
- int attribs[9] = {
- GLX_CONTEXT_MAJOR_VERSION_ARB,
- _this->gl_config.major_version,
- GLX_CONTEXT_MINOR_VERSION_ARB,
- _this->gl_config.minor_version,
- 0
- };
- int iattr = 4;
+ /* max 10 attributes plus terminator */
+ int attribs[11] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB,
+ _this->gl_config.major_version,
+ GLX_CONTEXT_MINOR_VERSION_ARB,
+ _this->gl_config.minor_version,
+ 0
+ };
+ int iattr = 4;
- /* SDL profile bits match GLX profile bits */
- if( _this->gl_config.profile_mask != 0 ) {
- attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
- attribs[iattr++] = _this->gl_config.profile_mask;
- }
+ /* SDL profile bits match GLX profile bits */
+ if( _this->gl_config.profile_mask != 0 ) {
+ attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+ attribs[iattr++] = _this->gl_config.profile_mask;
+ }
- /* SDL flags match GLX flags */
- if( _this->gl_config.flags != 0 ) {
- attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
- attribs[iattr++] = _this->gl_config.flags;
- }
-
- attribs[iattr++] = 0;
+ /* SDL flags match GLX flags */
+ if( _this->gl_config.flags != 0 ) {
+ attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
+ attribs[iattr++] = _this->gl_config.flags;
+ }
- /* Get a pointer to the context creation function for GL 3.0 */
- glXCreateContextAttribs =
- (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
- glXGetProcAddress((GLubyte *)
- "glXCreateContextAttribsARB");
- if (!glXCreateContextAttribs) {
- SDL_SetError("GL 3.x is not supported");
- context = temp_context;
- } else {
- int glxAttribs[64];
+ /* only set if glx extension is available */
+ if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
+ attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
+ attribs[iattr++] =
+ _this->gl_config.release_behavior ?
+ GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
+ GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
+ }
- /* Create a GL 3.x context */
- GLXFBConfig *framebuffer_config = NULL;
- int fbcount = 0;
- GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
- int screen,
- const int *attrib_list,
- int *nelements);
+ attribs[iattr++] = 0;
- glXChooseFBConfig =
- (GLXFBConfig *
- (*)(Display *, int, const int *,
- int *)) _this->gl_data->
- glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
+ /* Get a pointer to the context creation function for GL 3.0 */
+ if (!_this->gl_data->glXCreateContextAttribsARB) {
+ SDL_SetError("OpenGL 3.0 and later are not supported by this system");
+ } else {
+ int glxAttribs[64];
- X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
+ /* Create a GL 3.x context */
+ GLXFBConfig *framebuffer_config = NULL;
+ int fbcount = 0;
- if (!glXChooseFBConfig
- || !(framebuffer_config =
- glXChooseFBConfig(display,
- DefaultScreen(display), glxAttribs,
- &fbcount))) {
- SDL_SetError
- ("No good framebuffers found. GL 3.x disabled");
- context = temp_context;
- } else {
- context =
- glXCreateContextAttribs(display,
+ X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
+
+ if (!_this->gl_data->glXChooseFBConfig
+ || !(framebuffer_config =
+ _this->gl_data->glXChooseFBConfig(display,
+ DefaultScreen(display), glxAttribs,
+ &fbcount))) {
+ SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
+ } else {
+ context = _this->gl_data->glXCreateContextAttribsARB(display,
framebuffer_config[0],
share_context, True, attribs);
- _this->gl_data->glXDestroyContext(display,
- temp_context);
- }
}
}
}
--- a/src/video/x11/SDL_x11opengl.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11opengl.h Mon Apr 06 15:26:37 2015 -0300
@@ -35,11 +35,14 @@
SDL_bool HAS_GLX_EXT_visual_info;
SDL_bool HAS_GLX_EXT_swap_control_tear;
SDL_bool HAS_GLX_EXT_create_context_es2_profile;
+ SDL_bool HAS_GLX_ARB_context_flush_control;
Bool (*glXQueryExtension) (Display*,int*,int*);
void *(*glXGetProcAddress) (const GLubyte*);
XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
+ GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
+ GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
void (*glXDestroyContext) (Display*, GLXContext);
Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
void (*glXSwapBuffers) (Display*, GLXDrawable);
--- a/src/video/x11/SDL_x11video.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11video.h Mon Apr 06 15:26:37 2015 -0300
@@ -112,6 +112,7 @@
SDL_Scancode key_layout[256];
SDL_bool selection_waiting;
+ Uint32 last_mode_change_deadline;
} SDL_VideoData;
extern SDL_bool X11_UseDirectColorVisuals(void);
--- a/src/video/x11/SDL_x11window.h Sat Jan 24 23:58:07 2015 -0400
+++ b/src/video/x11/SDL_x11window.h Mon Apr 06 15:26:37 2015 -0300
@@ -27,8 +27,7 @@
video mode changes and we can respond to them by triggering more mode
changes.
*/
-#define PENDING_FOCUS_IN_TIME 200
-#define PENDING_FOCUS_OUT_TIME 200
+#define PENDING_FOCUS_TIME 200
#if SDL_VIDEO_OPENGL_EGL
#include <EGL/egl.h>
--- a/test/Makefile.in Sat Jan 24 23:58:07 2015 -0400
+++ b/test/Makefile.in Mon Apr 06 15:26:37 2015 -0300
@@ -38,6 +38,7 @@
testloadso$(EXE) \
testlock$(EXE) \
testmultiaudio$(EXE) \
+ testaudiohotplug$(EXE) \
testnative$(EXE) \
testoverlay2$(EXE) \
testplatform$(EXE) \
@@ -105,6 +106,9 @@
testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+testaudiohotplug$(EXE): $(srcdir)/testaudiohotplug.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
testatomic$(EXE): $(srcdir)/testatomic.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
--- a/test/loopwave.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/loopwave.c Mon Apr 06 15:26:37 2015 -0300
@@ -29,7 +29,6 @@
#endif
#include "SDL.h"
-#include "SDL_audio.h"
struct
{
--- a/test/loopwavequeue.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/loopwavequeue.c Mon Apr 06 15:26:37 2015 -0300
@@ -15,6 +15,10 @@
#include <stdio.h>
#include <stdlib.h>
+#ifdef __EMSCRIPTEN__
+#include <emscripten/emscripten.h>
+#endif
+
#include "SDL.h"
#if HAVE_SIGNAL_H
@@ -45,10 +49,32 @@
done = 1;
}
+void
+loop()
+{
+#ifdef __EMSCRIPTEN__
+ if (done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)) {
+ emscripten_cancel_main_loop();
+ }
+ else
+#endif
+ {
+ /* The device from SDL_OpenAudio() is always device #1. */
+ const Uint32 queued = SDL_GetQueuedAudioSize(1);
+ SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued);
+ if (queued <= 8192) { /* time to requeue the whole thing? */
+ if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) {
+ SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen);
+ } else {
+ SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError());
+ }
+ }
+ }
+}
+
int
main(int argc, char *argv[])
{
- int i;
char filename[4096];
/* Enable standard application logging */
@@ -97,25 +123,22 @@
/* Let the audio run */
SDL_PauseAudio(0);
+ done = 0;
+
/* Note that we stuff the entire audio buffer into the queue in one
shot. Most apps would want to feed it a little at a time, as it
plays, but we're going for simplicity here. */
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop(loop, 0, 1);
+#else
while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING))
{
- /* The device from SDL_OpenAudio() is always device #1. */
- const Uint32 queued = SDL_GetQueuedAudioSize(1);
- SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued);
- if (queued <= 8192) { /* time to requeue the whole thing? */
- if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) {
- SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen);
- } else {
- SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError());
- }
- }
+ loop();
SDL_Delay(100); /* let it play for awhile. */
}
+#endif
/* Clean up on signal */
SDL_CloseAudio();
--- a/test/relative_mode.markdown Sat Jan 24 23:58:07 2015 -0400
+++ b/test/relative_mode.markdown Mon Apr 06 15:26:37 2015 -0300
@@ -37,9 +37,11 @@
int main(int argc, char *argv[])
{
+ SDL_Window *win;
+
SDL_Init(SDL_INIT_VIDEO);
- SDL_Window *win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0);
+ win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0);
SDL_SetRelativeMouseMode(SDL_TRUE);
while (1)
--- a/test/testatomic.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testatomic.c Mon Apr 06 15:26:37 2015 -0300
@@ -12,9 +12,6 @@
#include <stdio.h>
#include "SDL.h"
-#include "SDL_atomic.h"
-#include "SDL_assert.h"
-#include "SDL_cpuinfo.h"
/*
Absolutely basic tests just to see if we get the expected value
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/testaudiohotplug.c Mon Apr 06 15:26:37 2015 -0300
@@ -0,0 +1,183 @@
+/*
+ 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.
+*/
+
+/* Program to test hotplugging of audio devices */
+
+#include "SDL_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef __EMSCRIPTEN__
+#include <emscripten/emscripten.h>
+#endif
+
+#include "SDL.h"
+
+static SDL_AudioSpec spec;
+static Uint8 *sound = NULL; /* Pointer to wave data */
+static Uint32 soundlen = 0; /* Length of wave data */
+
+static int posindex = 0;
+static Uint32 positions[64];
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+ SDL_Quit();
+ exit(rc);
+}
+
+void SDLCALL
+fillerup(void *_pos, Uint8 * stream, int len)
+{
+ Uint32 pos = *((Uint32 *) _pos);
+ Uint8 *waveptr;
+ int waveleft;
+
+ /* Set up the pointers */
+ waveptr = sound + pos;
+ waveleft = soundlen - pos;
+
+ /* Go! */
+ while (waveleft <= len) {
+ SDL_memcpy(stream, waveptr, waveleft);
+ stream += waveleft;
+ len -= waveleft;
+ waveptr = sound;
+ waveleft = soundlen;
+ pos = 0;
+ }
+ SDL_memcpy(stream, waveptr, len);
+ pos += len;
+ *((Uint32 *) _pos) = pos;
+}
+
+static int done = 0;
+void
+poked(int sig)
+{
+ done = 1;
+}
+
+static void
+iteration()
+{
+ SDL_Event e;
+ SDL_AudioDeviceID dev;
+ while (SDL_PollEvent(&e)) {
+ if (e.type == SDL_QUIT) {
+ done = 1;
+ } else if (e.type == SDL_AUDIODEVICEADDED) {
+ const char *name = SDL_GetAudioDeviceName(e.adevice.which, 0);
+ SDL_Log("New %s audio device: %s\n", e.adevice.iscapture ? "capture" : "output", name);
+ if (!e.adevice.iscapture) {
+ positions[posindex] = 0;
+ spec.userdata = &positions[posindex++];
+ spec.callback = fillerup;
+ dev = SDL_OpenAudioDevice(name, 0, &spec, NULL, 0);
+ if (!dev) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open '%s': %s\n", name, SDL_GetError());
+ } else {
+ SDL_Log("Opened '%s' as %u\n", name, (unsigned int) dev);
+ SDL_PauseAudioDevice(dev, 0);
+ }
+ }
+ } else if (e.type == SDL_AUDIODEVICEREMOVED) {
+ dev = (SDL_AudioDeviceID) e.adevice.which;
+ SDL_Log("%s device %u removed.\n", e.adevice.iscapture ? "capture" : "output", (unsigned int) dev);
+ SDL_CloseAudioDevice(dev);
+ }
+ }
+}
+
+#ifdef __EMSCRIPTEN__
+void
+loop()
+{
+ if(done)
+ emscripten_cancel_main_loop();
+ else
+ iteration();
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ char filename[4096];
+
+ /* Enable standard application logging */
+ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+ /* Load the SDL library */
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
+ return (1);
+ }
+
+ /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */
+ SDL_MinimizeWindow(SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0));
+
+ if (argc > 1) {
+ SDL_strlcpy(filename, argv[1], sizeof(filename));
+ } else {
+ SDL_strlcpy(filename, "sample.wav", sizeof(filename));
+ }
+ /* Load the wave file into memory */
+ if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
+ quit(1);
+ }
+
+#if HAVE_SIGNAL_H
+ /* Set the signals */
+#ifdef SIGHUP
+ signal(SIGHUP, poked);
+#endif
+ signal(SIGINT, poked);
+#ifdef SIGQUIT
+ signal(SIGQUIT, poked);
+#endif
+ signal(SIGTERM, poked);
+#endif /* HAVE_SIGNAL_H */
+
+ /* Show the list of available drivers */
+ SDL_Log("Available audio drivers:");
+ for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
+ SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));
+ }
+
+ SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
+
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop(loop, 0, 1);
+#else
+ while (!done) {
+ SDL_Delay(100);
+ iteration();
+ }
+#endif
+
+ /* Clean up on signal */
+ SDL_Quit();
+ SDL_FreeWAV(sound);
+ return (0);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/test/testerror.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testerror.c Mon Apr 06 15:26:37 2015 -0300
@@ -17,7 +17,6 @@
#include <signal.h>
#include "SDL.h"
-#include "SDL_thread.h"
static int alive = 0;
--- a/test/testfile.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testfile.c Mon Apr 06 15:26:37 2015 -0300
@@ -22,7 +22,6 @@
#endif
#include "SDL.h"
-#include "SDL_endian.h"
#include <stdio.h>
--- a/test/testgamecontroller.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testgamecontroller.c Mon Apr 06 15:26:37 2015 -0300
@@ -163,6 +163,10 @@
const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
char *title = (char *)SDL_malloc(titlelen);
SDL_Window *window = NULL;
+
+ retval = SDL_FALSE;
+ done = SDL_FALSE;
+
if (title) {
SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
}
@@ -219,6 +223,10 @@
#endif
SDL_DestroyRenderer(screen);
+ screen = NULL;
+ background = NULL;
+ button = NULL;
+ axis = NULL;
SDL_DestroyWindow(window);
return retval;
}
--- a/test/testhaptic.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testhaptic.c Mon Apr 06 15:26:37 2015 -0300
@@ -22,8 +22,6 @@
#ifndef SDL_HAPTIC_DISABLED
-#include "SDL_haptic.h"
-
static SDL_Haptic *haptic;
--- a/test/testhotplug.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testhotplug.c Mon Apr 06 15:26:37 2015 -0300
@@ -17,7 +17,6 @@
#include <string.h>
#include "SDL.h"
-#include "SDL_haptic.h"
#if !defined SDL_JOYSTICK_DISABLED && !defined SDL_HAPTIC_DISABLED
--- a/test/testjoystick.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testjoystick.c Mon Apr 06 15:26:37 2015 -0300
@@ -56,6 +56,12 @@
while (SDL_PollEvent(&event)) {
switch (event.type) {
+
+ case SDL_JOYDEVICEREMOVED:
+ SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
+ SDL_Log("Our instance ID is %d\n", (int) SDL_JoystickInstanceID(joystick));
+ break;
+
case SDL_JOYAXISMOTION:
SDL_Log("Joystick %d axis %d value: %d\n",
event.jaxis.which,
@@ -177,6 +183,8 @@
SDL_Window *window = NULL;
const char *name = NULL;
+ retval = SDL_FALSE;
+ done = SDL_FALSE;
/* Create a window to display joystick axis position */
window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
@@ -217,6 +225,7 @@
#endif
SDL_DestroyRenderer(screen);
+ screen = NULL;
SDL_DestroyWindow(window);
return retval;
}
--- a/test/testlock.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testlock.c Mon Apr 06 15:26:37 2015 -0300
@@ -19,8 +19,6 @@
#include <stdlib.h> /* for atexit() */
#include "SDL.h"
-#include "SDL_mutex.h"
-#include "SDL_thread.h"
static SDL_mutex *mutex = NULL;
static SDL_threadID mainthread;
--- a/test/testmessage.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testmessage.c Mon Apr 06 15:26:37 2015 -0300
@@ -17,7 +17,6 @@
#include <signal.h>
#include "SDL.h"
-#include "SDL_thread.h"
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
--- a/test/testplatform.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testplatform.c Mon Apr 06 15:26:37 2015 -0300
@@ -13,9 +13,6 @@
#include <stdio.h>
#include "SDL.h"
-#include "SDL_endian.h"
-#include "SDL_cpuinfo.h"
-#include "SDL_assert.h"
/*
* Watcom C flags these as Warning 201: "Unreachable code" if you just
@@ -170,7 +167,7 @@
#endif
{
- const SDL_assert_data *item = SDL_GetAssertionReport();
+ const SDL_AssertData *item = SDL_GetAssertionReport();
while (item) {
SDL_Log("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
item->condition, item->function, item->filename,
--- a/test/testrelative.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testrelative.c Mon Apr 06 15:26:37 2015 -0300
@@ -49,12 +49,20 @@
}
}
for (i = 0; i < state->num_windows; ++i) {
+ SDL_Rect viewport;
SDL_Renderer *renderer = state->renderers[i];
if (state->windows[i] == NULL)
continue;
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
+ /* Wrap the cursor rectangle at the screen edges to keep it visible */
+ SDL_RenderGetViewport(renderer, &viewport);
+ if (rect.x < viewport.x) rect.x += viewport.w;
+ if (rect.y < viewport.y) rect.y += viewport.h;
+ if (rect.x > viewport.x + viewport.w) rect.x -= viewport.w;
+ if (rect.y > viewport.y + viewport.h) rect.y -= viewport.h;
+
DrawRects(renderer, &rect);
SDL_RenderPresent(renderer);
--- a/test/testrumble.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testrumble.c Mon Apr 06 15:26:37 2015 -0300
@@ -33,8 +33,6 @@
#ifndef SDL_HAPTIC_DISABLED
-#include "SDL_haptic.h"
-
static SDL_Haptic *haptic;
--- a/test/testsem.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testsem.c Mon Apr 06 15:26:37 2015 -0300
@@ -17,7 +17,6 @@
#include <signal.h>
#include "SDL.h"
-#include "SDL_thread.h"
#define NUM_THREADS 10
--- a/test/testthread.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/testthread.c Mon Apr 06 15:26:37 2015 -0300
@@ -17,7 +17,6 @@
#include <signal.h>
#include "SDL.h"
-#include "SDL_thread.h"
static SDL_TLSID tls;
static int alive = 0;
--- a/test/torturethread.c Sat Jan 24 23:58:07 2015 -0400
+++ b/test/torturethread.c Mon Apr 06 15:26:37 2015 -0300
@@ -18,7 +18,6 @@
#include <string.h>
#include "SDL.h"
-#include "SDL_thread.h"
#define NUMTHREADS 10