Bladeren bron

Merge branch 'development' into osxDedeprecation

Areloch 8 jaren geleden
bovenliggende
commit
8f420893eb
100 gewijzigde bestanden met toevoegingen van 5197 en 2172 verwijderingen
  1. 1 1
      Engine/lib/sdl/Android.mk
  2. 134 49
      Engine/lib/sdl/CMakeLists.txt
  3. 9 2
      Engine/lib/sdl/Makefile.in
  4. 1 1
      Engine/lib/sdl/Makefile.pandora
  5. 1 0
      Engine/lib/sdl/Makefile.psp
  6. 5 5
      Engine/lib/sdl/Makefile.wiz
  7. 2 2
      Engine/lib/sdl/README-SDL.txt
  8. 1 1
      Engine/lib/sdl/SDL2.spec
  9. 2 2
      Engine/lib/sdl/VisualC.html
  10. 0 4
      Engine/lib/sdl/VisualC/clean.sh
  11. 63 0
      Engine/lib/sdl/WhatsNew.txt
  12. 3 3
      Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
  13. 72 45
      Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
  14. 2 2
      Engine/lib/sdl/Xcode/SDL/pkg-support/SDL.info
  15. 6 0
      Engine/lib/sdl/autogen.sh
  16. 4 4
      Engine/lib/sdl/build-scripts/androidbuild.sh
  17. 3 3
      Engine/lib/sdl/build-scripts/checker-buildbot.sh
  18. 4 3
      Engine/lib/sdl/build-scripts/emscripten-buildbot.sh
  19. 3 3
      Engine/lib/sdl/build-scripts/g++-fat.sh
  20. 4 4
      Engine/lib/sdl/build-scripts/gcc-fat.sh
  21. 1 3
      Engine/lib/sdl/build-scripts/install-sh
  22. 89 9
      Engine/lib/sdl/build-scripts/strip_fPIC.sh
  23. 272 17
      Engine/lib/sdl/configure
  24. 180 20
      Engine/lib/sdl/configure.in
  25. 6 0
      Engine/lib/sdl/debian/changelog
  26. 0 11
      Engine/lib/sdl/debian/copyright
  27. 1 0
      Engine/lib/sdl/debian/libsdl2-dev.install
  28. 10 10
      Engine/lib/sdl/debian/rules
  29. 81 14
      Engine/lib/sdl/include/SDL_audio.h
  30. 2 0
      Engine/lib/sdl/include/SDL_config.h.cmake
  31. 4 0
      Engine/lib/sdl/include/SDL_config.h.in
  32. 3 0
      Engine/lib/sdl/include/SDL_config_android.h
  33. 1 5
      Engine/lib/sdl/include/SDL_config_iphoneos.h
  34. 6 2
      Engine/lib/sdl/include/SDL_events.h
  35. 3 3
      Engine/lib/sdl/include/SDL_gamecontroller.h
  36. 16 16
      Engine/lib/sdl/include/SDL_haptic.h
  37. 98 14
      Engine/lib/sdl/include/SDL_hints.h
  38. 1 1
      Engine/lib/sdl/include/SDL_joystick.h
  39. 1 1
      Engine/lib/sdl/include/SDL_keyboard.h
  40. 1 1
      Engine/lib/sdl/include/SDL_main.h
  41. 4 2
      Engine/lib/sdl/include/SDL_mouse.h
  42. 1 0
      Engine/lib/sdl/include/SDL_opengles.h
  43. 2 0
      Engine/lib/sdl/include/SDL_opengles2.h
  44. 14 0
      Engine/lib/sdl/include/SDL_pixels.h
  45. 9 5
      Engine/lib/sdl/include/SDL_platform.h
  46. 26 1
      Engine/lib/sdl/include/SDL_render.h
  47. 2 2
      Engine/lib/sdl/include/SDL_revision.h
  48. 6 6
      Engine/lib/sdl/include/SDL_rwops.h
  49. 7 3
      Engine/lib/sdl/include/SDL_stdinc.h
  50. 10 0
      Engine/lib/sdl/include/SDL_surface.h
  51. 21 1
      Engine/lib/sdl/include/SDL_syswm.h
  52. 1 1
      Engine/lib/sdl/include/SDL_version.h
  53. 124 9
      Engine/lib/sdl/include/SDL_video.h
  54. 1 0
      Engine/lib/sdl/sdl2-config.cmake.in
  55. 43 11
      Engine/lib/sdl/sdl2.m4
  56. 12 10
      Engine/lib/sdl/src/SDL.c
  57. 7 0
      Engine/lib/sdl/src/SDL_error.c
  58. 13 0
      Engine/lib/sdl/src/SDL_hints.c
  59. 4 4
      Engine/lib/sdl/src/SDL_log.c
  60. 382 169
      Engine/lib/sdl/src/audio/SDL_audio.c
  61. 0 3
      Engine/lib/sdl/src/audio/SDL_audio_c.h
  62. 49 1
      Engine/lib/sdl/src/audio/SDL_mixer.c
  63. 15 9
      Engine/lib/sdl/src/audio/SDL_sysaudio.h
  64. 1 1
      Engine/lib/sdl/src/audio/SDL_wave.c
  65. 374 76
      Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c
  66. 73 36
      Engine/lib/sdl/src/audio/android/SDL_androidaudio.c
  67. 0 2
      Engine/lib/sdl/src/audio/android/SDL_androidaudio.h
  68. 7 26
      Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c
  69. 110 55
      Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c
  70. 13 3
      Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h
  71. 348 197
      Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.m
  72. 186 98
      Engine/lib/sdl/src/audio/directsound/SDL_directsound.c
  73. 2 1
      Engine/lib/sdl/src/audio/directsound/SDL_directsound.h
  74. 96 63
      Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c
  75. 2 3
      Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h
  76. 43 31
      Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c
  77. 22 5
      Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c
  78. 225 61
      Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
  79. 6 16
      Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c
  80. 11 28
      Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c
  81. 9 15
      Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc
  82. 17 20
      Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c
  83. 116 50
      Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c
  84. 6 18
      Engine/lib/sdl/src/audio/paudio/SDL_paudio.c
  85. 22 41
      Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c
  86. 132 59
      Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c
  87. 3 0
      Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h
  88. 27 65
      Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c
  89. 1 1
      Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h
  90. 7 24
      Engine/lib/sdl/src/audio/sdlgenaudiocvt.pl
  91. 7 14
      Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c
  92. 121 63
      Engine/lib/sdl/src/audio/winmm/SDL_winmm.c
  93. 30 54
      Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c
  94. 242 90
      Engine/lib/sdl/src/core/android/SDL_android.c
  95. 4 2
      Engine/lib/sdl/src/core/android/SDL_android.h
  96. 1 1
      Engine/lib/sdl/src/core/linux/SDL_dbus.c
  97. 491 435
      Engine/lib/sdl/src/core/linux/SDL_evdev.c
  98. 0 20
      Engine/lib/sdl/src/core/linux/SDL_evdev.h
  99. 553 0
      Engine/lib/sdl/src/core/linux/SDL_fcitx.c
  100. 40 0
      Engine/lib/sdl/src/core/linux/SDL_fcitx.h

+ 1 - 1
Engine/lib/sdl/Android.mk

@@ -1,7 +1,7 @@
 
 
 Bugs are now managed in the SDL bug tracker, here:
 Bugs are now managed in the SDL bug tracker, here:
 
 
-    http://bugzilla.libsdl.org/
+    https://bugzilla.libsdl.org/
 
 
 You may report bugs there, and search to see if a given issue has already
 You may report bugs there, and search to see if a given issue has already
  been reported, discussed, and maybe even fixed.
  been reported, discussed, and maybe even fixed.

+ 134 - 49
Engine/lib/sdl/CMakeLists.txt

@@ -2,8 +2,19 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
   message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL source code and call cmake from there")
   message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL source code and call cmake from there")
 endif()
 endif()
 
 
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.5)
 project(SDL2 C)
 project(SDL2 C)
+
+# !!! FIXME: this should probably do "MACOSX_RPATH ON" as a target property
+# !!! FIXME:  for the SDL2 shared library (so you get an
+# !!! FIXME:  install_name ("soname") of "@rpath/libSDL-whatever.dylib"
+# !!! FIXME:  instead of "/usr/local/lib/libSDL-whatever.dylib"), but I'm
+# !!! FIXME:  punting for now and leaving the existing behavior. Until this
+# !!! FIXME:  properly resolved, this line silences a warning in CMake 3.0+.
+# !!! FIXME:  remove it and this comment entirely once the problem is
+# !!! FIXME:  properly resolved.
+#cmake_policy(SET CMP0042 OLD)
+
 include(CheckFunctionExists)
 include(CheckFunctionExists)
 include(CheckLibraryExists)
 include(CheckLibraryExists)
 include(CheckIncludeFiles)
 include(CheckIncludeFiles)
@@ -15,6 +26,7 @@ include(CheckTypeSize)
 include(CheckStructHasMember)
 include(CheckStructHasMember)
 include(CMakeDependentOption)
 include(CMakeDependentOption)
 include(FindPkgConfig)
 include(FindPkgConfig)
+include(GNUInstallDirs)
 set(CMAKE_MODULE_PATH "${SDL2_SOURCE_DIR}/cmake")
 set(CMAKE_MODULE_PATH "${SDL2_SOURCE_DIR}/cmake")
 include(${SDL2_SOURCE_DIR}/cmake/macros.cmake)
 include(${SDL2_SOURCE_DIR}/cmake/macros.cmake)
 include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
 include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
@@ -29,9 +41,9 @@ include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
 # set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
 # set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MAJOR_VERSION 2)
 set(SDL_MINOR_VERSION 0)
 set(SDL_MINOR_VERSION 0)
-set(SDL_MICRO_VERSION 4)
-set(SDL_INTERFACE_AGE 0)
-set(SDL_BINARY_AGE 4)
+set(SDL_MICRO_VERSION 5)
+set(SDL_INTERFACE_AGE 1)
+set(SDL_BINARY_AGE 5)
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
 
 
 # Calculate a libtool-like version number
 # Calculate a libtool-like version number
@@ -147,8 +159,10 @@ endif()
 
 
 # Default flags, if not set otherwise
 # Default flags, if not set otherwise
 if("$ENV{CFLAGS}" STREQUAL "")
 if("$ENV{CFLAGS}" STREQUAL "")
-  if(USE_GCC OR USE_CLANG)
-    set(CMAKE_C_FLAGS "-g -O3")
+  if(CMAKE_BUILD_TYPE STREQUAL "")
+    if(USE_GCC OR USE_CLANG)
+      set(CMAKE_C_FLAGS "-g -O3")
+    endif()
   endif()
   endif()
 else()
 else()
   set(CMAKE_C_FLAGS "$ENV{CFLAGS}")
   set(CMAKE_C_FLAGS "$ENV{CFLAGS}")
@@ -183,8 +197,8 @@ endif()
 set(SDL_LIBS "-lSDL2")
 set(SDL_LIBS "-lSDL2")
 set(SDL_CFLAGS "")
 set(SDL_CFLAGS "")
 
 
-# Emscripten toolchain has a nonempty default value for this, and the checks
-# in this file need to change that, so remember the original value, and
+# Emscripten toolchain has a nonempty default value for this, and the checks 
+# in this file need to change that, so remember the original value, and 
 # restore back to that afterwards. For check_function_exists() to work in
 # restore back to that afterwards. For check_function_exists() to work in
 # Emscripten, this value must be at its default value.
 # Emscripten, this value must be at its default value.
 set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
 set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
@@ -192,7 +206,7 @@ set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
 if(CYGWIN)
 if(CYGWIN)
   # We build SDL on cygwin without the UNIX emulation layer
   # We build SDL on cygwin without the UNIX emulation layer
   include_directories("-I/usr/include/mingw")
   include_directories("-I/usr/include/mingw")
-  set(CMAKE_REQUIRED_FLAGS "-mno-cygwin")
+  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mno-cygwin")
   check_c_source_compiles("int main(int argc, char **argv) {}"
   check_c_source_compiles("int main(int argc, char **argv) {}"
     HAVE_GCC_NO_CYGWIN)
     HAVE_GCC_NO_CYGWIN)
   set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
@@ -212,7 +226,7 @@ include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include)
 set(OPT_DEF_ASM TRUE)
 set(OPT_DEF_ASM TRUE)
 if(EMSCRIPTEN)
 if(EMSCRIPTEN)
   # Set up default values for the currently supported set of subsystems:
   # Set up default values for the currently supported set of subsystems:
-  # Emscripten/Javascript does not have assembly support, a dynamic library
+  # Emscripten/Javascript does not have assembly support, a dynamic library 
   # loading architecture, low-level CPU inspection or multithreading.
   # loading architecture, low-level CPU inspection or multithreading.
   set(OPT_DEF_ASM FALSE)
   set(OPT_DEF_ASM FALSE)
   set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
   set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
@@ -299,6 +313,8 @@ set_option(VIDEO_VIVANTE       "Use Vivante EGL video driver" ${UNIX_SYS})
 set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
 set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
 set(SDL_STATIC ON CACHE BOOL "Build a static version of the library")
 set(SDL_STATIC ON CACHE BOOL "Build a static version of the library")
 
 
+dep_option(SDL_STATIC_PIC      "Static version of the library should be built with Position Independent Code" OFF "SDL_STATIC" OFF)
+
 # General source files
 # General source files
 file(GLOB SOURCE_FILES
 file(GLOB SOURCE_FILES
   ${SDL2_SOURCE_DIR}/src/*.c
   ${SDL2_SOURCE_DIR}/src/*.c
@@ -334,6 +350,24 @@ set(HAVE_ASSERTIONS ${ASSERTIONS})
 
 
 # Compiler option evaluation
 # Compiler option evaluation
 if(USE_GCC OR USE_CLANG)
 if(USE_GCC OR USE_CLANG)
+  # Check for -Wall first, so later things can override pieces of it.
+  check_c_compiler_flag(-Wall HAVE_GCC_WALL)
+  if(HAVE_GCC_WALL)
+    list(APPEND EXTRA_CFLAGS "-Wall")
+    if(HAIKU)
+      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
+    endif()
+  endif()
+
+  check_c_compiler_flag(-Wdeclaration-after-statement HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
+  if(HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
+    check_c_compiler_flag(-Werror=declaration-after-statement HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
+    if(HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
+      list(APPEND EXTRA_CFLAGS "-Werror=declaration-after-statement")
+    endif()
+    list(APPEND EXTRA_CFLAGS "-Wdeclaration-after-statement")
+  endif()
+
   if(DEPENDENCY_TRACKING)
   if(DEPENDENCY_TRACKING)
     check_c_source_compiles("
     check_c_source_compiles("
         #if !defined(__GNUC__) || __GNUC__ < 3
         #if !defined(__GNUC__) || __GNUC__ < 3
@@ -375,26 +409,16 @@ if(USE_GCC OR USE_CLANG)
   endif()
   endif()
   set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
   set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
 
 
-  check_c_compiler_flag(-Wall HAVE_GCC_WALL)
-  if(HAVE_GCC_WALL)
-    list(APPEND EXTRA_CFLAGS "-Wall")
-    if(HAIKU)
-      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
-    endif()
-  endif()
   check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
   check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
   if(HAVE_GCC_WSHADOW)
   if(HAVE_GCC_WSHADOW)
     list(APPEND EXTRA_CFLAGS "-Wshadow")
     list(APPEND EXTRA_CFLAGS "-Wshadow")
   endif()
   endif()
 
 
-  # --no-undefined is unsupported with clang
-  if(NOT USE_CLANG)
-    set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
-    check_c_compiler_flag("" HAVE_NO_UNDEFINED)
-    set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
-    if(HAVE_NO_UNDEFINED)
-      list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
-    endif()
+  set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
+  check_c_compiler_flag("" HAVE_NO_UNDEFINED)
+  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+  if(HAVE_NO_UNDEFINED)
+    list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
   endif()
   endif()
 endif()
 endif()
 
 
@@ -773,6 +797,16 @@ if(EMSCRIPTEN)
     set(SOURCE_FILES ${SOURCE_FILES} ${EM_POWER_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${EM_POWER_SOURCES})
     set(HAVE_SDL_POWER TRUE)
     set(HAVE_SDL_POWER TRUE)
   endif()
   endif()
+  if(SDL_TIMERS)
+    set(SDL_TIMER_UNIX 1)
+    file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
+    set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES})
+    set(HAVE_SDL_TIMERS TRUE)
+
+    if(CLOCK_GETTIME)
+      set(HAVE_CLOCK_GETTIME 1)
+    endif()
+  endif()
   if(SDL_VIDEO)
   if(SDL_VIDEO)
     set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1)
     set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1)
     file(GLOB EM_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/emscripten/*.c)
     file(GLOB EM_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/emscripten/*.c)
@@ -839,7 +873,7 @@ elseif(UNIX AND NOT APPLE)
         #include <linux/kd.h>
         #include <linux/kd.h>
         #include <linux/keyboard.h>
         #include <linux/keyboard.h>
 
 
-        int main(int argc, char **argv)
+        int main(int argc, char **argv) 
         {
         {
             struct kbentry kbe;
             struct kbentry kbe;
             kbe.kb_table = KG_CTRL;
             kbe.kb_table = KG_CTRL;
@@ -866,8 +900,24 @@ elseif(UNIX AND NOT APPLE)
 
 
     check_include_file("libudev.h" HAVE_LIBUDEV_H)
     check_include_file("libudev.h" HAVE_LIBUDEV_H)
 
 
-    # !!! FIXME: this needs pkg-config to find the include path, I think.
-    check_include_file("dbus/dbus.h" HAVE_DBUS_DBUS_H)
+    if(PKG_CONFIG_FOUND)
+      pkg_search_module(DBUS dbus-1 dbus)
+      if(DBUS_FOUND)
+        set(HAVE_DBUS_DBUS_H TRUE)
+        include_directories(${DBUS_INCLUDE_DIRS})
+        list(APPEND EXTRA_LIBS ${DBUS_LIBRARIES})
+      endif()
+
+      pkg_search_module(IBUS ibus-1.0 ibus)
+      if(IBUS_FOUND)
+        set(HAVE_IBUS_IBUS_H TRUE)
+        include_directories(${IBUS_INCLUDE_DIRS})
+        list(APPEND EXTRA_LIBS ${IBUS_LIBRARIES})
+      endif()
+    endif()
+
+    check_include_file("fcitx/frontend.h" HAVE_FCITX_FRONTEND_H)
+
   endif()
   endif()
 
 
   if(INPUT_TSLIB)
   if(INPUT_TSLIB)
@@ -936,7 +986,14 @@ elseif(UNIX AND NOT APPLE)
   if(RPATH)
   if(RPATH)
     set(SDL_RLD_FLAGS "")
     set(SDL_RLD_FLAGS "")
     if(BSDI OR FREEBSD OR LINUX OR NETBSD)
     if(BSDI OR FREEBSD OR LINUX OR NETBSD)
-      set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}")
+      set(CMAKE_REQUIRED_FLAGS "-Wl,--enable-new-dtags")
+      check_c_compiler_flag("" HAVE_ENABLE_NEW_DTAGS)
+      set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+      if(HAVE_ENABLE_NEW_DTAGS)
+        set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir} -Wl,--enable-new-dtags")
+      else()
+        set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}")
+      endif()
     elseif(SOLARIS)
     elseif(SOLARIS)
       set(SDL_RLD_FLAGS "-R\${libdir}")
       set(SDL_RLD_FLAGS "-R\${libdir}")
     endif()
     endif()
@@ -1108,7 +1165,7 @@ elseif(WINDOWS)
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     if(HAVE_DINPUT_H)
     if(HAVE_DINPUT_H)
       set(SDL_JOYSTICK_DINPUT 1)
       set(SDL_JOYSTICK_DINPUT 1)
-      list(APPEND EXTRA_LIBS dinput8 dxguid)
+      list(APPEND EXTRA_LIBS dinput8)
       if(CMAKE_COMPILER_IS_MINGW)
       if(CMAKE_COMPILER_IS_MINGW)
         list(APPEND EXTRA_LIBS dxerr8)
         list(APPEND EXTRA_LIBS dxerr8)
       elseif (NOT USE_WINSDK_DIRECTX)
       elseif (NOT USE_WINSDK_DIRECTX)
@@ -1166,16 +1223,20 @@ elseif(APPLE)
 
 
   if(SDL_AUDIO)
   if(SDL_AUDIO)
     set(SDL_AUDIO_DRIVER_COREAUDIO 1)
     set(SDL_AUDIO_DRIVER_COREAUDIO 1)
-    file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/coreaudio/*.c)
+    file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/coreaudio/*.m)
     set(SOURCE_FILES ${SOURCE_FILES} ${AUDIO_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${AUDIO_SOURCES})
     set(HAVE_SDL_AUDIO TRUE)
     set(HAVE_SDL_AUDIO TRUE)
     set(SDL_FRAMEWORK_COREAUDIO 1)
     set(SDL_FRAMEWORK_COREAUDIO 1)
-    set(SDL_FRAMEWORK_AUDIOUNIT 1)
+    set(SDL_FRAMEWORK_AUDIOTOOLBOX 1)
   endif()
   endif()
 
 
   if(SDL_JOYSTICK)
   if(SDL_JOYSTICK)
     set(SDL_JOYSTICK_IOKIT 1)
     set(SDL_JOYSTICK_IOKIT 1)
-    file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
+    if (IOS)
+      file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m)
+    else()
+      file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
+    endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
     set(HAVE_SDL_JOYSTICK TRUE)
     set(HAVE_SDL_JOYSTICK TRUE)
     set(SDL_FRAMEWORK_IOKIT 1)
     set(SDL_FRAMEWORK_IOKIT 1)
@@ -1184,7 +1245,12 @@ elseif(APPLE)
 
 
   if(SDL_HAPTIC)
   if(SDL_HAPTIC)
     set(SDL_HAPTIC_IOKIT 1)
     set(SDL_HAPTIC_IOKIT 1)
-    file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
+    if (IOS)
+      file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/dummy/*.c)
+      set(SDL_HAPTIC_DUMMY 1)
+    else()
+      file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
+    endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
     set(HAVE_SDL_HAPTIC TRUE)
     set(HAVE_SDL_HAPTIC TRUE)
     set(SDL_FRAMEWORK_IOKIT 1)
     set(SDL_FRAMEWORK_IOKIT 1)
@@ -1196,7 +1262,11 @@ elseif(APPLE)
 
 
   if(SDL_POWER)
   if(SDL_POWER)
     set(SDL_POWER_MACOSX 1)
     set(SDL_POWER_MACOSX 1)
-    file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
+    if (IOS)
+      file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
+    else()
+      file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
+    endif()
     set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
     set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
     set(HAVE_SDL_POWER TRUE)
     set(HAVE_SDL_POWER TRUE)
     set(SDL_FRAMEWORK_CARBON 1)
     set(SDL_FRAMEWORK_CARBON 1)
@@ -1243,19 +1313,25 @@ elseif(APPLE)
     find_library(COREAUDIO CoreAudio)
     find_library(COREAUDIO CoreAudio)
     list(APPEND EXTRA_LIBS ${COREAUDIO})
     list(APPEND EXTRA_LIBS ${COREAUDIO})
   endif()
   endif()
-  if(SDL_FRAMEWORK_AUDIOUNIT)
-    find_library(AUDIOUNIT AudioUnit)
-    list(APPEND EXTRA_LIBS ${AUDIOUNIT})
+  if(SDL_FRAMEWORK_AUDIOTOOLBOX)
+    find_library(AUDIOTOOLBOX AudioToolbox)
+    list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX})
   endif()
   endif()
 
 
   # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
   # iOS hack needed - http://code.google.com/p/ios-cmake/ ?
   if(SDL_VIDEO)
   if(SDL_VIDEO)
-    CheckCOCOA()
-    if(VIDEO_OPENGL)
-      set(SDL_VIDEO_OPENGL 1)
-      set(SDL_VIDEO_OPENGL_CGL 1)
-      set(SDL_VIDEO_RENDER_OGL 1)
-      set(HAVE_VIDEO_OPENGL TRUE)
+    if (IOS)
+      set(SDL_VIDEO_DRIVER_UIKIT 1)
+      file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
+      set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+    else()
+      CheckCOCOA()
+      if(VIDEO_OPENGL)
+        set(SDL_VIDEO_OPENGL 1)
+        set(SDL_VIDEO_OPENGL_CGL 1)
+        set(SDL_VIDEO_RENDER_OGL 1)
+        set(HAVE_VIDEO_OPENGL TRUE)
+      endif()
     endif()
     endif()
   endif()
   endif()
 
 
@@ -1442,6 +1518,9 @@ message(STATUS " EXTRA_LIBS:    ${EXTRA_LIBS}")
 message(STATUS "")
 message(STATUS "")
 message(STATUS " Build Shared Library: ${SDL_SHARED}")
 message(STATUS " Build Shared Library: ${SDL_SHARED}")
 message(STATUS " Build Static Library: ${SDL_STATIC}")
 message(STATUS " Build Static Library: ${SDL_STATIC}")
+if(SDL_STATIC)
+    message(STATUS " Build Static Library with Position Independent Code: ${SDL_STATIC_PIC}")
+endif()
 message(STATUS "")
 message(STATUS "")
 if(UNIX)
 if(UNIX)
   message(STATUS "If something was not detected, although the libraries")
   message(STATUS "If something was not detected, although the libraries")
@@ -1458,7 +1537,7 @@ add_library(SDL2main STATIC ${SDLMAIN_SOURCES})
 set(_INSTALL_LIBS "SDL2main")
 set(_INSTALL_LIBS "SDL2main")
 
 
 if(SDL_SHARED)
 if(SDL_SHARED)
-  add_library(SDL2 SHARED ${SOURCE_FILES})
+  add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
   if(UNIX)
   if(UNIX)
     set_target_properties(SDL2 PROPERTIES
     set_target_properties(SDL2 PROPERTIES
       VERSION ${LT_VERSION}
       VERSION ${LT_VERSION}
@@ -1484,6 +1563,7 @@ if(SDL_STATIC)
   set (BUILD_SHARED_LIBS FALSE)
   set (BUILD_SHARED_LIBS FALSE)
   add_library(SDL2-static STATIC ${SOURCE_FILES})
   add_library(SDL2-static STATIC ${SOURCE_FILES})
   set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2")
   set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2")
+  set_target_properties(SDL2-static PROPERTIES POSITION_INDEPENDENT_CODE ${SDL_STATIC_PIC})
   if(MSVC)
   if(MSVC)
     set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
     set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
     set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
     set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
@@ -1510,12 +1590,17 @@ endforeach()
 list(APPEND INCLUDE_FILES ${BIN_INCLUDE_FILES})
 list(APPEND INCLUDE_FILES ${BIN_INCLUDE_FILES})
 install(FILES ${INCLUDE_FILES} DESTINATION include/SDL2)
 install(FILES ${INCLUDE_FILES} DESTINATION include/SDL2)
 
 
-if(NOT WINDOWS OR CYGWIN)
+if(NOT (WINDOWS OR CYGWIN))
   if(SDL_SHARED)
   if(SDL_SHARED)
+    if (APPLE)
+        set(SOEXT "dylib")
+    else()
+        set(SOEXT "so")
+    endif()
     install(CODE "
     install(CODE "
       execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
       execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
-      \"libSDL2-2.0.so\" \"libSDL2.so\")")
-    install(FILES ${SDL2_BINARY_DIR}/libSDL2.so DESTINATION "lib${LIB_SUFFIX}")
+      \"libSDL2-2.0.${SOEXT}\" \"libSDL2.${SOEXT}\")")
+    install(FILES ${SDL2_BINARY_DIR}/libSDL2.${SOEXT} DESTINATION "lib${LIB_SUFFIX}")
   endif()
   endif()
   if(FREEBSD)
   if(FREEBSD)
     # FreeBSD uses ${PREFIX}/libdata/pkgconfig
     # FreeBSD uses ${PREFIX}/libdata/pkgconfig
@@ -1526,7 +1611,7 @@ if(NOT WINDOWS OR CYGWIN)
   endif()
   endif()
   install(PROGRAMS ${SDL2_BINARY_DIR}/sdl2-config DESTINATION bin)
   install(PROGRAMS ${SDL2_BINARY_DIR}/sdl2-config DESTINATION bin)
   # TODO: what about the .spec file? Is it only needed for RPM creation?
   # TODO: what about the .spec file? Is it only needed for RPM creation?
-  install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "share/aclocal")
+  install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/aclocal")
 endif()
 endif()
 
 
 ##### Uninstall target #####
 ##### Uninstall target #####

+ 9 - 2
Engine/lib/sdl/Makefile.in

@@ -3,6 +3,7 @@
 top_builddir = .
 top_builddir = .
 srcdir  = @srcdir@
 srcdir  = @srcdir@
 objects = build
 objects = build
+gen = gen
 prefix = @prefix@
 prefix = @prefix@
 exec_prefix = @exec_prefix@
 exec_prefix = @exec_prefix@
 bindir	= @bindir@
 bindir	= @bindir@
@@ -31,6 +32,8 @@ WINDRES	= @WINDRES@
 
 
 TARGET  = libSDL2.la
 TARGET  = libSDL2.la
 OBJECTS = @OBJECTS@
 OBJECTS = @OBJECTS@
+GEN_HEADERS = @GEN_HEADERS@
+GEN_OBJECTS = @GEN_OBJECTS@
 VERSION_OBJECTS = @VERSION_OBJECTS@
 VERSION_OBJECTS = @VERSION_OBJECTS@
 
 
 SDLMAIN_TARGET = libSDL2main.a
 SDLMAIN_TARGET = libSDL2main.a
@@ -39,6 +42,8 @@ SDLMAIN_OBJECTS = @SDLMAIN_OBJECTS@
 SDLTEST_TARGET = libSDL2_test.a
 SDLTEST_TARGET = libSDL2_test.a
 SDLTEST_OBJECTS = @SDLTEST_OBJECTS@
 SDLTEST_OBJECTS = @SDLTEST_OBJECTS@
 
 
+WAYLAND_SCANNER = @WAYLAND_SCANNER@
+
 SRC_DIST = *.txt acinclude Android.mk autogen.sh android-project build-scripts cmake cmake_uninstall.cmake.in configure configure.in debian docs include Makefile.* sdl2-config.cmake.in sdl2-config.in sdl2.m4 sdl2.pc.in SDL2.spec.in src test VisualC.html VisualC VisualC-WinRT Xcode Xcode-iOS
 SRC_DIST = *.txt acinclude Android.mk autogen.sh android-project build-scripts cmake cmake_uninstall.cmake.in configure configure.in debian docs include Makefile.* sdl2-config.cmake.in sdl2-config.in sdl2.m4 sdl2.pc.in SDL2.spec.in src test VisualC.html VisualC VisualC-WinRT Xcode Xcode-iOS
 GEN_DIST = SDL2.spec
 GEN_DIST = SDL2.spec
 
 
@@ -48,6 +53,7 @@ RUN_CMD_CC     = @echo "  CC    " $@;
 RUN_CMD_CXX    = @echo "  CXX   " $@;
 RUN_CMD_CXX    = @echo "  CXX   " $@;
 RUN_CMD_LTLINK = @echo "  LTLINK" $@;
 RUN_CMD_LTLINK = @echo "  LTLINK" $@;
 RUN_CMD_RANLIB = @echo "  RANLIB" $@;
 RUN_CMD_RANLIB = @echo "  RANLIB" $@;
+RUN_CMD_GEN    = @echo "  GEN   " $@;
 LIBTOOL += --quiet
 LIBTOOL += --quiet
 endif
 endif
 
 
@@ -137,8 +143,8 @@ update-revision:
 
 
 .PHONY: all update-revision install install-bin install-hdrs install-lib install-data uninstall uninstall-bin uninstall-hdrs uninstall-lib uninstall-data clean distclean dist $(OBJECTS:.lo=.d)
 .PHONY: all update-revision install install-bin install-hdrs install-lib install-data uninstall uninstall-bin uninstall-hdrs uninstall-lib uninstall-data clean distclean dist $(OBJECTS:.lo=.d)
 
 
-$(objects)/$(TARGET): $(OBJECTS) $(VERSION_OBJECTS)
-	$(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
+$(objects)/$(TARGET): $(GEN_HEADERS) $(GEN_OBJECTS) $(OBJECTS) $(VERSION_OBJECTS)
+	$(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(GEN_OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
 
 
 $(objects)/$(SDLMAIN_TARGET): $(SDLMAIN_OBJECTS)
 $(objects)/$(SDLMAIN_TARGET): $(SDLMAIN_OBJECTS)
 	$(RUN_CMD_AR)$(AR) cru $@ $(SDLMAIN_OBJECTS)
 	$(RUN_CMD_AR)$(AR) cru $@ $(SDLMAIN_OBJECTS)
@@ -200,6 +206,7 @@ uninstall-data:
 
 
 clean:
 clean:
 	rm -rf $(objects)
 	rm -rf $(objects)
+	rm -rf $(gen)
 	if test -f test/Makefile; then (cd test; $(MAKE) $@); fi
 	if test -f test/Makefile; then (cd test; $(MAKE) $@); fi
 
 
 distclean: clean
 distclean: clean

+ 1 - 1
Engine/lib/sdl/Makefile.pandora

@@ -19,7 +19,7 @@ SOURCES = ./src/*.c ./src/audio/*.c ./src/cpuinfo/*.c ./src/events/*.c \
 	./src/thread/pthread/SDL_systhread.c ./src/thread/pthread/SDL_syssem.c \
 	./src/thread/pthread/SDL_systhread.c ./src/thread/pthread/SDL_syssem.c \
 	./src/thread/pthread/SDL_sysmutex.c ./src/thread/pthread/SDL_syscond.c \
 	./src/thread/pthread/SDL_sysmutex.c ./src/thread/pthread/SDL_syscond.c \
 	./src/joystick/linux/*.c ./src/haptic/linux/*.c ./src/timer/unix/*.c \
 	./src/joystick/linux/*.c ./src/haptic/linux/*.c ./src/timer/unix/*.c \
-	./src/atomic/linux/*.c ./src/filesystem/unix/*.c \
+	./src/atomic/*.c ./src/filesystem/unix/*.c \
 	./src/video/pandora/SDL_pandora.o ./src/video/pandora/SDL_pandora_events.o ./src/video/x11/*.c 
 	./src/video/pandora/SDL_pandora.o ./src/video/pandora/SDL_pandora_events.o ./src/video/x11/*.c 
 	
 	
 
 

+ 1 - 0
Engine/lib/sdl/Makefile.psp

@@ -49,6 +49,7 @@ OBJS= src/SDL.o \
       src/stdlib/SDL_stdlib.o \
       src/stdlib/SDL_stdlib.o \
       src/stdlib/SDL_string.o \
       src/stdlib/SDL_string.o \
       src/thread/SDL_thread.o \
       src/thread/SDL_thread.o \
+      src/thread/generic/SDL_systls.o \
       src/thread/psp/SDL_syssem.o \
       src/thread/psp/SDL_syssem.o \
       src/thread/psp/SDL_systhread.o \
       src/thread/psp/SDL_systhread.o \
       src/thread/psp/SDL_sysmutex.o \
       src/thread/psp/SDL_sysmutex.o \

+ 5 - 5
Engine/lib/sdl/Makefile.wiz

@@ -9,8 +9,8 @@ STRIP = $(WIZSDK)/bin/arm-openwiz-linux-gnu-strip
 
 
 CFLAGS  = -Wall -fPIC -I./include -I$(WIZSDK)/include -DWIZ_GLES_LITE
 CFLAGS  = -Wall -fPIC -I./include -I$(WIZSDK)/include -DWIZ_GLES_LITE
 
 
-TARGET_STATIC  = libSDL13.a
-TARGET_SHARED  = libSDL13.so
+TARGET_STATIC  = libSDL2.a
+TARGET_SHARED  = libSDL2.so
 
 
 SOURCES = ./src/*.c ./src/audio/*.c ./src/cpuinfo/*.c ./src/events/*.c \
 SOURCES = ./src/*.c ./src/audio/*.c ./src/cpuinfo/*.c ./src/events/*.c \
 	./src/file/*.c ./src/stdlib/*.c ./src/thread/*.c ./src/timer/*.c ./src/video/*.c \
 	./src/file/*.c ./src/stdlib/*.c ./src/thread/*.c ./src/timer/*.c ./src/video/*.c \
@@ -43,7 +43,7 @@ clean:
 
 
 install:
 install:
 	mkdir -p $(WIZSDK)/lib
 	mkdir -p $(WIZSDK)/lib
-	mkdir -p $(WIZSDK)/include/SDL13
+	mkdir -p $(WIZSDK)/include/SDL2
 	cp -f $(TARGET_STATIC) $(WIZSDK)/lib
 	cp -f $(TARGET_STATIC) $(WIZSDK)/lib
 	cp -f $(TARGET_SHARED).0.0.1 $(WIZSDK)/lib
 	cp -f $(TARGET_SHARED).0.0.1 $(WIZSDK)/lib
 	rm -f $(WIZSDK)/lib/$(TARGET_SHARED).0 $(WIZSDK)/lib/$(TARGET_SHARED)
 	rm -f $(WIZSDK)/lib/$(TARGET_SHARED).0 $(WIZSDK)/lib/$(TARGET_SHARED)
@@ -57,5 +57,5 @@ install:
 	ln -s ../../toolchain/libs/$(TARGET_SHARED).0 ../../toolchain/libs/$(TARGET_SHARED)
 	ln -s ../../toolchain/libs/$(TARGET_SHARED).0 ../../toolchain/libs/$(TARGET_SHARED)
 
 
 	cp $(TARGET_SHARED).0.0.1 ../nehe_demos/build/$(TARGET_SHARED).0
 	cp $(TARGET_SHARED).0.0.1 ../nehe_demos/build/$(TARGET_SHARED).0
-	cp -f include/*.h $(WIZSDK)/include/SDL13/
-	cp -f include/*.h ../../toolchain/include/SDL13/
+	cp -f include/*.h $(WIZSDK)/include/SDL2/
+	cp -f include/*.h ../../toolchain/include/SDL2/

+ 2 - 2
Engine/lib/sdl/README-SDL.txt

@@ -2,8 +2,8 @@
 Please distribute this file with the SDL runtime environment:
 Please distribute this file with the SDL runtime environment:
 
 
 The Simple DirectMedia Layer (SDL for short) is a cross-platform library
 The Simple DirectMedia Layer (SDL for short) is a cross-platform library
-designed to make it easy to write multi-media software, such as games and
-emulators.
+designed to make it easy to write multi-media software, such as games
+and emulators.
 
 
 The Simple DirectMedia Layer library source code is available from:
 The Simple DirectMedia Layer library source code is available from:
 http://www.libsdl.org/
 http://www.libsdl.org/

+ 1 - 1
Engine/lib/sdl/SDL2.spec

@@ -1,6 +1,6 @@
 Summary: Simple DirectMedia Layer
 Summary: Simple DirectMedia Layer
 Name: SDL2
 Name: SDL2
-Version: 2.0.4
+Version: 2.0.5
 Release: 2
 Release: 2
 Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
 Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
 URL: http://www.libsdl.org/
 URL: http://www.libsdl.org/

+ 2 - 2
Engine/lib/sdl/VisualC.html

@@ -21,7 +21,7 @@
 		</P>
 		</P>
 		<P>
 		<P>
 			There are different solution files for the various
 			There are different solution files for the various
-			versions of the IDE. Please use the appropiate version
+			versions of the IDE. Please use the appropriate version
 			2008, 2010, 2012 or 2013.
 			2008, 2010, 2012 or 2013.
 		</P>
 		</P>
 		<P>
 		<P>
@@ -101,7 +101,7 @@
 				files to project")
 				files to project")
 			</P>
 			</P>
 		<P><STRONG><FONT color="#009900">Instead of adding the files to your project it is more 
 		<P><STRONG><FONT color="#009900">Instead of adding the files to your project it is more 
-					desireable to add them to the linker options: Project|Properties|Linker|Command 
+					desirable to add them to the linker options: Project|Properties|Linker|Command 
 					Line and type the names of the libraries to link with in the "Additional 
 					Line and type the names of the libraries to link with in the "Additional 
 					Options:" box.&nbsp; Note: This must be done&nbsp;for&nbsp;each&nbsp;build 
 					Options:" box.&nbsp; Note: This must be done&nbsp;for&nbsp;each&nbsp;build 
 					configuration (e.g. Release,Debug).</FONT></STRONG></P>
 					configuration (e.g. Release,Debug).</FONT></STRONG></P>

+ 0 - 4
Engine/lib/sdl/VisualC/clean.sh

@@ -1,4 +0,0 @@
-#!/bin/sh
-find . -type f \( -name '*.user' -o -name '*.sdf' -o -name '*.ncb' -o -name '*.suo' \) -print -delete
-find . -type f \( -name '*.bmp' -o -name '*.wav' -o -name '*.dat' \) -print -delete
-find . -depth -type d \( -name Win32 -o -name x64 \) -exec rm -rv {} \;

+ 63 - 0
Engine/lib/sdl/WhatsNew.txt

@@ -1,6 +1,69 @@
 
 
 This is a list of major changes in SDL's version history.
 This is a list of major changes in SDL's version history.
 
 
+---------------------------------------------------------------------------
+2.0.5:
+---------------------------------------------------------------------------
+
+General:
+* Implemented audio capture support for some platforms
+* Added SDL_DequeueAudio() to retrieve audio when buffer queuing is turned on for audio capture
+* Added events for dragging and dropping text
+* Added events for dragging and dropping multiple items
+* By default the click raising a window will not be delivered to the SDL application. You can set the hint SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH to "1" to allow that click through to the window.
+* Saving a surface with an alpha channel as a BMP will use a newer BMP format that supports alpha information. You can set the hint SDL_HINT_BMP_SAVE_LEGACY_FORMAT to "1" to use the old format.
+* Added SDL_GetHintBoolean() to get the boolean value of a hint
+* Added SDL_RenderSetIntegerScale() to set whether to smoothly scale or use integral multiples of the viewport size when scaling the rendering output
+* Added SDL_CreateRGBSurfaceWithFormat() and SDL_CreateRGBSurfaceWithFormatFrom() to create an SDL surface with a specific pixel format
+* Added SDL_GetDisplayUsableBounds() which returns the area usable for windows. For example, on Mac OS X, this subtracts the area occupied by the menu bar and dock.
+* Added SDL_GetWindowBordersSize() which returns the size of the window's borders around the client area
+* Added a window event SDL_WINDOWEVENT_HIT_TEST when a window had a hit test that wasn't SDL_HITTEST_NORMAL (e.g. in the title bar or window frame)
+* Added SDL_SetWindowResizable() to change whether a window is resizable
+* Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity() to affect the window transparency
+* Added SDL_SetWindowModalFor() to set a window as modal for another window
+* Added support for AUDIO_U16LSB and AUDIO_U16MSB to SDL_MixAudioFormat()
+* Fixed flipped images when reading back from target textures when using the OpenGL renderer
+* Fixed texture color modulation with SDL_BLENDMODE_NONE when using the OpenGL renderer
+* Fixed bug where the alpha value of colorkeys was ignored when blitting in some cases
+
+Windows:
+* Added a hint SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING to prevent SDL from raising a debugger exception to name threads. This exception can cause problems with .NET applications when running under a debugger.
+* The hint SDL_HINT_THREAD_STACK_SIZE is now supported on Windows
+* Fixed XBox controller triggers automatically being pulled at startup
+* The first icon from the executable is used as the default window icon at runtime
+* Fixed SDL log messages being printed twice if SDL was built with C library support
+* Reset dead keys when the SDL window loses focus, so dead keys pressed in SDL applications don't affect text input into other applications.
+
+Mac OS X:
+* Fixed selecting the dummy video driver
+* The caps lock key now generates a pressed event when pressed and a released event when released, instead of a press/release event pair when pressed.
+* Fixed mouse wheel events on Mac OS X 10.12
+* The audio driver has been updated to use AVFoundation for better compatibility with newer versions of Mac OS X
+
+Linux:
+* Added support for the Fcitx IME
+* Added a window event SDL_WINDOWEVENT_TAKE_FOCUS when a window manager asks the SDL window whether it wants to take focus.
+* Refresh rates are now rounded instead of truncated, e.g. 59.94 Hz is rounded up to 60 Hz instead of 59.
+* Added initial support for touchscreens on Raspberry Pi
+
+OpenBSD:
+* SDL_GetBasePath() is now implemented on OpenBSD
+
+iOS:
+* Added support for dynamically loaded objects on iOS 8 and newer
+
+tvOS:
+* Added support for Apple TV
+* Added a hint SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION to control whether he Apple TV remote's joystick axes will automatically match the rotation of the remote.  
+
+Android:
+* Fixed SDL not resizing window when Android screen resolution changes
+* Corrected the joystick Z axis reporting for the accelerometer
+
+Emscripten (running in a web browser):
+* Many bug fixes and improvements
+
+
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 2.0.4:
 2.0.4:
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 3 - 3
Engine/lib/sdl/Xcode/SDL/Info-Framework.plist

@@ -11,7 +11,7 @@
 	<key>CFBundleIconFile</key>
 	<key>CFBundleIconFile</key>
 	<string></string>
 	<string></string>
 	<key>CFBundleIdentifier</key>
 	<key>CFBundleIdentifier</key>
-	<string>org.libsdl.SDL2</string>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<string>6.0</string>
 	<key>CFBundleName</key>
 	<key>CFBundleName</key>
@@ -19,10 +19,10 @@
 	<key>CFBundlePackageType</key>
 	<key>CFBundlePackageType</key>
 	<string>FMWK</string>
 	<string>FMWK</string>
 	<key>CFBundleShortVersionString</key>
 	<key>CFBundleShortVersionString</key>
-	<string>2.0.4</string>
+	<string>2.0.5</string>
 	<key>CFBundleSignature</key>
 	<key>CFBundleSignature</key>
 	<string>SDLX</string>
 	<string>SDLX</string>
 	<key>CFBundleVersion</key>
 	<key>CFBundleVersion</key>
-	<string>2.0.4</string>
+	<string>2.0.5</string>
 </dict>
 </dict>
 </plist>
 </plist>

+ 72 - 45
Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj

@@ -7,15 +7,9 @@
 	objects = {
 	objects = {
 
 
 /* Begin PBXBuildFile section */
 /* Begin PBXBuildFile section */
-		007317A20858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
-		007317A30858DECD00B2BC32 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
 		007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
 		007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
-		007317A50858DECD00B2BC32 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
 		007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
 		007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
-		007317A90858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
-		007317AA0858DECD00B2BC32 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
 		007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
 		007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
-		007317AC0858DECD00B2BC32 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
 		007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
 		007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
 		007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
 		007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
 		00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
 		00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
@@ -57,14 +51,12 @@
 		04BD000912E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
 		04BD000912E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
 		04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
 		04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
 		04BD001112E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
 		04BD001112E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
-		04BD001812E6671800899322 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
 		04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		04BD002612E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		04BD002612E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		04BD002712E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		04BD002712E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		04BD002912E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
 		04BD002912E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
 		04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
 		04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
-		04BD002B12E6671800899322 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
 		04BD002C12E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
 		04BD002C12E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
 		04BD002D12E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
 		04BD002D12E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
 		04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
 		04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
@@ -211,14 +203,12 @@
 		04BD022512E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
 		04BD022512E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
 		04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
 		04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
 		04BD022D12E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
 		04BD022D12E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
-		04BD023412E6671800899322 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
 		04BD023512E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		04BD023512E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		04BD024212E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		04BD024212E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		04BD024312E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		04BD024312E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		04BD024512E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
 		04BD024512E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
 		04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
 		04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
-		04BD024712E6671800899322 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
 		04BD024812E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
 		04BD024812E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
 		04BD024912E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
 		04BD024912E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
 		04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
 		04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
@@ -387,6 +377,10 @@
 		04F7805D12FB74A200FC43C0 /* SDL_drawline.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804512FB74A200FC43C0 /* SDL_drawline.h */; };
 		04F7805D12FB74A200FC43C0 /* SDL_drawline.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804512FB74A200FC43C0 /* SDL_drawline.h */; };
 		04F7805E12FB74A200FC43C0 /* SDL_drawpoint.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F7804612FB74A200FC43C0 /* SDL_drawpoint.c */; };
 		04F7805E12FB74A200FC43C0 /* SDL_drawpoint.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F7804612FB74A200FC43C0 /* SDL_drawpoint.c */; };
 		04F7805F12FB74A200FC43C0 /* SDL_drawpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804712FB74A200FC43C0 /* SDL_drawpoint.h */; };
 		04F7805F12FB74A200FC43C0 /* SDL_drawpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804712FB74A200FC43C0 /* SDL_drawpoint.h */; };
+		562C4AE91D8F496200AF9EBE /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
+		562C4AEA1D8F496300AF9EBE /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
+		562D3C7C1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
+		562D3C7D1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
 		566CDE8F148F0AC200C5A9BB /* SDL_dropevents_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 566CDE8D148F0AC200C5A9BB /* SDL_dropevents_c.h */; };
 		566CDE8F148F0AC200C5A9BB /* SDL_dropevents_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 566CDE8D148F0AC200C5A9BB /* SDL_dropevents_c.h */; };
 		566CDE90148F0AC200C5A9BB /* SDL_dropevents.c in Sources */ = {isa = PBXBuildFile; fileRef = 566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */; };
 		566CDE90148F0AC200C5A9BB /* SDL_dropevents.c in Sources */ = {isa = PBXBuildFile; fileRef = 566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */; };
 		567E2F1C17C44BB2005F1892 /* SDL_sysfilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 567E2F1B17C44BB2005F1892 /* SDL_sysfilesystem.m */; };
 		567E2F1C17C44BB2005F1892 /* SDL_sysfilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 567E2F1B17C44BB2005F1892 /* SDL_sysfilesystem.m */; };
@@ -406,6 +400,12 @@
 		56A6702A185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
 		56A6702A185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
 		56A6702B185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
 		56A6702B185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
 		56A6702C185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
 		56A6702C185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
+		56C5237E1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+		56C5237F1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+		56C523801D8F498B001F2F30 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D0D08310675DD9004B05EF /* CoreFoundation.framework */; };
+		56C523811D8F498C001F2F30 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D0D08310675DD9004B05EF /* CoreFoundation.framework */; };
+		A7381E961D8B69D600B177DD /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+		A7381E971D8B6A0300B177DD /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
 		A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
 		AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
@@ -563,7 +563,6 @@
 		DB313F7617554B71006C0E22 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		DB313F7617554B71006C0E22 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
 		DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
 		DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
 		DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
-		DB313F7917554B71006C0E22 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
 		DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
 		DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
 		DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC412E6671700899322 /* SDL_wave.h */; };
 		DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC412E6671700899322 /* SDL_wave.h */; };
 		DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDD612E6671700899322 /* blank_cursor.h */; };
 		DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDD612E6671700899322 /* blank_cursor.h */; };
@@ -698,7 +697,6 @@
 		DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD7512E6671700899322 /* SDL_spinlock.c */; };
 		DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD7512E6671700899322 /* SDL_spinlock.c */; };
 		DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD8812E6671700899322 /* SDL_diskaudio.c */; };
 		DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD8812E6671700899322 /* SDL_diskaudio.c */; };
 		DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
 		DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
-		DB31400217554B71006C0E22 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
 		DB31400317554B71006C0E22 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		DB31400317554B71006C0E22 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
 		DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
 		DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
 		DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
@@ -802,10 +800,7 @@
 		DB31406817554B71006C0E22 /* SDL_x11xinput2.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628ACF159367F2005138DD /* SDL_x11xinput2.c */; };
 		DB31406817554B71006C0E22 /* SDL_x11xinput2.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628ACF159367F2005138DD /* SDL_x11xinput2.c */; };
 		DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */; };
 		DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */; };
 		DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; };
 		DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; };
-		DB31406C17554B71006C0E22 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
-		DB31406D17554B71006C0E22 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
 		DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
 		DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
-		DB31406F17554B71006C0E22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
 		DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
 		DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
 		DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
 		DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
 		DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
 		DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
@@ -813,6 +808,7 @@
 		FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
 		FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
+		FABA34C71D8B5DB100915323 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
 /* End PBXBuildFile section */
 /* End PBXBuildFile section */
 
 
 /* Begin PBXContainerItemProxy section */
 /* Begin PBXContainerItemProxy section */
@@ -826,10 +822,7 @@
 /* End PBXContainerItemProxy section */
 /* End PBXContainerItemProxy section */
 
 
 /* Begin PBXFileReference section */
 /* Begin PBXFileReference section */
-		0073179B0858DECD00B2BC32 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
-		0073179C0858DECD00B2BC32 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = "<absolute>"; };
 		0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
 		0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
-		0073179E0858DECD00B2BC32 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = "<absolute>"; };
 		0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
 		0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
 		007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
 		007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
 		00794D3F09D0C461003FC8A1 /* License.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
 		00794D3F09D0C461003FC8A1 /* License.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = License.txt; sourceTree = "<group>"; };
@@ -857,14 +850,12 @@
 		04BDFD8912E6671700899322 /* SDL_diskaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_diskaudio.h; sourceTree = "<group>"; };
 		04BDFD8912E6671700899322 /* SDL_diskaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_diskaudio.h; sourceTree = "<group>"; };
 		04BDFD9412E6671700899322 /* SDL_dummyaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyaudio.c; sourceTree = "<group>"; };
 		04BDFD9412E6671700899322 /* SDL_dummyaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyaudio.c; sourceTree = "<group>"; };
 		04BDFD9512E6671700899322 /* SDL_dummyaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dummyaudio.h; sourceTree = "<group>"; };
 		04BDFD9512E6671700899322 /* SDL_dummyaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dummyaudio.h; sourceTree = "<group>"; };
-		04BDFDA012E6671700899322 /* SDL_coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_coreaudio.c; sourceTree = "<group>"; };
 		04BDFDA112E6671700899322 /* SDL_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_coreaudio.h; sourceTree = "<group>"; };
 		04BDFDA112E6671700899322 /* SDL_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_coreaudio.h; sourceTree = "<group>"; };
 		04BDFDB412E6671700899322 /* SDL_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audio.c; sourceTree = "<group>"; };
 		04BDFDB412E6671700899322 /* SDL_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audio.c; sourceTree = "<group>"; };
 		04BDFDB512E6671700899322 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = "<group>"; };
 		04BDFDB512E6671700899322 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = "<group>"; };
 		04BDFDB612E6671700899322 /* SDL_audiocvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiocvt.c; sourceTree = "<group>"; };
 		04BDFDB612E6671700899322 /* SDL_audiocvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiocvt.c; sourceTree = "<group>"; };
 		04BDFDB712E6671700899322 /* SDL_audiodev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiodev.c; sourceTree = "<group>"; };
 		04BDFDB712E6671700899322 /* SDL_audiodev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiodev.c; sourceTree = "<group>"; };
 		04BDFDB812E6671700899322 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = "<group>"; };
 		04BDFDB812E6671700899322 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = "<group>"; };
-		04BDFDB912E6671700899322 /* SDL_audiomem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiomem.h; sourceTree = "<group>"; };
 		04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiotypecvt.c; sourceTree = "<group>"; };
 		04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiotypecvt.c; sourceTree = "<group>"; };
 		04BDFDBB12E6671700899322 /* SDL_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_mixer.c; sourceTree = "<group>"; };
 		04BDFDBB12E6671700899322 /* SDL_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_mixer.c; sourceTree = "<group>"; };
 		04BDFDC212E6671700899322 /* SDL_sysaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysaudio.h; sourceTree = "<group>"; };
 		04BDFDC212E6671700899322 /* SDL_sysaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysaudio.h; sourceTree = "<group>"; };
@@ -1027,6 +1018,8 @@
 		56A6701E185654B40007D20F /* SDL_dynapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_dynapi.c; path = ../../src/dynapi/SDL_dynapi.c; sourceTree = "<group>"; };
 		56A6701E185654B40007D20F /* SDL_dynapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_dynapi.c; path = ../../src/dynapi/SDL_dynapi.c; sourceTree = "<group>"; };
 		56A6701F185654B40007D20F /* SDL_dynapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi.h; path = ../../src/dynapi/SDL_dynapi.h; sourceTree = "<group>"; };
 		56A6701F185654B40007D20F /* SDL_dynapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi.h; path = ../../src/dynapi/SDL_dynapi.h; sourceTree = "<group>"; };
 		56A67020185654B40007D20F /* SDL_dynapi_overrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi_overrides.h; path = ../../src/dynapi/SDL_dynapi_overrides.h; sourceTree = "<group>"; };
 		56A67020185654B40007D20F /* SDL_dynapi_overrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi_overrides.h; path = ../../src/dynapi/SDL_dynapi_overrides.h; sourceTree = "<group>"; };
+		A7381E931D8B69C300B177DD /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+		A7381E951D8B69D600B177DD /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
 		A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
 		A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
 		AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
 		AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
 		AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
 		AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
@@ -1106,6 +1099,7 @@
 		F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
 		F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = "<group>"; };
 		F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
 		F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
 		FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = "<absolute>"; };
 		FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = "<absolute>"; };
+		FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coreaudio.m; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 /* End PBXFileReference section */
 
 
 /* Begin PBXFrameworksBuildPhase section */
 /* Begin PBXFrameworksBuildPhase section */
@@ -1113,11 +1107,10 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				A7381E971D8B6A0300B177DD /* AudioToolbox.framework in Frameworks */,
+				A7381E961D8B69D600B177DD /* CoreAudio.framework in Frameworks */,
 				FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */,
 				FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */,
-				007317A20858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */,
-				007317A30858DECD00B2BC32 /* AudioUnit.framework in Frameworks */,
 				007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
 				007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
-				007317A50858DECD00B2BC32 /* CoreAudio.framework in Frameworks */,
 				007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */,
 				007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */,
 				00D0D08410675DD9004B05EF /* CoreFoundation.framework in Frameworks */,
 				00D0D08410675DD9004B05EF /* CoreFoundation.framework in Frameworks */,
 				00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */,
 				00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */,
@@ -1129,14 +1122,14 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				56C5237E1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */,
 				FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */,
 				FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */,
-				007317A90858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */,
-				007317AA0858DECD00B2BC32 /* AudioUnit.framework in Frameworks */,
 				007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
 				007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
-				007317AC0858DECD00B2BC32 /* CoreAudio.framework in Frameworks */,
 				007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */,
 				007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */,
+				56C523801D8F498B001F2F30 /* CoreFoundation.framework in Frameworks */,
 				007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */,
 				007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */,
 				DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */,
 				DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */,
+				562C4AE91D8F496200AF9EBE /* AudioToolbox.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1144,14 +1137,14 @@
 			isa = PBXFrameworksBuildPhase;
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			buildActionMask = 2147483647;
 			files = (
 			files = (
+				56C5237F1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */,
 				FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */,
 				FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */,
-				DB31406C17554B71006C0E22 /* AudioToolbox.framework in Frameworks */,
-				DB31406D17554B71006C0E22 /* AudioUnit.framework in Frameworks */,
 				DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */,
 				DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */,
-				DB31406F17554B71006C0E22 /* CoreAudio.framework in Frameworks */,
 				DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */,
 				DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */,
+				56C523811D8F498C001F2F30 /* CoreFoundation.framework in Frameworks */,
 				DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */,
 				DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */,
 				DB31408D17554D3C006C0E22 /* ForceFeedback.framework in Frameworks */,
 				DB31408D17554D3C006C0E22 /* ForceFeedback.framework in Frameworks */,
+				562C4AEA1D8F496300AF9EBE /* AudioToolbox.framework in Frameworks */,
 			);
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 		};
@@ -1307,7 +1300,6 @@
 				04BDFDB612E6671700899322 /* SDL_audiocvt.c */,
 				04BDFDB612E6671700899322 /* SDL_audiocvt.c */,
 				04BDFDB712E6671700899322 /* SDL_audiodev.c */,
 				04BDFDB712E6671700899322 /* SDL_audiodev.c */,
 				04BDFDB812E6671700899322 /* SDL_audiodev_c.h */,
 				04BDFDB812E6671700899322 /* SDL_audiodev_c.h */,
-				04BDFDB912E6671700899322 /* SDL_audiomem.h */,
 				04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */,
 				04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */,
 				04BDFDBB12E6671700899322 /* SDL_mixer.c */,
 				04BDFDBB12E6671700899322 /* SDL_mixer.c */,
 				04BDFDC212E6671700899322 /* SDL_sysaudio.h */,
 				04BDFDC212E6671700899322 /* SDL_sysaudio.h */,
@@ -1339,8 +1331,8 @@
 		04BDFD9F12E6671700899322 /* coreaudio */ = {
 		04BDFD9F12E6671700899322 /* coreaudio */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
-				04BDFDA012E6671700899322 /* SDL_coreaudio.c */,
 				04BDFDA112E6671700899322 /* SDL_coreaudio.h */,
 				04BDFDA112E6671700899322 /* SDL_coreaudio.h */,
+				FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */,
 			);
 			);
 			path = coreaudio;
 			path = coreaudio;
 			sourceTree = "<group>";
 			sourceTree = "<group>";
@@ -1737,13 +1729,12 @@
 		BEC562FE0761C0E800A33029 /* Linked Frameworks */ = {
 		BEC562FE0761C0E800A33029 /* Linked Frameworks */ = {
 			isa = PBXGroup;
 			isa = PBXGroup;
 			children = (
 			children = (
+				A7381E931D8B69C300B177DD /* AudioToolbox.framework */,
+				A7381E951D8B69D600B177DD /* CoreAudio.framework */,
 				FA73671C19A540EF004122E4 /* CoreVideo.framework */,
 				FA73671C19A540EF004122E4 /* CoreVideo.framework */,
 				00D0D08310675DD9004B05EF /* CoreFoundation.framework */,
 				00D0D08310675DD9004B05EF /* CoreFoundation.framework */,
 				007317C10858E15000B2BC32 /* Carbon.framework */,
 				007317C10858E15000B2BC32 /* Carbon.framework */,
-				0073179B0858DECD00B2BC32 /* AudioToolbox.framework */,
-				0073179C0858DECD00B2BC32 /* AudioUnit.framework */,
 				0073179D0858DECD00B2BC32 /* Cocoa.framework */,
 				0073179D0858DECD00B2BC32 /* Cocoa.framework */,
-				0073179E0858DECD00B2BC32 /* CoreAudio.framework */,
 				0073179F0858DECD00B2BC32 /* IOKit.framework */,
 				0073179F0858DECD00B2BC32 /* IOKit.framework */,
 				00CFA89C106B4BA100758660 /* ForceFeedback.framework */,
 				00CFA89C106B4BA100758660 /* ForceFeedback.framework */,
 			);
 			);
@@ -1840,7 +1831,6 @@
 				04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */,
 				04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */,
 				04BD002712E6671800899322 /* SDL_audio_c.h in Headers */,
 				04BD002712E6671800899322 /* SDL_audio_c.h in Headers */,
 				04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */,
 				04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */,
-				04BD002B12E6671800899322 /* SDL_audiomem.h in Headers */,
 				04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */,
 				04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */,
 				04BD003612E6671800899322 /* SDL_wave.h in Headers */,
 				04BD003612E6671800899322 /* SDL_wave.h in Headers */,
 				04BD004212E6671800899322 /* blank_cursor.h in Headers */,
 				04BD004212E6671800899322 /* blank_cursor.h in Headers */,
@@ -1996,7 +1986,6 @@
 				04BD024312E6671800899322 /* SDL_audio_c.h in Headers */,
 				04BD024312E6671800899322 /* SDL_audio_c.h in Headers */,
 				04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */,
 				04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */,
 				AAC070FD195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
 				AAC070FD195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
-				04BD024712E6671800899322 /* SDL_audiomem.h in Headers */,
 				04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */,
 				04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */,
 				04BD025212E6671800899322 /* SDL_wave.h in Headers */,
 				04BD025212E6671800899322 /* SDL_wave.h in Headers */,
 				04BD025D12E6671800899322 /* blank_cursor.h in Headers */,
 				04BD025D12E6671800899322 /* blank_cursor.h in Headers */,
@@ -2151,7 +2140,6 @@
 				DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */,
 				DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */,
 				DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */,
 				DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */,
 				AAC070FE195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
 				AAC070FE195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
-				DB313F7917554B71006C0E22 /* SDL_audiomem.h in Headers */,
 				DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */,
 				DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */,
 				DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */,
 				DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */,
 				DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */,
 				DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */,
@@ -2323,7 +2311,7 @@
 		0867D690FE84028FC02AAC07 /* Project object */ = {
 		0867D690FE84028FC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			isa = PBXProject;
 			attributes = {
 			attributes = {
-				LastUpgradeCheck = 0630;
+				LastUpgradeCheck = 0730;
 				TargetAttributes = {
 				TargetAttributes = {
 					BECDF5FE0761BA81005FE872 = {
 					BECDF5FE0761BA81005FE872 = {
 						DevelopmentTeam = EH385AYQ6F;
 						DevelopmentTeam = EH385AYQ6F;
@@ -2404,7 +2392,6 @@
 				04BDFFFC12E6671800899322 /* SDL_spinlock.c in Sources */,
 				04BDFFFC12E6671800899322 /* SDL_spinlock.c in Sources */,
 				04BD000812E6671800899322 /* SDL_diskaudio.c in Sources */,
 				04BD000812E6671800899322 /* SDL_diskaudio.c in Sources */,
 				04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */,
 				04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */,
-				04BD001812E6671800899322 /* SDL_coreaudio.c in Sources */,
 				04BD002612E6671800899322 /* SDL_audio.c in Sources */,
 				04BD002612E6671800899322 /* SDL_audio.c in Sources */,
 				04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */,
 				04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */,
 				04BD002912E6671800899322 /* SDL_audiodev.c in Sources */,
 				04BD002912E6671800899322 /* SDL_audiodev.c in Sources */,
@@ -2440,6 +2427,7 @@
 				04BD00A812E6671800899322 /* SDL_string.c in Sources */,
 				04BD00A812E6671800899322 /* SDL_string.c in Sources */,
 				04BD00BD12E6671800899322 /* SDL_syscond.c in Sources */,
 				04BD00BD12E6671800899322 /* SDL_syscond.c in Sources */,
 				04BD00BE12E6671800899322 /* SDL_sysmutex.c in Sources */,
 				04BD00BE12E6671800899322 /* SDL_sysmutex.c in Sources */,
+				FABA34C71D8B5DB100915323 /* SDL_coreaudio.m in Sources */,
 				04BD00C012E6671800899322 /* SDL_syssem.c in Sources */,
 				04BD00C012E6671800899322 /* SDL_syssem.c in Sources */,
 				04BD00C112E6671800899322 /* SDL_systhread.c in Sources */,
 				04BD00C112E6671800899322 /* SDL_systhread.c in Sources */,
 				04BD00CA12E6671800899322 /* SDL_thread.c in Sources */,
 				04BD00CA12E6671800899322 /* SDL_thread.c in Sources */,
@@ -2523,7 +2511,6 @@
 				04BD021812E6671800899322 /* SDL_spinlock.c in Sources */,
 				04BD021812E6671800899322 /* SDL_spinlock.c in Sources */,
 				04BD022412E6671800899322 /* SDL_diskaudio.c in Sources */,
 				04BD022412E6671800899322 /* SDL_diskaudio.c in Sources */,
 				04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */,
 				04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */,
-				04BD023412E6671800899322 /* SDL_coreaudio.c in Sources */,
 				04BD024212E6671800899322 /* SDL_audio.c in Sources */,
 				04BD024212E6671800899322 /* SDL_audio.c in Sources */,
 				04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */,
 				04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */,
 				04BD024512E6671800899322 /* SDL_audiodev.c in Sources */,
 				04BD024512E6671800899322 /* SDL_audiodev.c in Sources */,
@@ -2559,6 +2546,7 @@
 				04BD02C012E6671800899322 /* SDL_qsort.c in Sources */,
 				04BD02C012E6671800899322 /* SDL_qsort.c in Sources */,
 				04BD02C112E6671800899322 /* SDL_stdlib.c in Sources */,
 				04BD02C112E6671800899322 /* SDL_stdlib.c in Sources */,
 				04BD02C212E6671800899322 /* SDL_string.c in Sources */,
 				04BD02C212E6671800899322 /* SDL_string.c in Sources */,
+				562D3C7C1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */,
 				04BD02D712E6671800899322 /* SDL_syscond.c in Sources */,
 				04BD02D712E6671800899322 /* SDL_syscond.c in Sources */,
 				04BD02D812E6671800899322 /* SDL_sysmutex.c in Sources */,
 				04BD02D812E6671800899322 /* SDL_sysmutex.c in Sources */,
 				04BD02DA12E6671800899322 /* SDL_syssem.c in Sources */,
 				04BD02DA12E6671800899322 /* SDL_syssem.c in Sources */,
@@ -2642,7 +2630,6 @@
 				DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */,
 				DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */,
 				DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */,
 				DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */,
 				DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */,
 				DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */,
-				DB31400217554B71006C0E22 /* SDL_coreaudio.c in Sources */,
 				DB31400317554B71006C0E22 /* SDL_audio.c in Sources */,
 				DB31400317554B71006C0E22 /* SDL_audio.c in Sources */,
 				DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */,
 				DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */,
 				DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */,
 				DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */,
@@ -2678,6 +2665,7 @@
 				DB31402417554B71006C0E22 /* SDL_qsort.c in Sources */,
 				DB31402417554B71006C0E22 /* SDL_qsort.c in Sources */,
 				DB31402517554B71006C0E22 /* SDL_stdlib.c in Sources */,
 				DB31402517554B71006C0E22 /* SDL_stdlib.c in Sources */,
 				DB31402617554B71006C0E22 /* SDL_string.c in Sources */,
 				DB31402617554B71006C0E22 /* SDL_string.c in Sources */,
+				562D3C7D1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */,
 				DB31402717554B71006C0E22 /* SDL_syscond.c in Sources */,
 				DB31402717554B71006C0E22 /* SDL_syscond.c in Sources */,
 				DB31402817554B71006C0E22 /* SDL_sysmutex.c in Sources */,
 				DB31402817554B71006C0E22 /* SDL_sysmutex.c in Sources */,
 				DB31402917554B71006C0E22 /* SDL_syssem.c in Sources */,
 				DB31402917554B71006C0E22 /* SDL_syssem.c in Sources */,
@@ -2767,14 +2755,31 @@
 		00CFA621106A567900758660 /* Release */ = {
 		00CFA621106A567900758660 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				DEPLOYMENT_POSTPROCESSING = YES;
 				DEPLOYMENT_POSTPROCESSING = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
 				GCC_AUTO_VECTORIZATION = YES;
 				GCC_AUTO_VECTORIZATION = YES;
 				GCC_ENABLE_SSE3_EXTENSIONS = YES;
 				GCC_ENABLE_SSE3_EXTENSIONS = YES;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_OPTIMIZATION_LEVEL = 3;
 				GCC_OPTIMIZATION_LEVEL = 3;
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
 				STRIP_STYLE = "non-global";
 				STRIP_STYLE = "non-global";
 			};
 			};
@@ -2783,15 +2788,17 @@
 		00CFA622106A567900758660 /* Release */ = {
 		00CFA622106A567900758660 /* Release */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				COMBINE_HIDPI_IMAGES = YES;
 				COMBINE_HIDPI_IMAGES = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
-				DYLIB_CURRENT_VERSION = 5.0.0;
+				DYLIB_CURRENT_VERSION = 5.1.0;
 				FRAMEWORK_VERSION = A;
 				FRAMEWORK_VERSION = A;
 				HEADER_SEARCH_PATHS = /usr/X11R6/include;
 				HEADER_SEARCH_PATHS = /usr/X11R6/include;
 				INFOPLIST_FILE = "Info-Framework.plist";
 				INFOPLIST_FILE = "Info-Framework.plist";
 				INSTALL_PATH = "@rpath";
 				INSTALL_PATH = "@rpath";
 				OTHER_LDFLAGS = "-liconv";
 				OTHER_LDFLAGS = "-liconv";
+				PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL2;
 				PRODUCT_NAME = SDL2;
 				PRODUCT_NAME = SDL2;
 				PROVISIONING_PROFILE = "";
 				PROVISIONING_PROFILE = "";
 				WRAPPER_EXTENSION = framework;
 				WRAPPER_EXTENSION = framework;
@@ -2827,12 +2834,30 @@
 		00CFA627106A568900758660 /* Debug */ = {
 		00CFA627106A568900758660 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
 				GCC_ALTIVEC_EXTENSIONS = YES;
 				GCC_AUTO_VECTORIZATION = YES;
 				GCC_AUTO_VECTORIZATION = YES;
 				GCC_ENABLE_SSE3_EXTENSIONS = YES;
 				GCC_ENABLE_SSE3_EXTENSIONS = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
 				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
 				ONLY_ACTIVE_ARCH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
 				SDKROOT = macosx;
 				STRIP_INSTALLED_PRODUCT = NO;
 				STRIP_INSTALLED_PRODUCT = NO;
@@ -2842,15 +2867,17 @@
 		00CFA628106A568900758660 /* Debug */ = {
 		00CFA628106A568900758660 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			isa = XCBuildConfiguration;
 			buildSettings = {
 			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				CLANG_LINK_OBJC_RUNTIME = NO;
 				COMBINE_HIDPI_IMAGES = YES;
 				COMBINE_HIDPI_IMAGES = YES;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
 				DYLIB_COMPATIBILITY_VERSION = 1.0.0;
-				DYLIB_CURRENT_VERSION = 5.0.0;
+				DYLIB_CURRENT_VERSION = 5.1.0;
 				FRAMEWORK_VERSION = A;
 				FRAMEWORK_VERSION = A;
 				HEADER_SEARCH_PATHS = /usr/X11R6/include;
 				HEADER_SEARCH_PATHS = /usr/X11R6/include;
 				INFOPLIST_FILE = "Info-Framework.plist";
 				INFOPLIST_FILE = "Info-Framework.plist";
 				INSTALL_PATH = "@rpath";
 				INSTALL_PATH = "@rpath";
 				OTHER_LDFLAGS = "-liconv";
 				OTHER_LDFLAGS = "-liconv";
+				PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL2;
 				PRODUCT_NAME = SDL2;
 				PRODUCT_NAME = SDL2;
 				PROVISIONING_PROFILE = "";
 				PROVISIONING_PROFILE = "";
 				WRAPPER_EXTENSION = framework;
 				WRAPPER_EXTENSION = framework;

+ 2 - 2
Engine/lib/sdl/Xcode/SDL/pkg-support/SDL.info

@@ -3934,7 +3934,7 @@
 				);
 				);
 				GCC_OPTIMIZATION_LEVEL = 0;
 				GCC_OPTIMIZATION_LEVEL = 0;
 				HEADER_SEARCH_PATHS = ../../include;
 				HEADER_SEARCH_PATHS = ../../include;
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
 			};
 			};
 			name = Debug;
 			name = Debug;
 		};
 		};
@@ -4060,7 +4060,7 @@
 				);
 				);
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				HEADER_SEARCH_PATHS = ../../include;
 				HEADER_SEARCH_PATHS = ../../include;
-				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
 			};
 			};
 			name = Release;
 			name = Release;
 		};
 		};

+ 6 - 0
Engine/lib/sdl/autogen.sh

@@ -3,6 +3,10 @@
 echo "Generating build information using autoconf"
 echo "Generating build information using autoconf"
 echo "This may take a while ..."
 echo "This may take a while ..."
 
 
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+pushd $srcdir
+
 # Regenerate configuration files
 # Regenerate configuration files
 cat acinclude/* >aclocal.m4
 cat acinclude/* >aclocal.m4
 found=false
 found=false
@@ -15,5 +19,7 @@ if test x$found = xfalse; then
 fi
 fi
 (cd test; sh autogen.sh)
 (cd test; sh autogen.sh)
 
 
+popd
+
 # Run configure for this platform
 # Run configure for this platform
 echo "Now you are ready to run ./configure"
 echo "Now you are ready to run ./configure"

+ 4 - 4
Engine/lib/sdl/build-scripts/androidbuild.sh

@@ -87,8 +87,8 @@ else
 fi
 fi
 
 
 cp -r $SDLPATH/Android.mk $BUILDPATH/jni/SDL
 cp -r $SDLPATH/Android.mk $BUILDPATH/jni/SDL
-sed -i "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/jni/src/Android.mk
-sed -i "s|org\.libsdl\.app|$APP|g" $BUILDPATH/AndroidManifest.xml
+sed -i -e "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/jni/src/Android.mk
+sed -i -e "s|org\.libsdl\.app|$APP|g" $BUILDPATH/AndroidManifest.xml
 
 
 # Copy user sources
 # Copy user sources
 for src in "${SOURCES[@]}"
 for src in "${SOURCES[@]}"
@@ -105,8 +105,8 @@ do
 done
 done
 
 
 ACTIVITY="${folder}Activity"
 ACTIVITY="${folder}Activity"
-sed -i "s|SDLActivity|$ACTIVITY|g" $BUILDPATH/AndroidManifest.xml
-sed -i "s|SDLActivity|$APP|g" $BUILDPATH/build.xml
+sed -i -e "s|SDLActivity|$ACTIVITY|g" $BUILDPATH/AndroidManifest.xml
+sed -i -e "s|SDLActivity|$APP|g" $BUILDPATH/build.xml
 
 
 # Fill in a default Activity
 # Fill in a default Activity
 echo "package $APP;" >  "$ACTIVITY.java"
 echo "package $APP;" >  "$ACTIVITY.java"

+ 3 - 3
Engine/lib/sdl/build-scripts/checker-buildbot.sh

@@ -61,13 +61,13 @@ mkdir checker-buildbot
 cd checker-buildbot
 cd checker-buildbot
 
 
 # You might want to do this for CMake-backed builds instead...
 # You might want to do this for CMake-backed builds instead...
-PATH="$CHECKERDIR:$PATH" scan-build -o analysis cmake -DCMAKE_BUILD_TYPE=Debug ..
+PATH="$CHECKERDIR:$PATH" scan-build -o analysis cmake -DCMAKE_BUILD_TYPE=Debug -DASSERTIONS=enabled ..
 
 
 # ...or run configure without the scan-build wrapper...
 # ...or run configure without the scan-build wrapper...
-#CC="$CHECKERDIR/libexec/ccc-analyzer" CFLAGS="-O0" ../configure
+#CC="$CHECKERDIR/libexec/ccc-analyzer" CFLAGS="-O0" ../configure --enable-assertions=enabled
 
 
 # ...but this works for our buildbots just fine (EXCEPT ON LATEST MAC OS X).
 # ...but this works for our buildbots just fine (EXCEPT ON LATEST MAC OS X).
-#CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure
+#CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure --enable-assertions=enabled
 
 
 rm -rf analysis
 rm -rf analysis
 PATH="$CHECKERDIR:$PATH" scan-build -o analysis $MAKE
 PATH="$CHECKERDIR:$PATH" scan-build -o analysis $MAKE

+ 4 - 3
Engine/lib/sdl/build-scripts/emscripten-buildbot.sh

@@ -51,13 +51,14 @@ mkdir buildbot
 pushd buildbot
 pushd buildbot
 
 
 echo "Configuring..."
 echo "Configuring..."
-emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --enable-cpuinfo=false CFLAGS="-O2 -Wno-warn-absolute-paths -Wdeclaration-after-statement -Werror=declaration-after-statement" --prefix="$PWD/emscripten-sdl2-installed"
+emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --enable-cpuinfo=false CFLAGS="-O2 -Wno-warn-absolute-paths -Wdeclaration-after-statement -Werror=declaration-after-statement" --prefix="$PWD/emscripten-sdl2-installed" || exit $?
 
 
 echo "Building..."
 echo "Building..."
-emmake $MAKE
+emmake $MAKE || exit $?
 
 
 echo "Moving things around..."
 echo "Moving things around..."
-emmake $MAKE install
+emmake $MAKE install || exit $?
+
 # Fix up a few things to a real install path
 # Fix up a few things to a real install path
 perl -w -pi -e "s#$PWD/emscripten-sdl2-installed#/usr/local#g;" ./emscripten-sdl2-installed/lib/libSDL2.la ./emscripten-sdl2-installed/lib/pkgconfig/sdl2.pc ./emscripten-sdl2-installed/bin/sdl2-config
 perl -w -pi -e "s#$PWD/emscripten-sdl2-installed#/usr/local#g;" ./emscripten-sdl2-installed/lib/libSDL2.la ./emscripten-sdl2-installed/lib/pkgconfig/sdl2.pc ./emscripten-sdl2-installed/bin/sdl2-config
 mkdir -p ./usr
 mkdir -p ./usr

+ 3 - 3
Engine/lib/sdl/build-scripts/g++-fat.sh

@@ -6,11 +6,11 @@
 
 
 DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
 DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
 
 
-# Intel 32-bit compiler flags (10.5 runtime compatibility)
-GCC_COMPILE_X86="g++ -arch i386 -mmacosx-version-min=10.5 \
+# Intel 32-bit compiler flags (10.6 runtime compatibility)
+GCC_COMPILE_X86="g++ -arch i386 -mmacosx-version-min=10.6 \
 -I/usr/local/include"
 -I/usr/local/include"
 
 
-GCC_LINK_X86="-mmacosx-version-min=10.5"
+GCC_LINK_X86="-mmacosx-version-min=10.6"
 
 
 # Intel 64-bit compiler flags (10.6 runtime compatibility)
 # Intel 64-bit compiler flags (10.6 runtime compatibility)
 GCC_COMPILE_X64="g++ -arch x86_64 -mmacosx-version-min=10.6 \
 GCC_COMPILE_X64="g++ -arch x86_64 -mmacosx-version-min=10.6 \

+ 4 - 4
Engine/lib/sdl/build-scripts/gcc-fat.sh

@@ -6,15 +6,15 @@
 
 
 DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
 DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
 
 
-# Intel 32-bit compiler flags (10.5 runtime compatibility)
-GCC_COMPILE_X86="gcc -arch i386 -mmacosx-version-min=10.5 \
+# Intel 32-bit compiler flags (10.6 runtime compatibility)
+GCC_COMPILE_X86="gcc -arch i386 -mmacosx-version-min=10.6 \
 -I/usr/local/include"
 -I/usr/local/include"
 
 
-GCC_LINK_X86="-mmacosx-version-min=10.5"
+GCC_LINK_X86="-mmacosx-version-min=10.6"
 
 
 # Intel 64-bit compiler flags (10.6 runtime compatibility)
 # Intel 64-bit compiler flags (10.6 runtime compatibility)
 GCC_COMPILE_X64="gcc -arch x86_64 -mmacosx-version-min=10.6 \
 GCC_COMPILE_X64="gcc -arch x86_64 -mmacosx-version-min=10.6 \
--DMAC_OS_X_VERSION_MIN_REQUIRED=1050 \
+-DMAC_OS_X_VERSION_MIN_REQUIRED=1060 \
 -I/usr/local/include"
 -I/usr/local/include"
 
 
 GCC_LINK_X64="-mmacosx-version-min=10.6"
 GCC_LINK_X64="-mmacosx-version-min=10.6"

+ 1 - 3
Engine/lib/sdl/build-scripts/install-sh

@@ -2,6 +2,4 @@
 #
 #
 # Print the current source revision, if available
 # Print the current source revision, if available
 
 
-# FIXME: this prints the tip, which isn't useful if you're on a different
-#  branch, or just not sync'd to the tip.
-hg tip --template 'hg-{rev}:{node|short}' || (echo "hg-0:baadf00d"; exit 1)
+hg parents --template 'hg-{rev}:{node|short}' || (echo "hg-0:baadf00d"; exit 1)

+ 89 - 9
Engine/lib/sdl/build-scripts/strip_fPIC.sh

@@ -105,7 +105,9 @@ macro(CheckALSA)
   if(ALSA)
   if(ALSA)
     CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ASOUNDLIB_H)
     CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ASOUNDLIB_H)
     if(HAVE_ASOUNDLIB_H)
     if(HAVE_ASOUNDLIB_H)
-      CHECK_LIBRARY_EXISTS(asound snd_pcm_open "" HAVE_LIBASOUND)
+      CHECK_LIBRARY_EXISTS(asound snd_pcm_recover "" HAVE_LIBASOUND)
+    endif()
+    if(HAVE_LIBASOUND)
       set(HAVE_ALSA TRUE)
       set(HAVE_ALSA TRUE)
       file(GLOB ALSA_SOURCES ${SDL2_SOURCE_DIR}/src/audio/alsa/*.c)
       file(GLOB ALSA_SOURCES ${SDL2_SOURCE_DIR}/src/audio/alsa/*.c)
       set(SOURCE_FILES ${SOURCE_FILES} ${ALSA_SOURCES})
       set(SOURCE_FILES ${SOURCE_FILES} ${ALSA_SOURCES})
@@ -537,6 +539,27 @@ macro(CheckMir)
     endif()
     endif()
 endmacro()
 endmacro()
 
 
+macro(WaylandProtocolGen _SCANNER _XML _PROTL)
+    set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
+    set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
+
+    add_custom_command(
+        OUTPUT "${_WAYLAND_PROT_H_CODE}"
+        DEPENDS "${_XML}"
+        COMMAND "${_SCANNER}"
+        ARGS client-header "${_XML}" "${_WAYLAND_PROT_H_CODE}"
+    )
+
+    add_custom_command(
+        OUTPUT "${_WAYLAND_PROT_C_CODE}"
+        DEPENDS "${_WAYLAND_PROT_H_CODE}"
+        COMMAND "${_SCANNER}"
+        ARGS code "${_XML}" "${_WAYLAND_PROT_C_CODE}"
+    )
+
+    set(SOURCE_FILES ${SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
+endmacro()
+
 # Requires:
 # Requires:
 # - EGL
 # - EGL
 # - PkgCheckModules
 # - PkgCheckModules
@@ -545,7 +568,51 @@ endmacro()
 # - HAVE_DLOPEN opt
 # - HAVE_DLOPEN opt
 macro(CheckWayland)
 macro(CheckWayland)
   if(VIDEO_WAYLAND)
   if(VIDEO_WAYLAND)
-    pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon)
+    pkg_check_modules(WAYLAND wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon)
+
+    # We have to generate some protocol interface code for some various Wayland features.
+    if(WAYLAND_FOUND)
+      execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-client
+        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+        RESULT_VARIABLE WAYLAND_CORE_PROTOCOL_DIR_RC
+        OUTPUT_VARIABLE WAYLAND_CORE_PROTOCOL_DIR
+        ERROR_QUIET
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+      )
+      if(NOT WAYLAND_CORE_PROTOCOL_DIR_RC EQUAL 0)
+        set(WAYLAND_FOUND FALSE)
+      endif()
+    endif()
+
+    if(WAYLAND_FOUND)
+      execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
+        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+        RESULT_VARIABLE WAYLAND_PROTOCOLS_DIR_RC
+        OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
+        ERROR_QUIET
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+      )
+      if(NOT WAYLAND_PROTOCOLS_DIR_RC EQUAL 0)
+        set(WAYLAND_FOUND FALSE)
+      endif()
+    endif()
+
+    if(WAYLAND_FOUND)
+      execute_process(
+        COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=wayland_scanner wayland-scanner
+        WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+        RESULT_VARIABLE WAYLAND_SCANNER_RC
+        OUTPUT_VARIABLE WAYLAND_SCANNER
+        ERROR_QUIET
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+      )
+      if(NOT WAYLAND_SCANNER_RC EQUAL 0)
+        set(WAYLAND_FOUND FALSE)
+      endif()
+    endif()
+
     if(WAYLAND_FOUND)
     if(WAYLAND_FOUND)
       link_directories(
       link_directories(
           ${WAYLAND_LIBRARY_DIRS}
           ${WAYLAND_LIBRARY_DIRS}
@@ -559,6 +626,17 @@ macro(CheckWayland)
       file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
       file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
       set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
       set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
 
 
+      # We have to generate some protocol interface code for some unstable Wayland features.
+      file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
+      include_directories("${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
+
+      WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_CORE_PROTOCOL_DIR}/wayland.xml" "wayland")
+
+      foreach(_PROTL relative-pointer-unstable-v1 pointer-constraints-unstable-v1)
+        string(REGEX REPLACE "\\-unstable\\-.*$" "" PROTSUBDIR ${_PROTL})
+        WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_PROTOCOLS_DIR}/unstable/${PROTSUBDIR}/${_PROTL}.xml" "${_PROTL}")
+      endforeach()
+
       if(VIDEO_WAYLAND_QT_TOUCH)
       if(VIDEO_WAYLAND_QT_TOUCH)
           set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
           set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
       endif()
       endif()
@@ -679,7 +757,6 @@ macro(CheckOpenGLX11)
       set(SDL_VIDEO_OPENGL 1)
       set(SDL_VIDEO_OPENGL 1)
       set(SDL_VIDEO_OPENGL_GLX 1)
       set(SDL_VIDEO_OPENGL_GLX 1)
       set(SDL_VIDEO_RENDER_OGL 1)
       set(SDL_VIDEO_RENDER_OGL 1)
-      list(APPEND EXTRA_LIBS GL)
     endif()
     endif()
   endif()
   endif()
 endmacro()
 endmacro()
@@ -767,7 +844,8 @@ macro(CheckPTHREAD)
     endif()
     endif()
 
 
     # Run some tests
     # Run some tests
-    set(CMAKE_REQUIRED_FLAGS "${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
+    set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
     if(CMAKE_CROSSCOMPILING)
     if(CMAKE_CROSSCOMPILING)
       set(HAVE_PTHREADS 1)
       set(HAVE_PTHREADS 1)
     else()
     else()
@@ -829,7 +907,7 @@ macro(CheckPTHREAD)
           int main(int argc, char** argv) { return 0; }" HAVE_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_setname_np HAVE_PTHREAD_SETNAME_NP)
       check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP)
       check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP)
-      set(CMAKE_REQUIRED_FLAGS)
+      set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
 
 
       set(SOURCE_FILES ${SOURCE_FILES}
       set(SOURCE_FILES ${SOURCE_FILES}
           ${SDL2_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c
           ${SDL2_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c
@@ -883,7 +961,8 @@ macro(CheckUSBHID)
     endif()
     endif()
   endif()
   endif()
 
 
-  set(CMAKE_REQUIRED_FLAGS "${USB_CFLAGS}")
+  set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+  set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${USB_CFLAGS}")
   set(CMAKE_REQUIRED_LIBRARIES "${USB_LIBS}")
   set(CMAKE_REQUIRED_LIBRARIES "${USB_LIBS}")
   check_c_source_compiles("
   check_c_source_compiles("
        #include <sys/types.h>
        #include <sys/types.h>
@@ -984,7 +1063,7 @@ macro(CheckUSBHID)
     set(HAVE_SDL_JOYSTICK TRUE)
     set(HAVE_SDL_JOYSTICK TRUE)
 
 
     set(CMAKE_REQUIRED_LIBRARIES)
     set(CMAKE_REQUIRED_LIBRARIES)
-    set(CMAKE_REQUIRED_FLAGS)
+    set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
   endif()
   endif()
 endmacro()
 endmacro()
 
 
@@ -998,12 +1077,13 @@ macro(CheckRPI)
     listtostr(VIDEO_RPI_INCLUDE_DIRS VIDEO_RPI_INCLUDE_FLAGS "-I")
     listtostr(VIDEO_RPI_INCLUDE_DIRS VIDEO_RPI_INCLUDE_FLAGS "-I")
     listtostr(VIDEO_RPI_LIBRARY_DIRS VIDEO_RPI_LIBRARY_FLAGS "-L")
     listtostr(VIDEO_RPI_LIBRARY_DIRS VIDEO_RPI_LIBRARY_FLAGS "-L")
 
 
-    set(CMAKE_REQUIRED_FLAGS "${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
+    set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+    set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
     set(CMAKE_REQUIRED_LIBRARIES "${VIDEO_RPI_LIBS}")
     set(CMAKE_REQUIRED_LIBRARIES "${VIDEO_RPI_LIBS}")
     check_c_source_compiles("
     check_c_source_compiles("
         #include <bcm_host.h>
         #include <bcm_host.h>
         int main(int argc, char **argv) {}" HAVE_VIDEO_RPI)
         int main(int argc, char **argv) {}" HAVE_VIDEO_RPI)
-    set(CMAKE_REQUIRED_FLAGS)
+    set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
     set(CMAKE_REQUIRED_LIBRARIES)
     set(CMAKE_REQUIRED_LIBRARIES)
 
 
     if(SDL_VIDEO AND HAVE_VIDEO_RPI)
     if(SDL_VIDEO AND HAVE_VIDEO_RPI)

+ 272 - 17
Engine/lib/sdl/configure

@@ -630,6 +630,7 @@ ac_includes_default="\
 #endif"
 #endif"
 
 
 ac_subst_vars='LTLIBOBJS
 ac_subst_vars='LTLIBOBJS
+WAYLAND_SCANNER
 EXTRA_LDFLAGS
 EXTRA_LDFLAGS
 BUILD_LDFLAGS
 BUILD_LDFLAGS
 EXTRA_CFLAGS
 EXTRA_CFLAGS
@@ -637,6 +638,8 @@ BUILD_CFLAGS
 SDLTEST_OBJECTS
 SDLTEST_OBJECTS
 SDLMAIN_OBJECTS
 SDLMAIN_OBJECTS
 VERSION_OBJECTS
 VERSION_OBJECTS
+GEN_OBJECTS
+GEN_HEADERS
 OBJECTS
 OBJECTS
 INCLUDE
 INCLUDE
 ac_aux_dir
 ac_aux_dir
@@ -846,7 +849,9 @@ enable_video_opengles1
 enable_video_opengles2
 enable_video_opengles2
 enable_libudev
 enable_libudev
 enable_dbus
 enable_dbus
+enable_ime
 enable_ibus
 enable_ibus
+enable_fcitx
 enable_input_tslib
 enable_input_tslib
 enable_pthreads
 enable_pthreads
 enable_pthread_sem
 enable_pthread_sem
@@ -1584,7 +1589,9 @@ Optional Features:
                           include OpenGL ES 2.0 support [[default=yes]]
                           include OpenGL ES 2.0 support [[default=yes]]
   --enable-libudev        enable libudev support [[default=yes]]
   --enable-libudev        enable libudev support [[default=yes]]
   --enable-dbus           enable D-Bus support [[default=yes]]
   --enable-dbus           enable D-Bus support [[default=yes]]
+  --enable-ime            enable IME support [[default=yes]]
   --enable-ibus           enable IBus support [[default=yes]]
   --enable-ibus           enable IBus support [[default=yes]]
+  --enable-fcitx          enable fcitx support [[default=yes]]
   --enable-input-tslib    use the Touchscreen library for input
   --enable-input-tslib    use the Touchscreen library for input
                           [[default=yes]]
                           [[default=yes]]
   --enable-pthreads       use POSIX threads for multi-threading
   --enable-pthreads       use POSIX threads for multi-threading
@@ -2683,9 +2690,9 @@ orig_CFLAGS="$CFLAGS"
 #
 #
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=0
 SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=4
-SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=4
+SDL_MICRO_VERSION=5
+SDL_INTERFACE_AGE=1
+SDL_BINARY_AGE=5
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 
 
@@ -17601,7 +17608,7 @@ LIBS="$ALSA_LIBS $LIBS"
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ALSA_LIBS" >&5
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ALSA_LIBS" >&5
 $as_echo "$ALSA_LIBS" >&6; }
 $as_echo "$ALSA_LIBS" >&6; }
 
 
-min_alsa_version=0.9.0
+min_alsa_version=1.0.11
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libasound headers version >= $min_alsa_version" >&5
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libasound headers version >= $min_alsa_version" >&5
 $as_echo_n "checking for libasound headers version >= $min_alsa_version... " >&6; }
 $as_echo_n "checking for libasound headers version >= $min_alsa_version... " >&6; }
 no_alsa=""
 no_alsa=""
@@ -18650,6 +18657,43 @@ $as_echo "$have_gcc_preferred_stack_boundary" >&6; }
     fi
     fi
 }
 }
 
 
+CheckDeclarationAfterStatement()
+{
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -Wdeclaration-after-statement option" >&5
+$as_echo_n "checking for GCC -Wdeclaration-after-statement option... " >&6; }
+    have_gcc_declaration_after_statement=no
+
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$save_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+    int x = 0;
+
+int
+main ()
+{
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+    have_gcc_declaration_after_statement=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_declaration_after_statement" >&5
+$as_echo "$have_gcc_declaration_after_statement" >&6; }
+    CFLAGS="$save_CFLAGS"
+
+    if test x$have_gcc_declaration_after_statement = xyes; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+    fi
+}
+
 CheckWarnAll()
 CheckWarnAll()
 {
 {
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -Wall option" >&5
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -Wall option" >&5
@@ -18767,9 +18811,12 @@ $as_echo_n "checking for Wayland support... " >&6; }
         if  test x$PKG_CONFIG != xno && \
         if  test x$PKG_CONFIG != xno && \
             test x$video_opengl_egl = xyes && \
             test x$video_opengl_egl = xyes && \
             test x$video_opengles_v2 = xyes; then
             test x$video_opengles_v2 = xyes; then
-            if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
+            if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then
                 WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
+                WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
+                WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
+                WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
                 video_wayland=yes
                 video_wayland=yes
             fi
             fi
         fi
         fi
@@ -18785,8 +18832,11 @@ $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND 1" >>confdefs.h
 $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
 $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
 
 
             fi
             fi
+
+            WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
+
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
+            EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
             # Check whether --enable-wayland-shared was given.
             # Check whether --enable-wayland-shared was given.
 if test "${enable_wayland_shared+set}" = set; then :
 if test "${enable_wayland_shared+set}" = set; then :
   enableval=$enable_wayland_shared;
   enableval=$enable_wayland_shared;
@@ -18928,7 +18978,7 @@ int
 main ()
 main ()
 {
 {
 
 
-                    MirMotionToolType tool = mir_motion_tool_type_mouse;
+                    MirTouchAction actions = mir_touch_actions
 
 
   ;
   ;
   return 0;
   return 0;
@@ -21604,6 +21654,23 @@ $as_echo "#define HAVE_DBUS_DBUS_H 1" >>confdefs.h
     fi
     fi
 }
 }
 
 
+CheckIME()
+{
+    # Check whether --enable-ime was given.
+if test "${enable_ime+set}" = set; then :
+  enableval=$enable_ime;
+else
+  enable_ime=yes
+fi
+
+    if test x$enable_ime = xyes; then
+
+$as_echo "#define SDL_USE_IME 1" >>confdefs.h
+
+            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+    fi
+}
+
 CheckIBus()
 CheckIBus()
 {
 {
     # Check whether --enable-ibus was given.
     # Check whether --enable-ibus was given.
@@ -21677,7 +21744,11 @@ fi
 
 
             CFLAGS="$save_CFLAGS"
             CFLAGS="$save_CFLAGS"
             if test x$have_ibus_ibus_h_hdr = xyes; then
             if test x$have_ibus_ibus_h_hdr = xyes; then
-                if test x$enable_dbus != xyes; then
+                if test x$enable_ime != xyes; then
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IME support is required for IBus." >&5
+$as_echo "$as_me: WARNING: IME support is required for IBus." >&2;}
+                    have_ibus_ibus_h_hdr=no
+                elif test x$enable_dbus != xyes; then
                     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: DBus support is required for IBus." >&5
                     { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: DBus support is required for IBus." >&5
 $as_echo "$as_me: WARNING: DBus support is required for IBus." >&2;}
 $as_echo "$as_me: WARNING: DBus support is required for IBus." >&2;}
                     have_ibus_ibus_h_hdr=no
                     have_ibus_ibus_h_hdr=no
@@ -21697,6 +21768,90 @@ $as_echo "#define HAVE_IBUS_IBUS_H 1" >>confdefs.h
     fi
     fi
 }
 }
 
 
+CheckFcitx()
+{
+    # Check whether --enable-fcitx was given.
+if test "${enable_fcitx+set}" = set; then :
+  enableval=$enable_fcitx;
+else
+  enable_fcitx=yes
+fi
+
+    if test x$enable_fcitx = xyes; then
+        # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PKG_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+  ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+        if test x$PKG_CONFIG != xno; then
+            FCITX_CFLAGS=`$PKG_CONFIG --cflags fcitx`
+            CFLAGS="$CFLAGS $FCITX_CFLAGS"
+            ac_fn_c_check_header_mongrel "$LINENO" "fcitx/frontend.h" "ac_cv_header_fcitx_frontend_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcitx_frontend_h" = xyes; then :
+  have_fcitx_frontend_h_hdr=yes
+else
+  have_fcitx_frontend_h_hdr=no
+fi
+
+
+            CFLAGS="$save_CFLAGS"
+            if test x$have_fcitx_frontend_h_hdr = xyes; then
+                if test x$enable_ime != xyes; then
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IME support is required for fcitx." >&5
+$as_echo "$as_me: WARNING: IME support is required for fcitx." >&2;}
+                    have_fcitx_frontend_h_hdr=no
+                elif test x$enable_dbus != xyes; then
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: DBus support is required for fcitx." >&5
+$as_echo "$as_me: WARNING: DBus support is required for fcitx." >&2;}
+                    have_fcitx_frontend_h_hdr=no
+                else
+
+$as_echo "#define HAVE_FCITX_FRONTEND_H 1" >>confdefs.h
+
+                    EXTRA_CFLAGS="$EXTRA_CFLAGS $FCITX_CFLAGS"
+                    SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
+               fi
+            fi
+        fi
+    fi
+}
+
 CheckTslib()
 CheckTslib()
 {
 {
     # Check whether --enable-input-tslib was given.
     # Check whether --enable-input-tslib was given.
@@ -22894,6 +23049,8 @@ fi
 
 
 }
 }
 
 
+CheckWarnAll
+
 case "$host" in
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
         case "$host" in
         case "$host" in
@@ -22962,6 +23119,7 @@ case "$host" in
             *-*-minix*)         ARCH=minix ;;
             *-*-minix*)         ARCH=minix ;;
         esac
         esac
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -22982,7 +23140,9 @@ case "$host" in
         CheckWayland
         CheckWayland
         CheckLibUDev
         CheckLibUDev
         CheckDBus
         CheckDBus
+        CheckIME
         CheckIBus
         CheckIBus
+        CheckFcitx
         case $ARCH in
         case $ARCH in
           linux)
           linux)
               CheckInputEvents
               CheckInputEvents
@@ -23392,6 +23552,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
         ARCH=ios
         ARCH=ios
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -23402,7 +23563,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
 
 
         # Set up files for the audio library
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
         if test x$enable_audio = xyes; then
-            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             have_audio=yes
             have_audio=yes
         fi
         fi
@@ -23461,6 +23622,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -23476,7 +23638,8 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
 
 
 $as_echo "#define SDL_AUDIO_DRIVER_COREAUDIO 1" >>confdefs.h
 $as_echo "#define SDL_AUDIO_DRIVER_COREAUDIO 1" >>confdefs.h
 
 
-            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
+            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             have_audio=yes
             have_audio=yes
         fi
         fi
@@ -23494,8 +23657,8 @@ $as_echo "#define SDL_JOYSTICK_IOKIT 1" >>confdefs.h
 $as_echo "#define SDL_HAPTIC_IOKIT 1" >>confdefs.h
 $as_echo "#define SDL_HAPTIC_IOKIT 1" >>confdefs.h
 
 
             SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
             SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
-            have_haptic=yes
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
+            have_haptic=yes
         fi
         fi
         # Set up files for the power library
         # Set up files for the power library
         if test x$enable_power = xyes; then
         if test x$enable_power = xyes; then
@@ -23532,10 +23695,6 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
-        # If audio is used, add the AudioUnit framework
-        if test x$enable_audio = xyes; then
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
-        fi
         ;;
         ;;
     *-nacl|*-pnacl)
     *-nacl|*-pnacl)
         ARCH=nacl
         ARCH=nacl
@@ -23581,6 +23740,7 @@ $as_echo "#define SDL_AUDIO_DRIVER_EMSCRIPTEN 1" >>confdefs.h
         fi
         fi
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -23630,8 +23790,6 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
         ;;
         ;;
 esac
 esac
 
 
-CheckWarnAll
-
 # Verify that we have all the platform specific files we need
 # Verify that we have all the platform specific files we need
 
 
 if test x$have_joystick != xyes; then
 if test x$have_joystick != xyes; then
@@ -23687,6 +23845,57 @@ if test x$SDLMAIN_SOURCES = x; then
 fi
 fi
 SDLTEST_SOURCES="$srcdir/src/test/*.c"
 SDLTEST_SOURCES="$srcdir/src/test/*.c"
 
 
+if test x$video_wayland = xyes; then
+    WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
+    WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
+    WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+        sed 's,[^ ]\+,\\$(gen)/&-protocol.c,g'`
+    WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+        sed 's,[^ ]\+,\\$(gen)/&-client-protocol.h,g'`
+    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
+    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+
+    WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
+
+    WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
+
+    WAYLAND_CORE_PROTOCOL_OBJECT="
+\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE
+	\$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@"
+
+    WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
+$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
+$WAYLAND_CORE_PROTOCOL_OBJECT
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+"
+fi
+
 OBJECTS=`echo $SOURCES`
 OBJECTS=`echo $SOURCES`
 DEPENDS=`echo $SOURCES | tr ' ' '\n'`
 DEPENDS=`echo $SOURCES | tr ' ' '\n'`
 for EXT in asm cc m c S; do
 for EXT in asm cc m c S; do
@@ -23696,6 +23905,8 @@ for EXT in asm cc m c S; do
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
 done
 done
 
 
+GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[^ ]*/\([^ ]*\)\.c,$(objects)/\1.lo,g'`
+
 VERSION_OBJECTS=`echo $VERSION_SOURCES`
 VERSION_OBJECTS=`echo $VERSION_SOURCES`
 VERSION_DEPENDS=`echo $VERSION_SOURCES`
 VERSION_DEPENDS=`echo $VERSION_SOURCES`
 VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[^ ]*/\([^ ]*\)\.rc,$(objects)/\1.o,g'`
 VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[^ ]*/\([^ ]*\)\.rc,$(objects)/\1.o,g'`
@@ -23722,6 +23933,36 @@ SDLTEST_DEPENDS=`echo "$SDLTEST_DEPENDS" | sed "s,\\([^ ]*\\)/\\([^ ]*\\)\\.c,\\
 if test "x$enable_rpath" = "xyes"; then
 if test "x$enable_rpath" = "xyes"; then
   if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
   if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
     SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
     SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker option --enable-new-dtags" >&5
+$as_echo_n "checking for linker option --enable-new-dtags... " >&6; }
+    have_enable_new_dtags=no
+    save_LDFLAGS="$LDFLAGS"
+    LDFLAGS="$LDFLAGS -Wl,--enable-new-dtags"
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+    have_enable_new_dtags=yes
+    SDL_RLD_FLAGS="$SDL_RLD_FLAGS -Wl,--enable-new-dtags"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+    LDFLAGS="$save_LDFLAGS"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_enable_new_dtags" >&5
+$as_echo "$have_enable_new_dtags" >&6; }
   fi
   fi
   if test $ARCH = solaris; then
   if test $ARCH = solaris; then
     SDL_RLD_FLAGS="-R\${libdir}"
     SDL_RLD_FLAGS="-R\${libdir}"
@@ -23767,6 +24008,9 @@ fi
 
 
 
 
 
 
+
+
+
 cat >Makefile.rules <<__EOF__
 cat >Makefile.rules <<__EOF__
 
 
 # Build rules for objects
 # Build rules for objects
@@ -23778,6 +24022,7 @@ $DEPENDS
 $VERSION_DEPENDS
 $VERSION_DEPENDS
 $SDLMAIN_DEPENDS
 $SDLMAIN_DEPENDS
 $SDLTEST_DEPENDS
 $SDLTEST_DEPENDS
+$WAYLAND_PROTOCOLS_DEPENDS
 __EOF__
 __EOF__
 
 
 ac_config_files="$ac_config_files Makefile:Makefile.in:Makefile.rules sdl2-config sdl2-config.cmake SDL2.spec sdl2.pc"
 ac_config_files="$ac_config_files Makefile:Makefile.in:Makefile.rules sdl2-config sdl2-config.cmake SDL2.spec sdl2.pc"
@@ -23810,11 +24055,21 @@ if test x$have_dbus_dbus_h_hdr = xyes; then
 else
 else
     SUMMARY="${SUMMARY}Using dbus      : NO\n"
     SUMMARY="${SUMMARY}Using dbus      : NO\n"
 fi
 fi
+if test x$enable_ime = xyes; then
+    SUMMARY="${SUMMARY}Using ime       : YES\n"
+else
+    SUMMARY="${SUMMARY}Using ime       : NO\n"
+fi
 if test x$have_ibus_ibus_h_hdr = xyes; then
 if test x$have_ibus_ibus_h_hdr = xyes; then
     SUMMARY="${SUMMARY}Using ibus      : YES\n"
     SUMMARY="${SUMMARY}Using ibus      : YES\n"
 else
 else
     SUMMARY="${SUMMARY}Using ibus      : NO\n"
     SUMMARY="${SUMMARY}Using ibus      : NO\n"
 fi
 fi
+if test x$have_fcitx_frontend_h_hdr = xyes; then
+    SUMMARY="${SUMMARY}Using fcitx     : YES\n"
+else
+    SUMMARY="${SUMMARY}Using fcitx     : NO\n"
+fi
 ac_config_commands="$ac_config_commands summary"
 ac_config_commands="$ac_config_commands summary"
 
 
 
 

+ 180 - 20
Engine/lib/sdl/configure.in

@@ -20,9 +20,9 @@ dnl Set various version strings - taken gratefully from the GTk sources
 #
 #
 SDL_MAJOR_VERSION=2
 SDL_MAJOR_VERSION=2
 SDL_MINOR_VERSION=0
 SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=4
-SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=4
+SDL_MICRO_VERSION=5
+SDL_INTERFACE_AGE=1
+SDL_BINARY_AGE=5
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
 
 
 AC_SUBST(SDL_MAJOR_VERSION)
 AC_SUBST(SDL_MAJOR_VERSION)
@@ -770,7 +770,7 @@ CheckALSA()
 AC_HELP_STRING([--enable-alsa], [support the ALSA audio API [[default=yes]]]),
 AC_HELP_STRING([--enable-alsa], [support the ALSA audio API [[default=yes]]]),
                   , enable_alsa=yes)
                   , enable_alsa=yes)
     if test x$enable_audio = xyes -a x$enable_alsa = xyes; then
     if test x$enable_audio = xyes -a x$enable_alsa = xyes; then
-        AM_PATH_ALSA(0.9.0, have_alsa=yes, have_alsa=no)
+        AM_PATH_ALSA(1.0.11, have_alsa=yes, have_alsa=no)
         # Restore all flags from before the ALSA detection runs
         # Restore all flags from before the ALSA detection runs
         CFLAGS="$alsa_save_CFLAGS"
         CFLAGS="$alsa_save_CFLAGS"
         LDFLAGS="$alsa_save_LDFLAGS"
         LDFLAGS="$alsa_save_LDFLAGS"
@@ -1124,6 +1124,30 @@ CheckStackBoundary()
     fi
     fi
 }
 }
 
 
+dnl See if GCC's -Wdeclaration-after-statement is supported.
+dnl  This lets us catch things that would fail on a C89 compiler when using
+dnl  a modern GCC.
+CheckDeclarationAfterStatement()
+{
+    AC_MSG_CHECKING(for GCC -Wdeclaration-after-statement option)
+    have_gcc_declaration_after_statement=no
+
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$save_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+    AC_TRY_COMPILE([
+    int x = 0;
+    ],[
+    ],[
+    have_gcc_declaration_after_statement=yes
+    ])
+    AC_MSG_RESULT($have_gcc_declaration_after_statement)
+    CFLAGS="$save_CFLAGS"
+
+    if test x$have_gcc_declaration_after_statement = xyes; then
+        EXTRA_CFLAGS="$EXTRA_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+    fi
+}
+
 dnl See if GCC's -Wall is supported.
 dnl See if GCC's -Wall is supported.
 CheckWarnAll()
 CheckWarnAll()
 {
 {
@@ -1177,9 +1201,12 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
         if  test x$PKG_CONFIG != xno && \
         if  test x$PKG_CONFIG != xno && \
             test x$video_opengl_egl = xyes && \
             test x$video_opengl_egl = xyes && \
             test x$video_opengles_v2 = xyes; then
             test x$video_opengles_v2 = xyes; then
-            if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
+            if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then
                 WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
                 WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
+                WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
+                WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
+                WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
                 video_wayland=yes
                 video_wayland=yes
             fi
             fi
         fi
         fi
@@ -1190,8 +1217,11 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
             if test x$enable_video_wayland_qt_touch = xyes; then
             if test x$enable_video_wayland_qt_touch = xyes; then
                 AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ])
                 AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ])
             fi
             fi
+
+            WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
+
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
             SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
-            EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
+            EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
             AC_ARG_ENABLE(wayland-shared,
             AC_ARG_ENABLE(wayland-shared,
 AC_HELP_STRING([--enable-wayland-shared], [dynamically load Wayland support [[default=maybe]]]),
 AC_HELP_STRING([--enable-wayland-shared], [dynamically load Wayland support [[default=maybe]]]),
                           , enable_wayland_shared=maybe)
                           , enable_wayland_shared=maybe)
@@ -1260,12 +1290,12 @@ AC_HELP_STRING([--enable-video-mir], [use Mir video driver [[default=yes]]]),
                 MIR_LIBS=`$PKG_CONFIG --libs mirclient egl xkbcommon`
                 MIR_LIBS=`$PKG_CONFIG --libs mirclient egl xkbcommon`
                 save_CFLAGS="$CFLAGS"
                 save_CFLAGS="$CFLAGS"
                 CFLAGS="$save_CFLAGS $MIR_CFLAGS"
                 CFLAGS="$save_CFLAGS $MIR_CFLAGS"
-                
-                dnl This will disable Mir on Ubuntu < 14.04
+
+                dnl This will disable Mir if >= v0.25 is not available
                 AC_TRY_COMPILE([
                 AC_TRY_COMPILE([
                 #include <mir_toolkit/mir_client_library.h>
                 #include <mir_toolkit/mir_client_library.h>
                 ],[
                 ],[
-                    MirMotionToolType tool = mir_motion_tool_type_mouse;
+                    MirTouchAction actions = mir_touch_actions
                 ],[
                 ],[
                 video_mir=yes
                 video_mir=yes
                 ])
                 ])
@@ -2230,6 +2260,18 @@ AC_HELP_STRING([--enable-dbus], [enable D-Bus support [[default=yes]]]),
     fi
     fi
 }
 }
 
 
+dnl See if the platform wanna IME support.
+CheckIME()
+{
+    AC_ARG_ENABLE(ime,
+AC_HELP_STRING([--enable-ime], [enable IME support [[default=yes]]]),
+                  , enable_ime=yes)
+    if test x$enable_ime = xyes; then
+        AC_DEFINE(SDL_USE_IME, 1, [ ])
+            SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+    fi
+}
+
 dnl See if the platform has libibus IME support.
 dnl See if the platform has libibus IME support.
 CheckIBus()
 CheckIBus()
 {
 {
@@ -2250,7 +2292,10 @@ AC_HELP_STRING([--enable-ibus], [enable IBus support [[default=yes]]]),
                             have_inotify_inotify_h_hdr=no)
                             have_inotify_inotify_h_hdr=no)
             CFLAGS="$save_CFLAGS"
             CFLAGS="$save_CFLAGS"
             if test x$have_ibus_ibus_h_hdr = xyes; then
             if test x$have_ibus_ibus_h_hdr = xyes; then
-                if test x$enable_dbus != xyes; then
+                if test x$enable_ime != xyes; then
+                    AC_MSG_WARN([IME support is required for IBus.])
+                    have_ibus_ibus_h_hdr=no
+                elif test x$enable_dbus != xyes; then
                     AC_MSG_WARN([DBus support is required for IBus.])
                     AC_MSG_WARN([DBus support is required for IBus.])
                     have_ibus_ibus_h_hdr=no
                     have_ibus_ibus_h_hdr=no
                 elif test x$have_inotify_inotify_h_hdr != xyes; then
                 elif test x$have_inotify_inotify_h_hdr != xyes; then
@@ -2266,6 +2311,38 @@ AC_HELP_STRING([--enable-ibus], [enable IBus support [[default=yes]]]),
     fi
     fi
 }
 }
 
 
+dnl See if the platform has fcitx IME support.
+CheckFcitx()
+{
+    AC_ARG_ENABLE(fcitx,
+AC_HELP_STRING([--enable-fcitx], [enable fcitx support [[default=yes]]]),
+                  , enable_fcitx=yes)
+    if test x$enable_fcitx = xyes; then
+        AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+        if test x$PKG_CONFIG != xno; then
+            FCITX_CFLAGS=`$PKG_CONFIG --cflags fcitx`
+            CFLAGS="$CFLAGS $FCITX_CFLAGS"
+            AC_CHECK_HEADER(fcitx/frontend.h,
+                            have_fcitx_frontend_h_hdr=yes,
+                            have_fcitx_frontend_h_hdr=no)
+            CFLAGS="$save_CFLAGS"
+            if test x$have_fcitx_frontend_h_hdr = xyes; then
+                if test x$enable_ime != xyes; then
+                    AC_MSG_WARN([IME support is required for fcitx.])
+                    have_fcitx_frontend_h_hdr=no
+                elif test x$enable_dbus != xyes; then
+                    AC_MSG_WARN([DBus support is required for fcitx.])
+                    have_fcitx_frontend_h_hdr=no
+                else
+                    AC_DEFINE(HAVE_FCITX_FRONTEND_H, 1, [ ])
+                    EXTRA_CFLAGS="$EXTRA_CFLAGS $FCITX_CFLAGS"
+                    SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
+               fi
+            fi
+        fi
+    fi
+}
+
 dnl See if we can use the Touchscreen input library
 dnl See if we can use the Touchscreen input library
 CheckTslib()
 CheckTslib()
 {
 {
@@ -2801,6 +2878,9 @@ AC_HELP_STRING([--enable-rpath], [use an rpath when linking SDL [[default=yes]]]
                   , enable_rpath=yes)
                   , enable_rpath=yes)
 }
 }
 
 
+dnl Do this on all platforms, before everything else (other things might want to override it).
+CheckWarnAll
+
 dnl Set up the configuration based on the host platform!
 dnl Set up the configuration based on the host platform!
 case "$host" in
 case "$host" in
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
     *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
@@ -2870,6 +2950,7 @@ case "$host" in
             *-*-minix*)         ARCH=minix ;;
             *-*-minix*)         ARCH=minix ;;
         esac
         esac
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -2890,7 +2971,9 @@ case "$host" in
         CheckWayland
         CheckWayland
         CheckLibUDev
         CheckLibUDev
         CheckDBus
         CheckDBus
+        CheckIME
         CheckIBus
         CheckIBus
+        CheckFcitx
         case $ARCH in
         case $ARCH in
           linux)
           linux)
               CheckInputEvents
               CheckInputEvents
@@ -3196,6 +3279,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         ARCH=ios
         ARCH=ios
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -3206,7 +3290,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
 
 
         # Set up files for the audio library
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
         if test x$enable_audio = xyes; then
-            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             have_audio=yes
             have_audio=yes
         fi
         fi
@@ -3265,6 +3349,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
         EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -3278,7 +3363,8 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         # Set up files for the audio library
         # Set up files for the audio library
         if test x$enable_audio = xyes; then
         if test x$enable_audio = xyes; then
             AC_DEFINE(SDL_AUDIO_DRIVER_COREAUDIO, 1, [ ])
             AC_DEFINE(SDL_AUDIO_DRIVER_COREAUDIO, 1, [ ])
-            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+            SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
+            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             SUMMARY_audio="${SUMMARY_audio} coreaudio"
             have_audio=yes
             have_audio=yes
         fi
         fi
@@ -3292,8 +3378,8 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         if test x$enable_haptic = xyes; then
         if test x$enable_haptic = xyes; then
             AC_DEFINE(SDL_HAPTIC_IOKIT, 1, [ ])
             AC_DEFINE(SDL_HAPTIC_IOKIT, 1, [ ])
             SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
             SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
-            have_haptic=yes
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
             EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
+            have_haptic=yes
         fi
         fi
         # Set up files for the power library
         # Set up files for the power library
         if test x$enable_power = xyes; then
         if test x$enable_power = xyes; then
@@ -3324,10 +3410,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
         EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
-        # If audio is used, add the AudioUnit framework
-        if test x$enable_audio = xyes; then
-            EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
-        fi
         ;;
         ;;
     *-nacl|*-pnacl)
     *-nacl|*-pnacl)
         ARCH=nacl
         ARCH=nacl
@@ -3366,6 +3448,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         fi
         fi
 
 
         CheckVisibilityHidden
         CheckVisibilityHidden
+        CheckDeclarationAfterStatement
         CheckDummyVideo
         CheckDummyVideo
         CheckDiskAudio
         CheckDiskAudio
         CheckDummyAudio
         CheckDummyAudio
@@ -3407,9 +3490,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
         ;;
         ;;
 esac
 esac
 
 
-dnl Do this on all platforms, after everything else.
-CheckWarnAll
-
 # Verify that we have all the platform specific files we need
 # Verify that we have all the platform specific files we need
 
 
 if test x$have_joystick != xyes; then
 if test x$have_joystick != xyes; then
@@ -3453,6 +3533,57 @@ if test x$SDLMAIN_SOURCES = x; then
 fi
 fi
 SDLTEST_SOURCES="$srcdir/src/test/*.c"
 SDLTEST_SOURCES="$srcdir/src/test/*.c"
 
 
+if test x$video_wayland = xyes; then
+    WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
+    WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
+    WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+        sed 's,[[^ ]]\+,\\$(gen)/&-protocol.c,g'`
+    WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+        sed 's,[[^ ]]\+,\\$(gen)/&-client-protocol.h,g'`
+    GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
+    GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+
+    WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
+
+    WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+	\$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+	\$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
+
+    WAYLAND_CORE_PROTOCOL_OBJECT="
+\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE
+	\$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@"
+
+    WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+	\\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+	\\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+        do echo ; echo \$p | sed\
+        "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
+    WAYLAND_PROTOCOLS_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
+$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
+$WAYLAND_CORE_PROTOCOL_OBJECT
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+"
+fi
+
 OBJECTS=`echo $SOURCES`
 OBJECTS=`echo $SOURCES`
 DEPENDS=`echo $SOURCES | tr ' ' '\n'`
 DEPENDS=`echo $SOURCES | tr ' ' '\n'`
 for EXT in asm cc m c S; do
 for EXT in asm cc m c S; do
@@ -3462,6 +3593,8 @@ for EXT in asm cc m c S; do
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
 	\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
 done
 done
 
 
+GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[[^ ]]*/\([[^ ]]*\)\.c,$(objects)/\1.lo,g'`
+
 VERSION_OBJECTS=`echo $VERSION_SOURCES`
 VERSION_OBJECTS=`echo $VERSION_SOURCES`
 VERSION_DEPENDS=`echo $VERSION_SOURCES`
 VERSION_DEPENDS=`echo $VERSION_SOURCES`
 VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[[^ ]]*/\([[^ ]]*\)\.rc,$(objects)/\1.o,g'`
 VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[[^ ]]*/\([[^ ]]*\)\.rc,$(objects)/\1.o,g'`
@@ -3488,6 +3621,19 @@ SDLTEST_DEPENDS=`echo "$SDLTEST_DEPENDS" | sed "s,\\([[^ ]]*\\)/\\([[^ ]]*\\)\\.
 if test "x$enable_rpath" = "xyes"; then
 if test "x$enable_rpath" = "xyes"; then
   if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
   if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
     SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
     SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
+
+    AC_MSG_CHECKING(for linker option --enable-new-dtags)
+    have_enable_new_dtags=no
+    save_LDFLAGS="$LDFLAGS"
+    LDFLAGS="$LDFLAGS -Wl,--enable-new-dtags"
+    AC_TRY_LINK([
+    ],[
+    ],[
+    have_enable_new_dtags=yes
+    SDL_RLD_FLAGS="$SDL_RLD_FLAGS -Wl,--enable-new-dtags"
+    ])
+    LDFLAGS="$save_LDFLAGS"
+    AC_MSG_RESULT($have_enable_new_dtags)
   fi
   fi
   if test $ARCH = solaris; then
   if test $ARCH = solaris; then
     SDL_RLD_FLAGS="-R\${libdir}"
     SDL_RLD_FLAGS="-R\${libdir}"
@@ -3526,6 +3672,8 @@ dnl Expand the sources and objects needed to build the library
 AC_SUBST(ac_aux_dir)
 AC_SUBST(ac_aux_dir)
 AC_SUBST(INCLUDE)
 AC_SUBST(INCLUDE)
 AC_SUBST(OBJECTS)
 AC_SUBST(OBJECTS)
+AC_SUBST(GEN_HEADERS)
+AC_SUBST(GEN_OBJECTS)
 AC_SUBST(VERSION_OBJECTS)
 AC_SUBST(VERSION_OBJECTS)
 AC_SUBST(SDLMAIN_OBJECTS)
 AC_SUBST(SDLMAIN_OBJECTS)
 AC_SUBST(SDLTEST_OBJECTS)
 AC_SUBST(SDLTEST_OBJECTS)
@@ -3534,6 +3682,7 @@ AC_SUBST(EXTRA_CFLAGS)
 AC_SUBST(BUILD_LDFLAGS)
 AC_SUBST(BUILD_LDFLAGS)
 AC_SUBST(EXTRA_LDFLAGS)
 AC_SUBST(EXTRA_LDFLAGS)
 AC_SUBST(WINDRES)
 AC_SUBST(WINDRES)
+AC_SUBST(WAYLAND_SCANNER)
 
 
 cat >Makefile.rules <<__EOF__
 cat >Makefile.rules <<__EOF__
 
 
@@ -3546,6 +3695,7 @@ $DEPENDS
 $VERSION_DEPENDS
 $VERSION_DEPENDS
 $SDLMAIN_DEPENDS
 $SDLMAIN_DEPENDS
 $SDLTEST_DEPENDS
 $SDLTEST_DEPENDS
+$WAYLAND_PROTOCOLS_DEPENDS
 __EOF__
 __EOF__
 
 
 AC_CONFIG_FILES([
 AC_CONFIG_FILES([
@@ -3578,11 +3728,21 @@ if test x$have_dbus_dbus_h_hdr = xyes; then
 else
 else
     SUMMARY="${SUMMARY}Using dbus      : NO\n"
     SUMMARY="${SUMMARY}Using dbus      : NO\n"
 fi
 fi
+if test x$enable_ime = xyes; then
+    SUMMARY="${SUMMARY}Using ime       : YES\n"
+else
+    SUMMARY="${SUMMARY}Using ime       : NO\n"
+fi
 if test x$have_ibus_ibus_h_hdr = xyes; then
 if test x$have_ibus_ibus_h_hdr = xyes; then
     SUMMARY="${SUMMARY}Using ibus      : YES\n"
     SUMMARY="${SUMMARY}Using ibus      : YES\n"
 else
 else
     SUMMARY="${SUMMARY}Using ibus      : NO\n"
     SUMMARY="${SUMMARY}Using ibus      : NO\n"
 fi
 fi
+if test x$have_fcitx_frontend_h_hdr = xyes; then
+    SUMMARY="${SUMMARY}Using fcitx     : YES\n"
+else
+    SUMMARY="${SUMMARY}Using fcitx     : NO\n"
+fi
 AC_CONFIG_COMMANDS([summary], [echo -en "$SUMMARY"], [SUMMARY="$SUMMARY"])
 AC_CONFIG_COMMANDS([summary], [echo -en "$SUMMARY"], [SUMMARY="$SUMMARY"])
 
 
 AC_OUTPUT
 AC_OUTPUT

+ 6 - 0
Engine/lib/sdl/debian/changelog

@@ -1,3 +1,9 @@
+libsdl2 (2.0.4) UNRELEASED; urgency=low
+
+  * Updated SDL to version 2.0.4
+
+ -- Sam Lantinga <[email protected]>  Thu, 07 Jan 2016 11:02:39 -0800
+
 libsdl2 (2.0.3) UNRELEASED; urgency=low
 libsdl2 (2.0.3) UNRELEASED; urgency=low
 
 
   * Updated SDL to version 2.0.3
   * Updated SDL to version 2.0.3

+ 0 - 11
Engine/lib/sdl/debian/copyright

@@ -31,10 +31,6 @@ Copyright: 1995 Erik Corry
            1995 Brown University
            1995 Brown University
 License: BrownUn_UnCalifornia_ErikCorry
 License: BrownUn_UnCalifornia_ErikCorry
 
 
-Files: src/stdlib/SDL_qsort.c
-Copyright: 1998 Gareth McCaughan
-License: Gareth_McCaughan
-
 Files: src/test/SDL_test_md5.c
 Files: src/test/SDL_test_md5.c
 Copyright: 1997-2016 Sam Lantinga <[email protected]>
 Copyright: 1997-2016 Sam Lantinga <[email protected]>
            1990 RSA Data Security, Inc.
            1990 RSA Data Security, Inc.
@@ -270,13 +266,6 @@ License: BrownUn_UnCalifornia_ErikCorry
   * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
   * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
   */
   */
 
 
-License: Gareth_McCaughan
-  You may use it in anything you like; you may make money
-  out of it; you may distribute it in object form or as
-  part of an executable without including source code;
-  you don't have to credit me. (But it would be nice if
-  you did.)
-
 License: Johnson_M._Hart
 License: Johnson_M._Hart
   Permission is granted for any and all use providing that this
   Permission is granted for any and all use providing that this
   copyright is properly acknowledged.
   copyright is properly acknowledged.

+ 1 - 0
Engine/lib/sdl/debian/libsdl2-dev.install

@@ -5,4 +5,5 @@ usr/lib/*/libSDL2.a
 usr/lib/*/libSDL2main.a
 usr/lib/*/libSDL2main.a
 usr/lib/*/libSDL2_test.a
 usr/lib/*/libSDL2_test.a
 usr/lib/*/pkgconfig/sdl2.pc
 usr/lib/*/pkgconfig/sdl2.pc
+usr/lib/*/cmake/SDL2/sdl2-config.cmake
 usr/share/aclocal/sdl2.m4
 usr/share/aclocal/sdl2.m4

+ 10 - 10
Engine/lib/sdl/debian/rules

@@ -72,14 +72,14 @@ extern "C" {
  *  specify the subsystems which you will be using in your application.
  *  specify the subsystems which you will be using in your application.
  */
  */
 /* @{ */
 /* @{ */
-#define SDL_INIT_TIMER          0x00000001
-#define SDL_INIT_AUDIO          0x00000010
-#define SDL_INIT_VIDEO          0x00000020  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
-#define SDL_INIT_JOYSTICK       0x00000200  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
-#define SDL_INIT_HAPTIC         0x00001000
-#define SDL_INIT_GAMECONTROLLER 0x00002000  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
-#define SDL_INIT_EVENTS         0x00004000
-#define SDL_INIT_NOPARACHUTE    0x00100000  /**< compatibility; this flag is ignored. */
+#define SDL_INIT_TIMER          0x00000001u
+#define SDL_INIT_AUDIO          0x00000010u
+#define SDL_INIT_VIDEO          0x00000020u  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK       0x00000200u  /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC         0x00001000u
+#define SDL_INIT_GAMECONTROLLER 0x00002000u  /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS         0x00004000u
+#define SDL_INIT_NOPARACHUTE    0x00100000u  /**< compatibility; this flag is ignored. */
 #define SDL_INIT_EVERYTHING ( \
 #define SDL_INIT_EVERYTHING ( \
                 SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                 SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                 SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
                 SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
@@ -95,8 +95,8 @@ extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
  *  This function initializes specific SDL subsystems
  *  This function initializes specific SDL subsystems
  *
  *
  *  Subsystem initialization is ref-counted, you must call
  *  Subsystem initialization is ref-counted, you must call
- *  SDL_QuitSubSystem for each SDL_InitSubSystem to correctly
- *  shutdown a subsystem manually (or call SDL_Quit to force shutdown).
+ *  SDL_QuitSubSystem() for each SDL_InitSubSystem() to correctly
+ *  shutdown a subsystem manually (or call SDL_Quit() to force shutdown).
  *  If a subsystem is already loaded then this call will
  *  If a subsystem is already loaded then this call will
  *  increase the ref-count and return.
  *  increase the ref-count and return.
  */
  */

+ 81 - 14
Engine/lib/sdl/include/SDL_audio.h

@@ -278,7 +278,8 @@ extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
  *      protect data structures that it accesses by calling SDL_LockAudio()
  *      protect data structures that it accesses by calling SDL_LockAudio()
  *      and SDL_UnlockAudio() in your code. Alternately, you may pass a NULL
  *      and SDL_UnlockAudio() in your code. Alternately, you may pass a NULL
  *      pointer here, and call SDL_QueueAudio() with some frequency, to queue
  *      pointer here, and call SDL_QueueAudio() with some frequency, to queue
- *      more audio samples to be played.
+ *      more audio samples to be played (or for capture devices, call
+ *      SDL_DequeueAudio() with some frequency, to obtain audio samples).
  *    - \c desired->userdata is passed as the first parameter to your callback
  *    - \c desired->userdata is passed as the first parameter to your callback
  *      function. If you passed a NULL callback, this value is ignored.
  *      function. If you passed a NULL callback, this value is ignored.
  *
  *
@@ -482,6 +483,10 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
 /**
 /**
  *  Queue more audio on non-callback devices.
  *  Queue more audio on non-callback devices.
  *
  *
+ *  (If you are looking to retrieve queued audio from a non-callback capture
+ *  device, you want SDL_DequeueAudio() instead. This will return -1 to
+ *  signify an error if you use it with capture devices.)
+ *
  *  SDL offers two ways to feed audio to the device: you can either supply a
  *  SDL offers two ways to feed audio to the device: you can either supply a
  *  callback that SDL triggers with some frequency to obtain more audio
  *  callback that SDL triggers with some frequency to obtain more audio
  *  (pull method), or you can supply no callback, and then SDL will expect
  *  (pull method), or you can supply no callback, and then SDL will expect
@@ -516,21 +521,76 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
  */
  */
 extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
 extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
 
 
+/**
+ *  Dequeue more audio on non-callback devices.
+ *
+ *  (If you are looking to queue audio for output on a non-callback playback
+ *  device, you want SDL_QueueAudio() instead. This will always return 0
+ *  if you use it with playback devices.)
+ *
+ *  SDL offers two ways to retrieve audio from a capture device: you can
+ *  either supply a callback that SDL triggers with some frequency as the
+ *  device records more audio data, (push method), or you can supply no
+ *  callback, and then SDL will expect you to retrieve data at regular
+ *  intervals (pull method) with this function.
+ *
+ *  There are no limits on the amount of data you can queue, short of
+ *  exhaustion of address space. Data from the device will keep queuing as
+ *  necessary without further intervention from you. This means you will
+ *  eventually run out of memory if you aren't routinely dequeueing data.
+ *
+ *  Capture devices will not queue data when paused; if you are expecting
+ *  to not need captured audio for some length of time, use
+ *  SDL_PauseAudioDevice() to stop the capture device from queueing more
+ *  data. This can be useful during, say, level loading times. When
+ *  unpaused, capture devices will start queueing data from that point,
+ *  having flushed any capturable data available while paused.
+ *
+ *  This function is thread-safe, but dequeueing from the same device from
+ *  two threads at once does not promise which thread will dequeued data
+ *  first.
+ *
+ *  You may not dequeue audio from a device that is using an
+ *  application-supplied callback; doing so returns an error. You have to use
+ *  the audio callback, or dequeue audio with this function, but not both.
+ *
+ *  You should not call SDL_LockAudio() on the device before queueing; SDL
+ *  handles locking internally for this function.
+ *
+ *  \param dev The device ID from which we will dequeue audio.
+ *  \param data A pointer into where audio data should be copied.
+ *  \param len The number of bytes (not samples!) to which (data) points.
+ *  \return number of bytes dequeued, which could be less than requested.
+ *
+ *  \sa SDL_GetQueuedAudioSize
+ *  \sa SDL_ClearQueuedAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len);
+
 /**
 /**
  *  Get the number of bytes of still-queued audio.
  *  Get the number of bytes of still-queued audio.
  *
  *
- *  This is the number of bytes that have been queued for playback with
- *  SDL_QueueAudio(), but have not yet been sent to the hardware.
+ *  For playback device:
+ *
+ *    This is the number of bytes that have been queued for playback with
+ *    SDL_QueueAudio(), but have not yet been sent to the hardware. This
+ *    number may shrink at any time, so this only informs of pending data.
+ *
+ *    Once we've sent it to the hardware, this function can not decide the
+ *    exact byte boundary of what has been played. It's possible that we just
+ *    gave the hardware several kilobytes right before you called this
+ *    function, but it hasn't played any of it yet, or maybe half of it, etc.
+ *
+ *  For capture devices:
  *
  *
- *  Once we've sent it to the hardware, this function can not decide the exact
- *  byte boundary of what has been played. It's possible that we just gave the
- *  hardware several kilobytes right before you called this function, but it
- *  hasn't played any of it yet, or maybe half of it, etc.
+ *    This is the number of bytes that have been captured by the device and
+ *    are waiting for you to dequeue. This number may grow at any time, so
+ *    this only informs of the lower-bound of available data.
  *
  *
  *  You may not queue audio on a device that is using an application-supplied
  *  You may not queue audio on a device that is using an application-supplied
  *  callback; calling this function on such a device always returns 0.
  *  callback; calling this function on such a device always returns 0.
- *  You have to use the audio callback or queue audio with SDL_QueueAudio(),
- *  but not both.
+ *  You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use
+ *  the audio callback, but not both.
  *
  *
  *  You should not call SDL_LockAudio() on the device before querying; SDL
  *  You should not call SDL_LockAudio() on the device before querying; SDL
  *  handles locking internally for this function.
  *  handles locking internally for this function.
@@ -544,10 +604,17 @@ extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *da
 extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
 extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
 
 
 /**
 /**
- *  Drop any queued audio data waiting to be sent to the hardware.
+ *  Drop any queued audio data. For playback devices, this is any queued data
+ *  still waiting to be submitted to the hardware. For capture devices, this
+ *  is any data that was queued by the device that hasn't yet been dequeued by
+ *  the application.
  *
  *
- *  Immediately after this call, SDL_GetQueuedAudioSize() will return 0 and
- *  the hardware will start playing silence if more audio isn't queued.
+ *  Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For
+ *  playback devices, the hardware will start playing silence if more audio
+ *  isn't queued. Unpaused capture devices will start filling the queue again
+ *  as soon as they have more data available (which, depending on the state
+ *  of the hardware and the thread, could be before this function call
+ *  returns!).
  *
  *
  *  This will not prevent playback of queued audio that's already been sent
  *  This will not prevent playback of queued audio that's already been sent
  *  to the hardware, as we can not undo that, so expect there to be some
  *  to the hardware, as we can not undo that, so expect there to be some
@@ -557,8 +624,8 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
  *
  *
  *  You may not queue audio on a device that is using an application-supplied
  *  You may not queue audio on a device that is using an application-supplied
  *  callback; calling this function on such a device is always a no-op.
  *  callback; calling this function on such a device is always a no-op.
- *  You have to use the audio callback or queue audio with SDL_QueueAudio(),
- *  but not both.
+ *  You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use
+ *  the audio callback, but not both.
  *
  *
  *  You should not call SDL_LockAudio() on the device before clearing the
  *  You should not call SDL_LockAudio() on the device before clearing the
  *  queue; SDL handles locking internally for this function.
  *  queue; SDL handles locking internally for this function.

+ 2 - 0
Engine/lib/sdl/include/SDL_config.h.cmake

@@ -81,6 +81,8 @@
 #cmakedefine HAVE_PTHREAD_NP_H 1
 #cmakedefine HAVE_PTHREAD_NP_H 1
 #cmakedefine HAVE_LIBUDEV_H 1
 #cmakedefine HAVE_LIBUDEV_H 1
 #cmakedefine HAVE_DBUS_DBUS_H 1
 #cmakedefine HAVE_DBUS_DBUS_H 1
+#cmakedefine HAVE_IBUS_IBUS_H 1
+#cmakedefine HAVE_FCITX_FRONTEND_H 1
 
 
 /* C library functions */
 /* C library functions */
 #cmakedefine HAVE_MALLOC 1
 #cmakedefine HAVE_MALLOC 1

+ 4 - 0
Engine/lib/sdl/include/SDL_config.h.in

@@ -82,6 +82,7 @@
 #undef HAVE_LIBUDEV_H
 #undef HAVE_LIBUDEV_H
 #undef HAVE_DBUS_DBUS_H
 #undef HAVE_DBUS_DBUS_H
 #undef HAVE_IBUS_IBUS_H
 #undef HAVE_IBUS_IBUS_H
+#undef HAVE_FCITX_FRONTEND_H
 
 
 /* C library functions */
 /* C library functions */
 #undef HAVE_MALLOC
 #undef HAVE_MALLOC
@@ -356,4 +357,7 @@
 #undef SDL_ASSEMBLY_ROUTINES
 #undef SDL_ASSEMBLY_ROUTINES
 #undef SDL_ALTIVEC_BLITTERS
 #undef SDL_ALTIVEC_BLITTERS
 
 
+/* Enable ime support */
+#undef SDL_USE_IME
+
 #endif /* _SDL_config_h */
 #endif /* _SDL_config_h */

+ 3 - 0
Engine/lib/sdl/include/SDL_config_android.h

@@ -43,6 +43,7 @@
 #define HAVE_STDINT_H   1
 #define HAVE_STDINT_H   1
 #define HAVE_CTYPE_H    1
 #define HAVE_CTYPE_H    1
 #define HAVE_MATH_H 1
 #define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
 
 
 /* C library functions */
 /* C library functions */
 #define HAVE_MALLOC 1
 #define HAVE_MALLOC 1
@@ -75,6 +76,7 @@
 #define HAVE_STRTOULL   1
 #define HAVE_STRTOULL   1
 #define HAVE_STRTOD 1
 #define HAVE_STRTOD 1
 #define HAVE_ATOI   1
 #define HAVE_ATOI   1
+#define HAVE_ATOF 1
 #define HAVE_STRCMP 1
 #define HAVE_STRCMP 1
 #define HAVE_STRNCMP    1
 #define HAVE_STRNCMP    1
 #define HAVE_STRCASECMP 1
 #define HAVE_STRCASECMP 1
@@ -101,6 +103,7 @@
 #define HAVE_SQRTF  1
 #define HAVE_SQRTF  1
 #define HAVE_TAN    1
 #define HAVE_TAN    1
 #define HAVE_TANF   1
 #define HAVE_TANF   1
+#define HAVE_SIGACTION 1
 #define HAVE_SETJMP 1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
 #define HAVE_NANOSLEEP  1
 #define HAVE_SYSCONF    1
 #define HAVE_SYSCONF    1

+ 1 - 5
Engine/lib/sdl/include/SDL_config_iphoneos.h

@@ -119,11 +119,7 @@
 #define SDL_JOYSTICK_MFI 1
 #define SDL_JOYSTICK_MFI 1
 
 
 /* Enable Unix style SO loading */
 /* Enable Unix style SO loading */
-/* Technically this works, but violates the iOS dev agreement prior to iOS 8 */
-/* #define SDL_LOADSO_DLOPEN 1 */
-
-/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
-#define SDL_LOADSO_DISABLED 1
+#define SDL_LOADSO_DLOPEN 1
 
 
 /* Enable various threading systems */
 /* Enable various threading systems */
 #define SDL_THREAD_PTHREAD  1
 #define SDL_THREAD_PTHREAD  1

+ 6 - 2
Engine/lib/sdl/include/SDL_events.h

@@ -136,6 +136,9 @@ typedef enum
 
 
     /* Drag and drop events */
     /* Drag and drop events */
     SDL_DROPFILE        = 0x1000, /**< The system requests a file open */
     SDL_DROPFILE        = 0x1000, /**< The system requests a file open */
+    SDL_DROPTEXT,                 /**< text/plain drag-and-drop event */
+    SDL_DROPBEGIN,                /**< A new set of drops is beginning (NULL filename) */
+    SDL_DROPCOMPLETE,             /**< Current set of drops is now complete (NULL filename) */
 
 
     /* Audio hotplug events */
     /* Audio hotplug events */
     SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
     SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
@@ -461,9 +464,10 @@ typedef struct SDL_DollarGestureEvent
  */
  */
 typedef struct SDL_DropEvent
 typedef struct SDL_DropEvent
 {
 {
-    Uint32 type;        /**< ::SDL_DROPFILE */
+    Uint32 type;        /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
     Uint32 timestamp;
     Uint32 timestamp;
-    char *file;         /**< The file name, which should be freed with SDL_free() */
+    char *file;         /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+    Uint32 windowID;    /**< The window that was dropped on, if any */
 } SDL_DropEvent;
 } SDL_DropEvent;
 
 
 
 

+ 3 - 3
Engine/lib/sdl/include/SDL_gamecontroller.h

@@ -93,7 +93,7 @@ typedef struct SDL_GameControllerButtonBind
  *      }
  *      }
  *  }
  *  }
  *
  *
- *  Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+ *  Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
  *  guid,name,mappings
  *  guid,name,mappings
  *
  *
  *  Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
  *  Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
@@ -136,14 +136,14 @@ extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping( const char* mappingStr
 /**
 /**
  *  Get a mapping string for a GUID
  *  Get a mapping string for a GUID
  *
  *
- *  \return the mapping string.  Must be freed with SDL_free.  Returns NULL if no mapping is available
+ *  \return the mapping string.  Must be freed with SDL_free().  Returns NULL if no mapping is available
  */
  */
 extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID( SDL_JoystickGUID guid );
 extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID( SDL_JoystickGUID guid );
 
 
 /**
 /**
  *  Get a mapping string for an open GameController
  *  Get a mapping string for an open GameController
  *
  *
- *  \return the mapping string.  Must be freed with SDL_free.  Returns NULL if no mapping is available
+ *  \return the mapping string.  Must be freed with SDL_free().  Returns NULL if no mapping is available
  */
  */
 extern DECLSPEC char * SDLCALL SDL_GameControllerMapping( SDL_GameController * gamecontroller );
 extern DECLSPEC char * SDLCALL SDL_GameControllerMapping( SDL_GameController * gamecontroller );
 
 

+ 16 - 16
Engine/lib/sdl/include/SDL_haptic.h

@@ -149,7 +149,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticCondition
  */
  */
-#define SDL_HAPTIC_CONSTANT   (1<<0)
+#define SDL_HAPTIC_CONSTANT   (1u<<0)
 
 
 /**
 /**
  *  \brief Sine wave effect supported.
  *  \brief Sine wave effect supported.
@@ -158,7 +158,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticPeriodic
  *  \sa SDL_HapticPeriodic
  */
  */
-#define SDL_HAPTIC_SINE       (1<<1)
+#define SDL_HAPTIC_SINE       (1u<<1)
 
 
 /**
 /**
  *  \brief Left/Right effect supported.
  *  \brief Left/Right effect supported.
@@ -169,7 +169,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
  * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
  *          we ran out of bits, and this is important for XInput devices.
  *          we ran out of bits, and this is important for XInput devices.
  */
  */
-#define SDL_HAPTIC_LEFTRIGHT     (1<<2)
+#define SDL_HAPTIC_LEFTRIGHT     (1u<<2)
 
 
 /* !!! FIXME: put this back when we have more bits in 2.1 */
 /* !!! FIXME: put this back when we have more bits in 2.1 */
 /* #define SDL_HAPTIC_SQUARE     (1<<2) */
 /* #define SDL_HAPTIC_SQUARE     (1<<2) */
@@ -181,7 +181,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticPeriodic
  *  \sa SDL_HapticPeriodic
  */
  */
-#define SDL_HAPTIC_TRIANGLE   (1<<3)
+#define SDL_HAPTIC_TRIANGLE   (1u<<3)
 
 
 /**
 /**
  *  \brief Sawtoothup wave effect supported.
  *  \brief Sawtoothup wave effect supported.
@@ -190,7 +190,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticPeriodic
  *  \sa SDL_HapticPeriodic
  */
  */
-#define SDL_HAPTIC_SAWTOOTHUP (1<<4)
+#define SDL_HAPTIC_SAWTOOTHUP (1u<<4)
 
 
 /**
 /**
  *  \brief Sawtoothdown wave effect supported.
  *  \brief Sawtoothdown wave effect supported.
@@ -199,7 +199,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticPeriodic
  *  \sa SDL_HapticPeriodic
  */
  */
-#define SDL_HAPTIC_SAWTOOTHDOWN (1<<5)
+#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5)
 
 
 /**
 /**
  *  \brief Ramp effect supported.
  *  \brief Ramp effect supported.
@@ -208,7 +208,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticRamp
  *  \sa SDL_HapticRamp
  */
  */
-#define SDL_HAPTIC_RAMP       (1<<6)
+#define SDL_HAPTIC_RAMP       (1u<<6)
 
 
 /**
 /**
  *  \brief Spring effect supported - uses axes position.
  *  \brief Spring effect supported - uses axes position.
@@ -218,7 +218,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticCondition
  */
  */
-#define SDL_HAPTIC_SPRING     (1<<7)
+#define SDL_HAPTIC_SPRING     (1u<<7)
 
 
 /**
 /**
  *  \brief Damper effect supported - uses axes velocity.
  *  \brief Damper effect supported - uses axes velocity.
@@ -228,7 +228,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticCondition
  */
  */
-#define SDL_HAPTIC_DAMPER     (1<<8)
+#define SDL_HAPTIC_DAMPER     (1u<<8)
 
 
 /**
 /**
  *  \brief Inertia effect supported - uses axes acceleration.
  *  \brief Inertia effect supported - uses axes acceleration.
@@ -238,7 +238,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticCondition
  */
  */
-#define SDL_HAPTIC_INERTIA    (1<<9)
+#define SDL_HAPTIC_INERTIA    (1u<<9)
 
 
 /**
 /**
  *  \brief Friction effect supported - uses axes movement.
  *  \brief Friction effect supported - uses axes movement.
@@ -248,14 +248,14 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticCondition
  *  \sa SDL_HapticCondition
  */
  */
-#define SDL_HAPTIC_FRICTION   (1<<10)
+#define SDL_HAPTIC_FRICTION   (1u<<10)
 
 
 /**
 /**
  *  \brief Custom effect is supported.
  *  \brief Custom effect is supported.
  *
  *
  *  User defined custom haptic effect.
  *  User defined custom haptic effect.
  */
  */
-#define SDL_HAPTIC_CUSTOM     (1<<11)
+#define SDL_HAPTIC_CUSTOM     (1u<<11)
 
 
 /* @} *//* Haptic effects */
 /* @} *//* Haptic effects */
 
 
@@ -268,7 +268,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticSetGain
  *  \sa SDL_HapticSetGain
  */
  */
-#define SDL_HAPTIC_GAIN       (1<<12)
+#define SDL_HAPTIC_GAIN       (1u<<12)
 
 
 /**
 /**
  *  \brief Device can set autocenter.
  *  \brief Device can set autocenter.
@@ -277,7 +277,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticSetAutocenter
  *  \sa SDL_HapticSetAutocenter
  */
  */
-#define SDL_HAPTIC_AUTOCENTER (1<<13)
+#define SDL_HAPTIC_AUTOCENTER (1u<<13)
 
 
 /**
 /**
  *  \brief Device can be queried for effect status.
  *  \brief Device can be queried for effect status.
@@ -286,7 +286,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *
  *  \sa SDL_HapticGetEffectStatus
  *  \sa SDL_HapticGetEffectStatus
  */
  */
-#define SDL_HAPTIC_STATUS     (1<<14)
+#define SDL_HAPTIC_STATUS     (1u<<14)
 
 
 /**
 /**
  *  \brief Device can be paused.
  *  \brief Device can be paused.
@@ -294,7 +294,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *  \sa SDL_HapticPause
  *  \sa SDL_HapticPause
  *  \sa SDL_HapticUnpause
  *  \sa SDL_HapticUnpause
  */
  */
-#define SDL_HAPTIC_PAUSE      (1<<15)
+#define SDL_HAPTIC_PAUSE      (1u<<15)
 
 
 
 
 /**
 /**

+ 98 - 14
Engine/lib/sdl/include/SDL_hints.h

@@ -233,16 +233,27 @@ extern "C" {
 #define SDL_HINT_GRAB_KEYBOARD              "SDL_GRAB_KEYBOARD"
 #define SDL_HINT_GRAB_KEYBOARD              "SDL_GRAB_KEYBOARD"
 
 
 /**
 /**
-*  \brief  A variable controlling whether relative mouse mode is implemented using mouse warping
-*
-*  This variable can be set to the following values:
-*    "0"       - Relative mouse mode uses raw input
-*    "1"       - Relative mouse mode uses mouse warping
-*
-*  By default SDL will use raw input for relative mouse mode
-*/
+ *  \brief  A variable controlling whether relative mouse mode is implemented using mouse warping
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Relative mouse mode uses raw input
+ *    "1"       - Relative mouse mode uses mouse warping
+ *
+ *  By default SDL will use raw input for relative mouse mode
+ */
 #define SDL_HINT_MOUSE_RELATIVE_MODE_WARP    "SDL_MOUSE_RELATIVE_MODE_WARP"
 #define SDL_HINT_MOUSE_RELATIVE_MODE_WARP    "SDL_MOUSE_RELATIVE_MODE_WARP"
 
 
+/**
+ *  \brief Allow mouse click events when clicking to focus an SDL window
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Ignore mouse clicks that activate a window
+ *    "1"       - Generate events for mouse clicks that activate a window
+ *
+ *  By default SDL will ignore mouse clicks that activate a window
+ */
+#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH"
+
 /**
 /**
  *  \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true.
  *  \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true.
  *
  *
@@ -257,8 +268,8 @@ extern "C" {
  *  this is problematic. This functionality can be disabled by setting this
  *  this is problematic. This functionality can be disabled by setting this
  *  hint.
  *  hint.
  *
  *
- *  As of SDL 2.0.4, SDL_EnableScreenSaver and SDL_DisableScreenSaver accomplish
- *  the same thing on iOS. They should be preferred over this hint.
+ *  As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver()
+ *  accomplish the same thing on iOS. They should be preferred over this hint.
  *
  *
  *  This variable can be set to the following values:
  *  This variable can be set to the following values:
  *    "0"       - Enable idle timer
  *    "0"       - Enable idle timer
@@ -276,7 +287,35 @@ extern "C" {
  *    "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
  *    "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
  */
  */
 #define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
 #define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
-    
+
+/**
+ *  \brief  A variable controlling whether controllers used with the Apple TV
+ *  generate UI events.
+ *
+ * When UI events are generated by controller input, the app will be
+ * backgrounded when the Apple TV remote's menu button is pressed, and when the
+ * pause or B buttons on gamepads are pressed.
+ *
+ * More information about properly making use of controllers for the Apple TV
+ * can be found here:
+ * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Controller input does not generate UI events (the default).
+ *    "1"       - Controller input generates UI events.
+ */
+#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"
+
+/**
+ * \brief  A variable controlling whether the Apple TV remote's joystick axes
+ *         will automatically match the rotation of the remote.
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Remote orientation does not affect joystick axes (the default).
+ *    "1"       - Joystick axes are based on the orientation of the remote.
+ */
+#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"
+
 /**
 /**
  *  \brief  A variable controlling whether the Android / iOS built-in
  *  \brief  A variable controlling whether the Android / iOS built-in
  *  accelerometer should be listed as a joystick device, rather than listing
  *  accelerometer should be listed as a joystick device, rather than listing
@@ -369,7 +408,7 @@ extern "C" {
 *  Use this hint in case you need to set SDL's threads stack size to other than the default.
 *  Use this hint in case you need to set SDL's threads stack size to other than the default.
 *  This is specially useful if you build SDL against a non glibc libc library (such as musl) which
 *  This is specially useful if you build SDL against a non glibc libc library (such as musl) which
 *  provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
 *  provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
-*  Support for this hint is currently available only in the pthread backend.
+*  Support for this hint is currently available only in the pthread, Windows, and PSP backend.
 */
 */
 #define SDL_HINT_THREAD_STACK_SIZE              "SDL_THREAD_STACK_SIZE"
 #define SDL_HINT_THREAD_STACK_SIZE              "SDL_THREAD_STACK_SIZE"
 
 
@@ -431,7 +470,7 @@ extern "C" {
  *  privacy policy.
  *  privacy policy.
  *
  *
  *  To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
  *  To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
- *  before calling any SDL_Init functions.  The contents of the hint should
+ *  before calling any SDL_Init() functions.  The contents of the hint should
  *  be a valid URL.  For example, "http://www.example.com".
  *  be a valid URL.  For example, "http://www.example.com".
  *
  *
  *  The default value is "", which will prevent SDL from adding a privacy policy
  *  The default value is "", which will prevent SDL from adding a privacy policy
@@ -461,7 +500,7 @@ extern "C" {
  *  The contents of this hint should be encoded as a UTF8 string.
  *  The contents of this hint should be encoded as a UTF8 string.
  *
  *
  *  The default value is "Privacy Policy".  This hint should only be set during app
  *  The default value is "Privacy Policy".  This hint should only be set during app
- *  initialization, preferably before any calls to SDL_Init.
+ *  initialization, preferably before any calls to SDL_Init().
  *
  *
  *  For additional information on linking to a privacy policy, see the documentation for
  *  For additional information on linking to a privacy policy, see the documentation for
  *  SDL_HINT_WINRT_PRIVACY_POLICY_URL.
  *  SDL_HINT_WINRT_PRIVACY_POLICY_URL.
@@ -630,6 +669,44 @@ extern "C" {
  */
  */
 #define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4	"SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
 #define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4	"SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
 
 
+/**
+ *  \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
+ *
+ * The bitmap header version 4 is required for proper alpha channel support and
+ * SDL will use it when required. Should this not be desired, this hint can
+ * force the use of the 40 byte header version which is supported everywhere.
+ *
+ * The variable can be set to the following values:
+ *   "0"       - Surfaces with a colorkey or an alpha channel are saved to a
+ *               32-bit BMP file with an alpha mask. SDL will use the bitmap
+ *               header version 4 and set the alpha mask accordingly.
+ *   "1"       - Surfaces with a colorkey or an alpha channel are saved to a
+ *               32-bit BMP file without an alpha mask. The alpha channel data
+ *               will be in the file, but applications are going to ignore it.
+ *
+ * The default value is "0".
+ */
+#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT"
+
+/**
+ * \brief Tell SDL not to name threads on Windows.
+ *
+ * The variable can be set to the following values:
+ *   "0"       - SDL will raise the 0x406D1388 Exception to name threads.
+ *               This is the default behavior of SDL <= 2.0.4. (default)
+ *   "1"       - SDL will not raise this exception, and threads will be unnamed.
+ *               For .NET languages this is required when running under a debugger.
+ */
+#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING"
+
+/**
+ * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI
+ *
+ * Also known as Z-order. The variable can take a negative or positive value.
+ * The default is 10000.
+ */
+#define SDL_HINT_RPI_VIDEO_LAYER           "SDL_RPI_VIDEO_LAYER"
+
 /**
 /**
  *  \brief  An enumeration of hint priorities
  *  \brief  An enumeration of hint priorities
  */
  */
@@ -669,6 +746,13 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
  */
  */
 extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
 extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
 
 
+/**
+ *  \brief Get a hint
+ *
+ *  \return The boolean value of a hint variable.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value);
+
 /**
 /**
  *  \brief Add a function to watch a particular hint
  *  \brief Add a function to watch a particular hint
  *
  *

+ 1 - 1
Engine/lib/sdl/include/SDL_joystick.h

@@ -24,7 +24,7 @@
  *
  *
  *  Include file for SDL joystick event handling
  *  Include file for SDL joystick event handling
  *
  *
- * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick
+ * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick
  *   behind a device_index changing as joysticks are plugged and unplugged.
  *   behind a device_index changing as joysticks are plugged and unplugged.
  *
  *
  * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
  * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted

+ 1 - 1
Engine/lib/sdl/include/SDL_keyboard.h

@@ -136,7 +136,7 @@ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name);
  *          copy it.  If the key doesn't have a name, this function returns an
  *          copy it.  If the key doesn't have a name, this function returns an
  *          empty string ("").
  *          empty string ("").
  *
  *
- *  \sa SDL_Key
+ *  \sa SDL_Keycode
  */
  */
 extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
 extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
 
 

+ 1 - 1
Engine/lib/sdl/include/SDL_main.h

@@ -63,7 +63,7 @@
 /* On Android SDL provides a Java class in SDLActivity.java that is the
 /* On Android SDL provides a Java class in SDLActivity.java that is the
    main activity entry point.
    main activity entry point.
 
 
-   See README-android.txt for more details on extending that class.
+   See README-android.md for more details on extending that class.
  */
  */
 #define SDL_MAIN_NEEDED
 #define SDL_MAIN_NEEDED
 
 

+ 4 - 2
Engine/lib/sdl/include/SDL_mouse.h

@@ -41,7 +41,7 @@ extern "C" {
 typedef struct SDL_Cursor SDL_Cursor;   /* Implementation dependent */
 typedef struct SDL_Cursor SDL_Cursor;   /* Implementation dependent */
 
 
 /**
 /**
- * \brief Cursor types for SDL_CreateSystemCursor.
+ * \brief Cursor types for SDL_CreateSystemCursor().
  */
  */
 typedef enum
 typedef enum
 {
 {
@@ -254,9 +254,11 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void);
 extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void);
 extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void);
 
 
 /**
 /**
- *  \brief Frees a cursor created with SDL_CreateCursor().
+ *  \brief Frees a cursor created with SDL_CreateCursor() or similar functions.
  *
  *
  *  \sa SDL_CreateCursor()
  *  \sa SDL_CreateCursor()
+ *  \sa SDL_CreateColorCursor()
+ *  \sa SDL_CreateSystemCursor()
  */
  */
 extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor);
 extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor);
 
 

+ 1 - 0
Engine/lib/sdl/include/SDL_opengles.h

@@ -24,6 +24,7 @@
  *
  *
  *  This is a simple file to encapsulate the OpenGL ES 1.X API headers.
  *  This is a simple file to encapsulate the OpenGL ES 1.X API headers.
  */
  */
+#include "SDL_config.h"
 
 
 #ifdef __IPHONEOS__
 #ifdef __IPHONEOS__
 #include <OpenGLES/ES1/gl.h>
 #include <OpenGLES/ES1/gl.h>

+ 2 - 0
Engine/lib/sdl/include/SDL_opengles2.h

@@ -24,6 +24,8 @@
  *
  *
  *  This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
  *  This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
  */
  */
+#include "SDL_config.h"
+
 #ifndef _MSC_VER
 #ifndef _MSC_VER
 
 
 #ifdef __IPHONEOS__
 #ifdef __IPHONEOS__

+ 14 - 0
Engine/lib/sdl/include/SDL_pixels.h

@@ -29,6 +29,7 @@
 #define _SDL_pixels_h
 #define _SDL_pixels_h
 
 
 #include "SDL_stdinc.h"
 #include "SDL_stdinc.h"
+#include "SDL_endian.h"
 
 
 #include "begin_code.h"
 #include "begin_code.h"
 /* Set up for C function definitions, even when using C++ */
 /* Set up for C function definitions, even when using C++ */
@@ -260,6 +261,19 @@ enum
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
                                SDL_PACKEDLAYOUT_2101010, 32, 4),
                                SDL_PACKEDLAYOUT_2101010, 32, 4),
 
 
+    /* Aliases for RGBA byte arrays of color data, for the current platform */
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+    SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888,
+    SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
+    SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
+    SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+#else
+    SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
+    SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
+    SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
+    SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+#endif
+
     SDL_PIXELFORMAT_YV12 =      /**< Planar mode: Y + V + U  (3 planes) */
     SDL_PIXELFORMAT_YV12 =      /**< Planar mode: Y + V + U  (3 planes) */
         SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
         SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
     SDL_PIXELFORMAT_IYUV =      /**< Planar mode: Y + U + V  (3 planes) */
     SDL_PIXELFORMAT_IYUV =      /**< Planar mode: Y + U + V  (3 planes) */

+ 9 - 5
Engine/lib/sdl/include/SDL_platform.h

@@ -70,18 +70,22 @@
 /* lets us know what version of Mac OS X we're compiling on */
 /* lets us know what version of Mac OS X we're compiling on */
 #include "AvailabilityMacros.h"
 #include "AvailabilityMacros.h"
 #include "TargetConditionals.h"
 #include "TargetConditionals.h"
+#if TARGET_OS_TV
+#undef __TVOS__
+#define __TVOS__ 1
+#endif
 #if TARGET_OS_IPHONE
 #if TARGET_OS_IPHONE
-/* if compiling for iPhone */
+/* if compiling for iOS */
 #undef __IPHONEOS__
 #undef __IPHONEOS__
 #define __IPHONEOS__ 1
 #define __IPHONEOS__ 1
 #undef __MACOSX__
 #undef __MACOSX__
 #else
 #else
-/* if not compiling for iPhone */
+/* if not compiling for iOS */
 #undef __MACOSX__
 #undef __MACOSX__
 #define __MACOSX__  1
 #define __MACOSX__  1
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
-# error SDL for Mac OS X only supports deploying on 10.5 and above.
-#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1050 */
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+# error SDL for Mac OS X only supports deploying on 10.6 and above.
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
 #endif /* TARGET_OS_IPHONE */
 #endif /* TARGET_OS_IPHONE */
 #endif /* defined(__APPLE__) */
 #endif /* defined(__APPLE__) */
 
 

+ 26 - 1
Engine/lib/sdl/include/SDL_render.h

@@ -499,6 +499,30 @@ extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, in
  */
  */
 extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
 extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
 
 
+/**
+ *  \brief Set whether to force integer scales for resolution-independent rendering
+ *
+ *  \param renderer The renderer for which integer scaling should be set.
+ *  \param enable   Enable or disable integer scaling
+ *
+ *  This function restricts the logical viewport to integer values - that is, when
+ *  a resolution is between two multiples of a logical size, the viewport size is
+ *  rounded down to the lower multiple.
+ *
+ *  \sa SDL_RenderSetLogicalSize()
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetIntegerScale(SDL_Renderer * renderer,
+                                                      SDL_bool enable);
+
+/**
+ *  \brief Get whether integer scales are forced for resolution-independent rendering
+ *
+ *  \param renderer The renderer from which integer scaling should be queried.
+ *
+ *  \sa SDL_RenderSetIntegerScale()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer);
+
 /**
 /**
  *  \brief Set the drawing area for rendering on the current target.
  *  \brief Set the drawing area for rendering on the current target.
  *
  *
@@ -658,7 +682,8 @@ extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer,
 /**
 /**
  *  \brief Clear the current rendering target with the drawing color
  *  \brief Clear the current rendering target with the drawing color
  *
  *
- *  This function clears the entire rendering target, ignoring the viewport.
+ *  This function clears the entire rendering target, ignoring the viewport and
+ *  the clip rectangle.
  *
  *
  *  \return 0 on success, or -1 on error
  *  \return 0 on success, or -1 on error
  */
  */

+ 2 - 2
Engine/lib/sdl/include/SDL_revision.h

@@ -1,2 +1,2 @@
-#define SDL_REVISION "hg-10001:e12c38730512"
-#define SDL_REVISION_NUMBER 10001
+#define SDL_REVISION "hg-10556:007dfe83abf8"
+#define SDL_REVISION_NUMBER 10556

+ 6 - 6
Engine/lib/sdl/include/SDL_rwops.h

@@ -39,12 +39,12 @@ extern "C" {
 #endif
 #endif
 
 
 /* RWops Types */
 /* RWops Types */
-#define SDL_RWOPS_UNKNOWN   0   /* Unknown stream type */
-#define SDL_RWOPS_WINFILE   1   /* Win32 file */
-#define SDL_RWOPS_STDFILE   2   /* Stdio file */
-#define SDL_RWOPS_JNIFILE   3   /* Android asset */
-#define SDL_RWOPS_MEMORY    4   /* Memory stream */
-#define SDL_RWOPS_MEMORY_RO 5   /* Read-Only memory stream */
+#define SDL_RWOPS_UNKNOWN   0U  /* Unknown stream type */
+#define SDL_RWOPS_WINFILE   1U  /* Win32 file */
+#define SDL_RWOPS_STDFILE   2U  /* Stdio file */
+#define SDL_RWOPS_JNIFILE   3U  /* Android asset */
+#define SDL_RWOPS_MEMORY    4U  /* Memory stream */
+#define SDL_RWOPS_MEMORY_RO 5U  /* Read-Only memory stream */
 
 
 /**
 /**
  * This is the read/write operation structure -- very basic.
  * This is the read/write operation structure -- very basic.

+ 7 - 3
Engine/lib/sdl/include/SDL_stdinc.h

@@ -83,9 +83,6 @@
 #ifdef HAVE_FLOAT_H
 #ifdef HAVE_FLOAT_H
 # include <float.h>
 # include <float.h>
 #endif
 #endif
-#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
-# include <iconv.h>
-#endif
 
 
 /**
 /**
  *  The number of elements in an array.
  *  The number of elements in an array.
@@ -93,6 +90,13 @@
 #define SDL_arraysize(array)    (sizeof(array)/sizeof(array[0]))
 #define SDL_arraysize(array)    (sizeof(array)/sizeof(array[0]))
 #define SDL_TABLESIZE(table)    SDL_arraysize(table)
 #define SDL_TABLESIZE(table)    SDL_arraysize(table)
 
 
+/**
+ *  Macro useful for building other macros with strings in them
+ *
+ *  e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")
+ */
+#define SDL_STRINGIFY_ARG(arg)  #arg
+
 /**
 /**
  *  \name Cast operators
  *  \name Cast operators
  *
  *

+ 10 - 0
Engine/lib/sdl/include/SDL_surface.h

@@ -118,6 +118,8 @@ typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
 extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface
 extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface
     (Uint32 flags, int width, int height, int depth,
     (Uint32 flags, int width, int height, int depth,
      Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
      Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat
+    (Uint32 flags, int width, int height, int depth, Uint32 format);
 extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
 extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
                                                               int width,
                                                               int width,
                                                               int height,
                                                               int height,
@@ -127,6 +129,8 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
                                                               Uint32 Gmask,
                                                               Uint32 Gmask,
                                                               Uint32 Bmask,
                                                               Uint32 Bmask,
                                                               Uint32 Amask);
                                                               Uint32 Amask);
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom
+    (void *pixels, int width, int height, int depth, int pitch, Uint32 format);
 extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
 extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
 
 
 /**
 /**
@@ -184,6 +188,12 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops * src,
 /**
 /**
  *  Save a surface to a seekable SDL data stream (memory or file).
  *  Save a surface to a seekable SDL data stream (memory or file).
  *
  *
+ *  Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
+ *  BMP directly. Other RGB formats with 8-bit or higher get converted to a
+ *  24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
+ *  surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
+ *  not supported.
+ *
  *  If \c freedst is non-zero, the stream will be closed after being written.
  *  If \c freedst is non-zero, the stream will be closed after being written.
  *
  *
  *  \return 0 if successful or -1 if there was an error.
  *  \return 0 if successful or -1 if there was an error.

+ 21 - 1
Engine/lib/sdl/include/SDL_syswm.h

@@ -106,6 +106,10 @@ typedef struct ANativeWindow ANativeWindow;
 typedef void *EGLSurface;
 typedef void *EGLSurface;
 #endif
 #endif
 
 
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+#include "SDL_egl.h"
+#endif
+
 /**
 /**
  *  These are the various supported windowing subsystems
  *  These are the various supported windowing subsystems
  */
  */
@@ -120,7 +124,8 @@ typedef enum
     SDL_SYSWM_WAYLAND,
     SDL_SYSWM_WAYLAND,
     SDL_SYSWM_MIR,
     SDL_SYSWM_MIR,
     SDL_SYSWM_WINRT,
     SDL_SYSWM_WINRT,
-    SDL_SYSWM_ANDROID
+    SDL_SYSWM_ANDROID,
+    SDL_SYSWM_VIVANTE
 } SDL_SYSWM_TYPE;
 } SDL_SYSWM_TYPE;
 
 
 /**
 /**
@@ -166,6 +171,13 @@ struct SDL_SysWMmsg
             int dummy;
             int dummy;
             /* No UIKit window events yet */
             /* No UIKit window events yet */
         } uikit;
         } uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+        struct
+        {
+            int dummy;
+            /* No Vivante window events yet */
+        } vivante;
 #endif
 #endif
         /* Can't have an empty union */
         /* Can't have an empty union */
         int dummy;
         int dummy;
@@ -259,6 +271,14 @@ struct SDL_SysWMinfo
         } android;
         } android;
 #endif
 #endif
 
 
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+        struct
+        {
+            EGLNativeDisplayType display;
+            EGLNativeWindowType window;
+        } vivante;
+#endif
+
         /* Can't have an empty union */
         /* Can't have an empty union */
         int dummy;
         int dummy;
     } info;
     } info;

+ 1 - 1
Engine/lib/sdl/include/SDL_version.h

@@ -59,7 +59,7 @@ typedef struct SDL_version
 */
 */
 #define SDL_MAJOR_VERSION   2
 #define SDL_MAJOR_VERSION   2
 #define SDL_MINOR_VERSION   0
 #define SDL_MINOR_VERSION   0
-#define SDL_PATCHLEVEL      4
+#define SDL_PATCHLEVEL      5
 
 
 /**
 /**
  *  \brief Macro to determine SDL version program was compiled against.
  *  \brief Macro to determine SDL version program was compiled against.

+ 124 - 9
Engine/lib/sdl/include/SDL_video.h

@@ -83,6 +83,7 @@ typedef struct
  *  \sa SDL_SetWindowPosition()
  *  \sa SDL_SetWindowPosition()
  *  \sa SDL_SetWindowSize()
  *  \sa SDL_SetWindowSize()
  *  \sa SDL_SetWindowBordered()
  *  \sa SDL_SetWindowBordered()
+ *  \sa SDL_SetWindowResizable()
  *  \sa SDL_SetWindowTitle()
  *  \sa SDL_SetWindowTitle()
  *  \sa SDL_ShowWindow()
  *  \sa SDL_ShowWindow()
  */
  */
@@ -95,6 +96,7 @@ typedef struct SDL_Window SDL_Window;
  */
  */
 typedef enum
 typedef enum
 {
 {
+    /* !!! FIXME: change this to name = (1<<x). */
     SDL_WINDOW_FULLSCREEN = 0x00000001,         /**< fullscreen window */
     SDL_WINDOW_FULLSCREEN = 0x00000001,         /**< fullscreen window */
     SDL_WINDOW_OPENGL = 0x00000002,             /**< window usable with OpenGL context */
     SDL_WINDOW_OPENGL = 0x00000002,             /**< window usable with OpenGL context */
     SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */
     SDL_WINDOW_SHOWN = 0x00000004,              /**< window is visible */
@@ -109,13 +111,18 @@ typedef enum
     SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
     SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
     SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */
     SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */
     SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000,      /**< window should be created in high-DPI mode if supported */
     SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000,      /**< window should be created in high-DPI mode if supported */
-    SDL_WINDOW_MOUSE_CAPTURE = 0x00004000       /**< window has mouse captured (unrelated to INPUT_GRABBED) */
+    SDL_WINDOW_MOUSE_CAPTURE = 0x00004000,      /**< window has mouse captured (unrelated to INPUT_GRABBED) */
+    SDL_WINDOW_ALWAYS_ON_TOP = 0x00008000,      /**< window should always be above others */
+    SDL_WINDOW_SKIP_TASKBAR  = 0x00010000,      /**< window should not be added to the taskbar */
+    SDL_WINDOW_UTILITY       = 0x00020000,      /**< window should be treated as a utility window */
+    SDL_WINDOW_TOOLTIP       = 0x00040000,      /**< window should be treated as a tooltip */
+    SDL_WINDOW_POPUP_MENU    = 0x00080000       /**< window should be treated as a popup menu */
 } SDL_WindowFlags;
 } SDL_WindowFlags;
 
 
 /**
 /**
  *  \brief Used to indicate that you don't care what the window position is.
  *  \brief Used to indicate that you don't care what the window position is.
  */
  */
-#define SDL_WINDOWPOS_UNDEFINED_MASK    0x1FFF0000
+#define SDL_WINDOWPOS_UNDEFINED_MASK    0x1FFF0000u
 #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X)  (SDL_WINDOWPOS_UNDEFINED_MASK|(X))
 #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X)  (SDL_WINDOWPOS_UNDEFINED_MASK|(X))
 #define SDL_WINDOWPOS_UNDEFINED         SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
 #define SDL_WINDOWPOS_UNDEFINED         SDL_WINDOWPOS_UNDEFINED_DISPLAY(0)
 #define SDL_WINDOWPOS_ISUNDEFINED(X)    \
 #define SDL_WINDOWPOS_ISUNDEFINED(X)    \
@@ -124,7 +131,7 @@ typedef enum
 /**
 /**
  *  \brief Used to indicate that the window position should be centered.
  *  \brief Used to indicate that the window position should be centered.
  */
  */
-#define SDL_WINDOWPOS_CENTERED_MASK    0x2FFF0000
+#define SDL_WINDOWPOS_CENTERED_MASK    0x2FFF0000u
 #define SDL_WINDOWPOS_CENTERED_DISPLAY(X)  (SDL_WINDOWPOS_CENTERED_MASK|(X))
 #define SDL_WINDOWPOS_CENTERED_DISPLAY(X)  (SDL_WINDOWPOS_CENTERED_MASK|(X))
 #define SDL_WINDOWPOS_CENTERED         SDL_WINDOWPOS_CENTERED_DISPLAY(0)
 #define SDL_WINDOWPOS_CENTERED         SDL_WINDOWPOS_CENTERED_DISPLAY(0)
 #define SDL_WINDOWPOS_ISCENTERED(X)    \
 #define SDL_WINDOWPOS_ISCENTERED(X)    \
@@ -154,8 +161,9 @@ typedef enum
     SDL_WINDOWEVENT_LEAVE,          /**< Window has lost mouse focus */
     SDL_WINDOWEVENT_LEAVE,          /**< Window has lost mouse focus */
     SDL_WINDOWEVENT_FOCUS_GAINED,   /**< Window has gained keyboard focus */
     SDL_WINDOWEVENT_FOCUS_GAINED,   /**< Window has gained keyboard focus */
     SDL_WINDOWEVENT_FOCUS_LOST,     /**< Window has lost keyboard focus */
     SDL_WINDOWEVENT_FOCUS_LOST,     /**< Window has lost keyboard focus */
-    SDL_WINDOWEVENT_CLOSE           /**< The window manager requests that the
-                                         window be closed */
+    SDL_WINDOWEVENT_CLOSE,          /**< The window manager requests that the window be closed */
+    SDL_WINDOWEVENT_TAKE_FOCUS,     /**< Window is being offered a focus (should SetWindowInputFocus() on itself or a subwindow, or ignore) */
+    SDL_WINDOWEVENT_HIT_TEST        /**< Window had a hit test that wasn't SDL_HITTEST_NORMAL. */
 } SDL_WindowEventID;
 } SDL_WindowEventID;
 
 
 /**
 /**
@@ -310,6 +318,25 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(int displayIndex, SDL_Rect * re
  */
  */
 extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
 extern DECLSPEC int SDLCALL SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi);
 
 
+/**
+ *  \brief Get the usable desktop area represented by a display, with the
+ *         primary display located at 0,0
+ *
+ *  This is the same area as SDL_GetDisplayBounds() reports, but with portions
+ *  reserved by the system removed. For example, on Mac OS X, this subtracts
+ *  the area occupied by the menu bar and dock.
+ *
+ *  Setting a window to be fullscreen generally bypasses these unusable areas,
+ *  so these are good guidelines for the maximum space available to a
+ *  non-fullscreen window.
+ *
+ *  \return 0 on success, or -1 if the index is out of range.
+ *
+ *  \sa SDL_GetDisplayBounds()
+ *  \sa SDL_GetNumVideoDisplays()
+ */
+extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect);
+
 /**
 /**
  *  \brief Returns the number of available display modes.
  *  \brief Returns the number of available display modes.
  *
  *
@@ -423,7 +450,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
  *               ::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,
  *               ::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,
  *               ::SDL_WINDOW_ALLOW_HIGHDPI.
  *               ::SDL_WINDOW_ALLOW_HIGHDPI.
  *
  *
- *  \return The id of the window created, or zero if window creation failed.
+ *  \return The created window, or NULL if window creation failed.
  *
  *
  *  If the window is created with the SDL_WINDOW_ALLOW_HIGHDPI flag, its size
  *  If the window is created with the SDL_WINDOW_ALLOW_HIGHDPI flag, its size
  *  in pixels may differ from its size in screen coordinates on platforms with
  *  in pixels may differ from its size in screen coordinates on platforms with
@@ -442,7 +469,7 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title,
  *
  *
  *  \param data A pointer to driver-dependent window creation data
  *  \param data A pointer to driver-dependent window creation data
  *
  *
- *  \return The id of the window created, or zero if window creation failed.
+ *  \return The created window, or NULL if window creation failed.
  *
  *
  *  \sa SDL_DestroyWindow()
  *  \sa SDL_DestroyWindow()
  */
  */
@@ -586,6 +613,25 @@ extern DECLSPEC void SDLCALL SDL_SetWindowSize(SDL_Window * window, int w,
 extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w,
 extern DECLSPEC void SDLCALL SDL_GetWindowSize(SDL_Window * window, int *w,
                                                int *h);
                                                int *h);
 
 
+/**
+ *  \brief Get the size of a window's borders (decorations) around the client area.
+ *
+ *  \param window The window to query.
+ *  \param top Pointer to variable for storing the size of the top border. NULL is permitted.
+ *  \param left Pointer to variable for storing the size of the left border. NULL is permitted.
+ *  \param bottom Pointer to variable for storing the size of the bottom border. NULL is permitted.
+ *  \param right Pointer to variable for storing the size of the right border. NULL is permitted.
+ *
+ *  \return 0 on success, or -1 if getting this information is not supported.
+ *
+ *  \note if this function fails (returns -1), the size values will be
+ *        initialized to 0, 0, 0, 0 (if a non-NULL pointer is provided), as
+ *        if the window in question was borderless.
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowBordersSize(SDL_Window * window,
+                                                     int *top, int *left,
+                                                     int *bottom, int *right);
+
 /**
 /**
  *  \brief Set the minimum size of a window's client area.
  *  \brief Set the minimum size of a window's client area.
  *
  *
@@ -661,6 +707,23 @@ extern DECLSPEC void SDLCALL SDL_GetWindowMaximumSize(SDL_Window * window,
 extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window,
 extern DECLSPEC void SDLCALL SDL_SetWindowBordered(SDL_Window * window,
                                                    SDL_bool bordered);
                                                    SDL_bool bordered);
 
 
+/**
+ *  \brief Set the user-resizable state of a window.
+ *
+ *  This will add or remove the window's SDL_WINDOW_RESIZABLE flag and
+ *  allow/disallow user resizing of the window. This is a no-op if the
+ *  window's resizable state already matches the requested state.
+ *
+ *  \param window The window of which to change the resizable state.
+ *  \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow.
+ *
+ *  \note You can't change the resizable state of a fullscreen window.
+ *
+ *  \sa SDL_GetWindowFlags()
+ */
+extern DECLSPEC void SDLCALL SDL_SetWindowResizable(SDL_Window * window,
+                                                    SDL_bool resizable);
+
 /**
 /**
  *  \brief Show a window.
  *  \brief Show a window.
  *
  *
@@ -744,7 +807,7 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window * window);
  *  \return 0 on success, or -1 on error.
  *  \return 0 on success, or -1 on error.
  *
  *
  *  \sa SDL_GetWindowSurface()
  *  \sa SDL_GetWindowSurface()
- *  \sa SDL_UpdateWindowSurfaceRect()
+ *  \sa SDL_UpdateWindowSurface()
  */
  */
 extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
 extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window,
                                                          const SDL_Rect * rects,
                                                          const SDL_Rect * rects,
@@ -801,6 +864,58 @@ extern DECLSPEC int SDLCALL SDL_SetWindowBrightness(SDL_Window * window, float b
  */
  */
 extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
 extern DECLSPEC float SDLCALL SDL_GetWindowBrightness(SDL_Window * window);
 
 
+/**
+ *  \brief Set the opacity for a window
+ *
+ *  \param window The window which will be made transparent or opaque
+ *  \param opacity Opacity (0.0f - transparent, 1.0f - opaque) This will be
+ *                 clamped internally between 0.0f and 1.0f.
+ * 
+ *  \return 0 on success, or -1 if setting the opacity isn't supported.
+ *
+ *  \sa SDL_GetWindowOpacity()
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window * window, float opacity);
+
+/**
+ *  \brief Get the opacity of a window.
+ *
+ *  If transparency isn't supported on this platform, opacity will be reported
+ *  as 1.0f without error.
+ *
+ *  \param window The window in question.
+ *  \param out_opacity Opacity (0.0f - transparent, 1.0f - opaque)
+ *
+ *  \return 0 on success, or -1 on error (invalid window, etc).
+ *
+ *  \sa SDL_SetWindowOpacity()
+ */
+extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity);
+
+/**
+ *  \brief Sets the window as a modal for another window (TODO: reconsider this function and/or its name)
+ *
+ *  \param modal_window The window that should be modal
+ *  \param parent_window The parent window
+ * 
+ *  \return 0 on success, or -1 otherwise.
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window);
+
+/**
+ *  \brief Explicitly sets input focus to the window.
+ *
+ *  You almost certainly want SDL_RaiseWindow() instead of this function. Use
+ *  this with caution, as you might give focus to a window that's completely
+ *  obscured by other windows.
+ *
+ *  \param window The window that should get the input focus
+ * 
+ *  \return 0 on success, or -1 otherwise.
+ *  \sa SDL_RaiseWindow()
+ */
+extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window * window);
+
 /**
 /**
  *  \brief Set the gamma ramp for a window.
  *  \brief Set the gamma ramp for a window.
  *
  *
@@ -920,7 +1035,7 @@ extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window * window);
 
 
 
 
 /**
 /**
- *  \brief Returns whether the screensaver is currently enabled (default on).
+ *  \brief Returns whether the screensaver is currently enabled (default off).
  *
  *
  *  \sa SDL_EnableScreenSaver()
  *  \sa SDL_EnableScreenSaver()
  *  \sa SDL_DisableScreenSaver()
  *  \sa SDL_DisableScreenSaver()

+ 1 - 0
Engine/lib/sdl/sdl2-config.cmake.in

@@ -8,3 +8,4 @@ set(SDL2_EXEC_PREFIX "@prefix@")
 set(SDL2_LIBDIR "@libdir@")
 set(SDL2_LIBDIR "@libdir@")
 set(SDL2_INCLUDE_DIRS "@includedir@/SDL2")
 set(SDL2_INCLUDE_DIRS "@includedir@/SDL2")
 set(SDL2_LIBRARIES "-L${SDL2_LIBDIR} @SDL_RLD_FLAGS@ @SDL_LIBS@")
 set(SDL2_LIBRARIES "-L${SDL2_LIBDIR} @SDL_RLD_FLAGS@ @SDL_LIBS@")
+string(STRIP "${SDL2_LIBRARIES}" SDL2_LIBRARIES)

+ 43 - 11
Engine/lib/sdl/sdl2.m4

@@ -4,6 +4,9 @@
 # stolen back from Frank Belew
 # stolen back from Frank Belew
 # stolen from Manish Singh
 # stolen from Manish Singh
 # Shamelessly stolen from Owen Taylor
 # Shamelessly stolen from Owen Taylor
+#
+# Changelog:
+# * also look for SDL2.framework under Mac OS X
 
 
 # serial 1
 # serial 1
 
 
@@ -20,6 +23,10 @@ AC_ARG_WITH(sdl-exec-prefix,[  --with-sdl-exec-prefix=PFX Exec prefix where SDL
             sdl_exec_prefix="$withval", sdl_exec_prefix="")
             sdl_exec_prefix="$withval", sdl_exec_prefix="")
 AC_ARG_ENABLE(sdltest, [  --disable-sdltest       Do not try to compile and run a test SDL program],
 AC_ARG_ENABLE(sdltest, [  --disable-sdltest       Do not try to compile and run a test SDL program],
 		    , enable_sdltest=yes)
 		    , enable_sdltest=yes)
+AC_ARG_ENABLE(sdlframework, [  --disable-sdlframework Do not search for SDL2.framework],
+        , search_sdl_framework=yes)
+
+AC_ARG_VAR(SDL2_FRAMEWORK, [Path to SDL2.framework])
 
 
   min_sdl_version=ifelse([$1], ,2.0.0,$1)
   min_sdl_version=ifelse([$1], ,2.0.0,$1)
 
 
@@ -53,14 +60,36 @@ AC_ARG_ENABLE(sdltest, [  --disable-sdltest       Do not try to compile and run
     fi
     fi
     AC_PATH_PROG(SDL2_CONFIG, sdl2-config, no, [$PATH])
     AC_PATH_PROG(SDL2_CONFIG, sdl2-config, no, [$PATH])
     PATH="$as_save_PATH"
     PATH="$as_save_PATH"
-    AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
     no_sdl=""
     no_sdl=""
 
 
-    if test "$SDL2_CONFIG" = "no" ; then
-      no_sdl=yes
-    else
-      SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags`
-      SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs`
+    if test "$SDL2_CONFIG" = "no" -a "x$search_sdl_framework" = "xyes"; then
+      AC_MSG_CHECKING(for SDL2.framework)
+      if test "x$SDL2_FRAMEWORK" != x; then
+        sdl_framework=$SDL2_FRAMEWORK
+      else
+        for d in / ~/ /System/; do
+          if test -d "$dLibrary/Frameworks/SDL2.framework"; then
+            sdl_framework="$dLibrary/Frameworks/SDL2.framework"
+          fi
+        done
+      fi
+
+      if test -d $sdl_framework; then
+        AC_MSG_RESULT($sdl_framework)
+        sdl_framework_dir=`dirname $sdl_framework`
+        SDL_CFLAGS="-F$sdl_framework_dir -Wl,-framework,SDL2 -I$sdl_framework/include"
+        SDL_LIBS="-F$sdl_framework_dir -Wl,-framework,SDL2"
+      else
+        no_sdl=yes
+      fi
+    fi
+
+    if test "$SDL2_CONFIG" != "no"; then
+      if test "x$sdl_pc" = "xno"; then
+        AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
+        SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags`
+        SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs`
+      fi
 
 
       sdl_major_version=`$SDL2_CONFIG $sdl_config_args --version | \
       sdl_major_version=`$SDL2_CONFIG $sdl_config_args --version | \
              sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
              sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
@@ -141,12 +170,15 @@ int main (int argc, char *argv[])
         CFLAGS="$ac_save_CFLAGS"
         CFLAGS="$ac_save_CFLAGS"
         CXXFLAGS="$ac_save_CXXFLAGS"
         CXXFLAGS="$ac_save_CXXFLAGS"
         LIBS="$ac_save_LIBS"
         LIBS="$ac_save_LIBS"
+
+      fi
+      if test "x$sdl_pc" = "xno"; then
+        if test "x$no_sdl" = "xyes"; then
+          AC_MSG_RESULT(no)
+        else
+          AC_MSG_RESULT(yes)
+        fi
       fi
       fi
-    fi
-    if test "x$no_sdl" = x ; then
-      AC_MSG_RESULT(yes)
-    else
-      AC_MSG_RESULT(no)
     fi
     fi
   fi
   fi
   if test "x$no_sdl" = x ; then
   if test "x$no_sdl" = x ; then

+ 12 - 10
Engine/lib/sdl/src/SDL.c

@@ -115,6 +115,16 @@ SDL_InitSubSystem(Uint32 flags)
     /* Clear the error message */
     /* Clear the error message */
     SDL_ClearError();
     SDL_ClearError();
 
 
+    if ((flags & SDL_INIT_GAMECONTROLLER)) {
+        /* game controller implies joystick */
+        flags |= SDL_INIT_JOYSTICK;
+    }
+
+    if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
+        /* video or joystick implies events */
+        flags |= SDL_INIT_EVENTS;
+    }
+
 #if SDL_VIDEO_DRIVER_WINDOWS
 #if SDL_VIDEO_DRIVER_WINDOWS
 	if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
 	if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
 		if (SDL_HelperWindowCreate() < 0) {
 		if (SDL_HelperWindowCreate() < 0) {
@@ -127,16 +137,6 @@ SDL_InitSubSystem(Uint32 flags)
     SDL_TicksInit();
     SDL_TicksInit();
 #endif
 #endif
 
 
-    if ((flags & SDL_INIT_GAMECONTROLLER)) {
-        /* game controller implies joystick */
-        flags |= SDL_INIT_JOYSTICK;
-    }
-
-    if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
-        /* video or joystick implies events */
-        flags |= SDL_INIT_EVENTS;
-    }
-
     /* Initialize the event subsystem */
     /* Initialize the event subsystem */
     if ((flags & SDL_INIT_EVENTS)) {
     if ((flags & SDL_INIT_EVENTS)) {
 #if !SDL_EVENTS_DISABLED
 #if !SDL_EVENTS_DISABLED
@@ -443,6 +443,8 @@ SDL_GetPlatform()
     return "Windows";
     return "Windows";
 #elif __WINRT__
 #elif __WINRT__
     return "WinRT";
     return "WinRT";
+#elif __TVOS__
+    return "tvOS";
 #elif __IPHONEOS__
 #elif __IPHONEOS__
     return "iOS";
     return "iOS";
 #elif __PSP__
 #elif __PSP__

+ 7 - 0
Engine/lib/sdl/src/SDL_error.c

@@ -116,6 +116,10 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
     return -1;
     return -1;
 }
 }
 
 
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
 /* This function has a bit more overhead than most error functions
 /* This function has a bit more overhead than most error functions
    so that it supports internationalization and thread-safe errors.
    so that it supports internationalization and thread-safe errors.
 */
 */
@@ -216,6 +220,9 @@ SDL_GetErrorMsg(char *errstr, int maxlen)
     }
     }
     return (errstr);
     return (errstr);
 }
 }
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
 
 
 /* Available for backwards compatibility */
 /* Available for backwards compatibility */
 const char *
 const char *

+ 13 - 0
Engine/lib/sdl/src/SDL_hints.c

@@ -118,6 +118,19 @@ SDL_GetHint(const char *name)
     return env;
     return env;
 }
 }
 
 
+SDL_bool
+SDL_GetHintBoolean(const char *name, SDL_bool default_value)
+{
+    const char *hint = SDL_GetHint(name);
+    if (!hint) {
+        return default_value;
+    }
+    if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
 void
 void
 SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
 SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
 {
 {

+ 4 - 4
Engine/lib/sdl/src/SDL_log.c

@@ -324,7 +324,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         size_t length;
         size_t length;
         LPTSTR tstr;
         LPTSTR tstr;
 
 
-#ifndef __WINRT__
+#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
         BOOL attachResult;
         BOOL attachResult;
         DWORD attachError;
         DWORD attachError;
         unsigned long charsWritten; 
         unsigned long charsWritten; 
@@ -356,7 +356,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
                         stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
                         stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
                 }
                 }
         }
         }
-#endif /* ifndef __WINRT__ */
+#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
 
 
         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
         length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
         output = SDL_stack_alloc(char, length);
         output = SDL_stack_alloc(char, length);
@@ -366,7 +366,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         /* Output to debugger */
         /* Output to debugger */
         OutputDebugString(tstr);
         OutputDebugString(tstr);
        
        
-#ifndef __WINRT__
+#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
         /* Screen output to stderr, if console was attached. */
         /* Screen output to stderr, if console was attached. */
         if (consoleAttached == 1) {
         if (consoleAttached == 1) {
                 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
                 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
@@ -376,7 +376,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
                     }
                     }
                 }
                 }
         }
         }
-#endif /* ifndef __WINRT__ */
+#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
 
 
         SDL_free(tstr);
         SDL_free(tstr);
         SDL_stack_free(output);
         SDL_stack_free(output);

+ 382 - 169
Engine/lib/sdl/src/audio/SDL_audio.c

@@ -25,33 +25,29 @@
 #include "SDL.h"
 #include "SDL.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "SDL_audio_c.h"
 #include "SDL_audio_c.h"
-#include "SDL_audiomem.h"
 #include "SDL_sysaudio.h"
 #include "SDL_sysaudio.h"
+#include "../thread/SDL_systhread.h"
 
 
 #define _THIS SDL_AudioDevice *_this
 #define _THIS SDL_AudioDevice *_this
 
 
 static SDL_AudioDriver current_audio;
 static SDL_AudioDriver current_audio;
 static SDL_AudioDevice *open_devices[16];
 static SDL_AudioDevice *open_devices[16];
 
 
-/* !!! FIXME: These are wordy and unlocalized... */
-#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
-#define DEFAULT_INPUT_DEVNAME "System audio capture device"
-
-
 /*
 /*
  * Not all of these will be compiled and linked in, but it's convenient
  * Not all of these will be compiled and linked in, but it's convenient
  *  to have a complete list here and saves yet-another block of #ifdefs...
  *  to have a complete list here and saves yet-another block of #ifdefs...
  *  Please see bootstrap[], below, for the actual #ifdef mess.
  *  Please see bootstrap[], below, for the actual #ifdef mess.
  */
  */
+extern AudioBootStrap PULSEAUDIO_bootstrap;
+extern AudioBootStrap ALSA_bootstrap;
+extern AudioBootStrap SNDIO_bootstrap;
 extern AudioBootStrap BSD_AUDIO_bootstrap;
 extern AudioBootStrap BSD_AUDIO_bootstrap;
 extern AudioBootStrap DSP_bootstrap;
 extern AudioBootStrap DSP_bootstrap;
-extern AudioBootStrap ALSA_bootstrap;
-extern AudioBootStrap PULSEAUDIO_bootstrap;
 extern AudioBootStrap QSAAUDIO_bootstrap;
 extern AudioBootStrap QSAAUDIO_bootstrap;
 extern AudioBootStrap SUNAUDIO_bootstrap;
 extern AudioBootStrap SUNAUDIO_bootstrap;
 extern AudioBootStrap ARTS_bootstrap;
 extern AudioBootStrap ARTS_bootstrap;
 extern AudioBootStrap ESD_bootstrap;
 extern AudioBootStrap ESD_bootstrap;
-extern AudioBootStrap NACLAUD_bootstrap;
+extern AudioBootStrap NACLAUDIO_bootstrap;
 extern AudioBootStrap NAS_bootstrap;
 extern AudioBootStrap NAS_bootstrap;
 extern AudioBootStrap XAUDIO2_bootstrap;
 extern AudioBootStrap XAUDIO2_bootstrap;
 extern AudioBootStrap DSOUND_bootstrap;
 extern AudioBootStrap DSOUND_bootstrap;
@@ -59,18 +55,13 @@ extern AudioBootStrap WINMM_bootstrap;
 extern AudioBootStrap PAUDIO_bootstrap;
 extern AudioBootStrap PAUDIO_bootstrap;
 extern AudioBootStrap HAIKUAUDIO_bootstrap;
 extern AudioBootStrap HAIKUAUDIO_bootstrap;
 extern AudioBootStrap COREAUDIO_bootstrap;
 extern AudioBootStrap COREAUDIO_bootstrap;
-extern AudioBootStrap SNDMGR_bootstrap;
-extern AudioBootStrap DISKAUD_bootstrap;
-extern AudioBootStrap DUMMYAUD_bootstrap;
-extern AudioBootStrap DCAUD_bootstrap;
-extern AudioBootStrap DART_bootstrap;
-extern AudioBootStrap NDSAUD_bootstrap;
+extern AudioBootStrap DISKAUDIO_bootstrap;
+extern AudioBootStrap DUMMYAUDIO_bootstrap;
 extern AudioBootStrap FUSIONSOUND_bootstrap;
 extern AudioBootStrap FUSIONSOUND_bootstrap;
-extern AudioBootStrap ANDROIDAUD_bootstrap;
-extern AudioBootStrap PSPAUD_bootstrap;
+extern AudioBootStrap ANDROIDAUDIO_bootstrap;
+extern AudioBootStrap PSPAUDIO_bootstrap;
 extern AudioBootStrap SNDIO_bootstrap;
 extern AudioBootStrap SNDIO_bootstrap;
-extern AudioBootStrap EmscriptenAudio_bootstrap;
-
+extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
 
 
 /* Available audio drivers */
 /* Available audio drivers */
 static const AudioBootStrap *const bootstrap[] = {
 static const AudioBootStrap *const bootstrap[] = {
@@ -102,7 +93,7 @@ static const AudioBootStrap *const bootstrap[] = {
     &ESD_bootstrap,
     &ESD_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_NACL
 #if SDL_AUDIO_DRIVER_NACL
-   &NACLAUD_bootstrap,
+    &NACLAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_NAS
 #if SDL_AUDIO_DRIVER_NAS
     &NAS_bootstrap,
     &NAS_bootstrap,
@@ -126,22 +117,22 @@ static const AudioBootStrap *const bootstrap[] = {
     &COREAUDIO_bootstrap,
     &COREAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_DISK
 #if SDL_AUDIO_DRIVER_DISK
-    &DISKAUD_bootstrap,
+    &DISKAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_DUMMY
 #if SDL_AUDIO_DRIVER_DUMMY
-    &DUMMYAUD_bootstrap,
+    &DUMMYAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_FUSIONSOUND
 #if SDL_AUDIO_DRIVER_FUSIONSOUND
     &FUSIONSOUND_bootstrap,
     &FUSIONSOUND_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_ANDROID
 #if SDL_AUDIO_DRIVER_ANDROID
-    &ANDROIDAUD_bootstrap,
+    &ANDROIDAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_PSP
 #if SDL_AUDIO_DRIVER_PSP
-    &PSPAUD_bootstrap,
+    &PSPAUDIO_bootstrap,
 #endif
 #endif
 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
-    &EmscriptenAudio_bootstrap,
+    &EMSCRIPTENAUDIO_bootstrap,
 #endif
 #endif
     NULL
     NULL
 };
 };
@@ -165,7 +156,7 @@ SDL_AudioDetectDevices_Default(void)
 {
 {
     /* you have to write your own implementation if these assertions fail. */
     /* you have to write your own implementation if these assertions fail. */
     SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
     SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
-    SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
+    SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
 
 
     SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
     SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
     if (current_audio.impl.HasCaptureSupport) {
     if (current_audio.impl.HasCaptureSupport) {
@@ -200,8 +191,19 @@ SDL_AudioGetDeviceBuf_Default(_THIS)
     return NULL;
     return NULL;
 }
 }
 
 
+static int
+SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
+{
+    return -1;  /* just fail immediately. */
+}
+
+static void
+SDL_AudioFlushCapture_Default(_THIS)
+{                               /* no-op. */
+}
+
 static void
 static void
-SDL_AudioWaitDone_Default(_THIS)
+SDL_AudioPrepareToClose_Default(_THIS)
 {                               /* no-op. */
 {                               /* no-op. */
 }
 }
 
 
@@ -257,15 +259,28 @@ SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
     }
     }
 }
 }
 
 
+static void
+SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
+{
+}
 
 
 static void
 static void
-finalize_audio_entry_points(void)
+finish_audio_entry_points_init(void)
 {
 {
     /*
     /*
      * Fill in stub functions for unused driver entry points. This lets us
      * Fill in stub functions for unused driver entry points. This lets us
      *  blindly call them without having to check for validity first.
      *  blindly call them without having to check for validity first.
      */
      */
 
 
+    if (current_audio.impl.SkipMixerLock) {
+        if (current_audio.impl.LockDevice == NULL) {
+            current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
+        }
+        if (current_audio.impl.UnlockDevice == NULL) {
+            current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
+        }
+    }
+
 #define FILL_STUB(x) \
 #define FILL_STUB(x) \
         if (current_audio.impl.x == NULL) { \
         if (current_audio.impl.x == NULL) { \
             current_audio.impl.x = SDL_Audio##x##_Default; \
             current_audio.impl.x = SDL_Audio##x##_Default; \
@@ -277,7 +292,9 @@ finalize_audio_entry_points(void)
     FILL_STUB(PlayDevice);
     FILL_STUB(PlayDevice);
     FILL_STUB(GetPendingBytes);
     FILL_STUB(GetPendingBytes);
     FILL_STUB(GetDeviceBuf);
     FILL_STUB(GetDeviceBuf);
-    FILL_STUB(WaitDone);
+    FILL_STUB(CaptureFromDevice);
+    FILL_STUB(FlushCapture);
+    FILL_STUB(PrepareToClose);
     FILL_STUB(CloseDevice);
     FILL_STUB(CloseDevice);
     FILL_STUB(LockDevice);
     FILL_STUB(LockDevice);
     FILL_STUB(UnlockDevice);
     FILL_STUB(UnlockDevice);
@@ -316,7 +333,7 @@ add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices,
 static SDL_INLINE int
 static SDL_INLINE int
 add_capture_device(const char *name, void *handle)
 add_capture_device(const char *name, void *handle)
 {
 {
-    /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
+    SDL_assert(current_audio.impl.HasCaptureSupport);
     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
 }
 }
 
 
@@ -365,14 +382,14 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
 {
 {
     SDL_assert(get_audio_device(device->id) == device);
     SDL_assert(get_audio_device(device->id) == device);
 
 
-    if (!device->enabled) {
+    if (!SDL_AtomicGet(&device->enabled)) {
         return;
         return;
     }
     }
 
 
     /* Ends the audio callback and mark the device as STOPPED, but the
     /* Ends the audio callback and mark the device as STOPPED, but the
        app still needs to close the device to free resources. */
        app still needs to close the device to free resources. */
     current_audio.impl.LockDevice(device);
     current_audio.impl.LockDevice(device);
-    device->enabled = 0;
+    SDL_AtomicSet(&device->enabled, 0);
     current_audio.impl.UnlockDevice(device);
     current_audio.impl.UnlockDevice(device);
 
 
     /* Post the event, if desired */
     /* Post the event, if desired */
@@ -404,13 +421,26 @@ mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *remove
 void
 void
 SDL_RemoveAudioDevice(const int iscapture, void *handle)
 SDL_RemoveAudioDevice(const int iscapture, void *handle)
 {
 {
+    int device_index;
+    SDL_AudioDevice *device = NULL;
+
     SDL_LockMutex(current_audio.detectionLock);
     SDL_LockMutex(current_audio.detectionLock);
     if (iscapture) {
     if (iscapture) {
         mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
         mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
     } else {
     } else {
         mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
         mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
     }
     }
+    for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
+    {
+        device = open_devices[device_index];
+        if (device != NULL && device->handle == handle)
+        {
+            SDL_OpenedAudioDeviceDisconnected(device);
+            break;
+        }
+    }
     SDL_UnlockMutex(current_audio.detectionLock);
     SDL_UnlockMutex(current_audio.detectionLock);
+
     current_audio.impl.FreeDeviceHandle(handle);
     current_audio.impl.FreeDeviceHandle(handle);
 }
 }
 
 
@@ -420,77 +450,24 @@ SDL_RemoveAudioDevice(const int iscapture, void *handle)
 
 
 /* this expects that you managed thread safety elsewhere. */
 /* this expects that you managed thread safety elsewhere. */
 static void
 static void
-free_audio_queue(SDL_AudioBufferQueue *buffer)
-{
-    while (buffer) {
-        SDL_AudioBufferQueue *next = buffer->next;
-        SDL_free(buffer);
-        buffer = next;
-    }
-}
-
-static void SDLCALL
-SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
+free_audio_queue(SDL_AudioBufferQueue *packet)
 {
 {
-    /* this function always holds the mixer lock before being called. */
-    Uint32 len = (Uint32) _len;
-    SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
-    SDL_AudioBufferQueue *buffer;
-
-    SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
-    SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
-
-    while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
-        const Uint32 avail = buffer->datalen - buffer->startpos;
-        const Uint32 cpy = SDL_min(len, avail);
-        SDL_assert(device->queued_bytes >= avail);
-
-        SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
-        buffer->startpos += cpy;
-        stream += cpy;
-        device->queued_bytes -= cpy;
-        len -= cpy;
-
-        if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
-            device->buffer_queue_head = buffer->next;
-            SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
-            buffer->next = device->buffer_queue_pool;
-            device->buffer_queue_pool = buffer;
-        }
-    }
-
-    SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
-
-    if (len > 0) {  /* fill any remaining space in the stream with silence. */
-        SDL_assert(device->buffer_queue_head == NULL);
-        SDL_memset(stream, device->spec.silence, len);
-    }
-
-    if (device->buffer_queue_head == NULL) {
-        device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
+    while (packet) {
+        SDL_AudioBufferQueue *next = packet->next;
+        SDL_free(packet);
+        packet = next;
     }
     }
 }
 }
 
 
-int
-SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
+/* NOTE: This assumes you'll hold the mixer lock before calling! */
+static int
+queue_audio_to_device(SDL_AudioDevice *device, const Uint8 *data, Uint32 len)
 {
 {
-    SDL_AudioDevice *device = get_audio_device(devid);
-    const Uint8 *data = (const Uint8 *) _data;
     SDL_AudioBufferQueue *orighead;
     SDL_AudioBufferQueue *orighead;
     SDL_AudioBufferQueue *origtail;
     SDL_AudioBufferQueue *origtail;
     Uint32 origlen;
     Uint32 origlen;
     Uint32 datalen;
     Uint32 datalen;
 
 
-    if (!device) {
-        return -1;  /* get_audio_device() will have set the error state */
-    }
-
-    if (device->spec.callback != SDL_BufferQueueDrainCallback) {
-        return SDL_SetError("Audio device has a callback, queueing not allowed");
-    }
-
-    current_audio.impl.LockDevice(device);
-
     orighead = device->buffer_queue_head;
     orighead = device->buffer_queue_head;
     origtail = device->buffer_queue_tail;
     origtail = device->buffer_queue_tail;
     origlen = origtail ? origtail->datalen : 0;
     origlen = origtail ? origtail->datalen : 0;
@@ -520,8 +497,6 @@ SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
                     device->buffer_queue_tail = origtail;
                     device->buffer_queue_tail = origtail;
                     device->buffer_queue_pool = NULL;
                     device->buffer_queue_pool = NULL;
 
 
-                    current_audio.impl.UnlockDevice(device);
-
                     free_audio_queue(packet);  /* give back what we can. */
                     free_audio_queue(packet);  /* give back what we can. */
 
 
                     return SDL_OutOfMemory();
                     return SDL_OutOfMemory();
@@ -548,22 +523,142 @@ SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
         device->queued_bytes += datalen;
         device->queued_bytes += datalen;
     }
     }
 
 
-    current_audio.impl.UnlockDevice(device);
-
     return 0;
     return 0;
 }
 }
 
 
+/* NOTE: This assumes you'll hold the mixer lock before calling! */
+static Uint32
+dequeue_audio_from_device(SDL_AudioDevice *device, Uint8 *stream, Uint32 len)
+{
+    SDL_AudioBufferQueue *packet;
+    Uint8 *ptr = stream;
+
+    while ((len > 0) && ((packet = device->buffer_queue_head) != NULL)) {
+        const Uint32 avail = packet->datalen - packet->startpos;
+        const Uint32 cpy = SDL_min(len, avail);
+        SDL_assert(device->queued_bytes >= avail);
+
+        SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
+        packet->startpos += cpy;
+        ptr += cpy;
+        device->queued_bytes -= cpy;
+        len -= cpy;
+
+        if (packet->startpos == packet->datalen) {  /* packet is done, put it in the pool. */
+            device->buffer_queue_head = packet->next;
+            SDL_assert((packet->next != NULL) || (packet == device->buffer_queue_tail));
+            packet->next = device->buffer_queue_pool;
+            device->buffer_queue_pool = packet;
+        }
+    }
+
+    SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
+
+    if (device->buffer_queue_head == NULL) {
+        device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
+    }
+
+    return (Uint32) (ptr - stream);
+}
+
+static void SDLCALL
+SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
+{
+    /* this function always holds the mixer lock before being called. */
+    SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
+    Uint32 written;
+
+    SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
+    SDL_assert(!device->iscapture);  /* this shouldn't ever happen, right?! */
+    SDL_assert(len >= 0);  /* this shouldn't ever happen, right?! */
+
+    written = dequeue_audio_from_device(device, stream, (Uint32) len);
+    stream += written;
+    len -= (int) written;
+
+    if (len > 0) {  /* fill any remaining space in the stream with silence. */
+        SDL_assert(device->buffer_queue_head == NULL);
+        SDL_memset(stream, device->spec.silence, len);
+    }
+}
+
+static void SDLCALL
+SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
+{
+    /* this function always holds the mixer lock before being called. */
+    SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
+
+    SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
+    SDL_assert(device->iscapture);  /* this shouldn't ever happen, right?! */
+    SDL_assert(len >= 0);  /* this shouldn't ever happen, right?! */
+
+    /* note that if this needs to allocate more space and run out of memory,
+       we have no choice but to quietly drop the data and hope it works out
+       later, but you probably have bigger problems in this case anyhow. */
+    queue_audio_to_device(device, stream, (Uint32) len);
+}
+
+int
+SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
+{
+    SDL_AudioDevice *device = get_audio_device(devid);
+    int rc = 0;
+
+    if (!device) {
+        return -1;  /* get_audio_device() will have set the error state */
+    } else if (device->iscapture) {
+        return SDL_SetError("This is a capture device, queueing not allowed");
+    } else if (device->spec.callback != SDL_BufferQueueDrainCallback) {
+        return SDL_SetError("Audio device has a callback, queueing not allowed");
+    }
+
+    if (len > 0) {
+        current_audio.impl.LockDevice(device);
+        rc = queue_audio_to_device(device, data, len);
+        current_audio.impl.UnlockDevice(device);
+    }
+
+    return rc;
+}
+
+Uint32
+SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
+{
+    SDL_AudioDevice *device = get_audio_device(devid);
+    Uint32 rc;
+
+    if ( (len == 0) ||  /* nothing to do? */
+         (!device) ||  /* called with bogus device id */
+         (!device->iscapture) ||  /* playback devices can't dequeue */
+         (device->spec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
+        return 0;  /* just report zero bytes dequeued. */
+    }
+
+    current_audio.impl.LockDevice(device);
+    rc = dequeue_audio_from_device(device, data, len);
+    current_audio.impl.UnlockDevice(device);
+    return rc;
+}
+
 Uint32
 Uint32
 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
 {
 {
     Uint32 retval = 0;
     Uint32 retval = 0;
     SDL_AudioDevice *device = get_audio_device(devid);
     SDL_AudioDevice *device = get_audio_device(devid);
 
 
+    if (!device) {
+        return 0;
+    }
+
     /* Nothing to do unless we're set up for queueing. */
     /* Nothing to do unless we're set up for queueing. */
-    if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
+    if (device->spec.callback == SDL_BufferQueueDrainCallback) {
         current_audio.impl.LockDevice(device);
         current_audio.impl.LockDevice(device);
         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
         current_audio.impl.UnlockDevice(device);
         current_audio.impl.UnlockDevice(device);
+    } else if (device->spec.callback == SDL_BufferQueueFillCallback) {
+        current_audio.impl.LockDevice(device);
+        retval = device->queued_bytes;
+        current_audio.impl.UnlockDevice(device);
     }
     }
 
 
     return retval;
     return retval;
@@ -573,25 +668,49 @@ void
 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
 {
 {
     SDL_AudioDevice *device = get_audio_device(devid);
     SDL_AudioDevice *device = get_audio_device(devid);
-    SDL_AudioBufferQueue *buffer = NULL;
+    SDL_AudioBufferQueue *packet;
+
     if (!device) {
     if (!device) {
         return;  /* nothing to do. */
         return;  /* nothing to do. */
     }
     }
 
 
     /* Blank out the device and release the mutex. Free it afterwards. */
     /* Blank out the device and release the mutex. Free it afterwards. */
     current_audio.impl.LockDevice(device);
     current_audio.impl.LockDevice(device);
-    buffer = device->buffer_queue_head;
+
+    /* merge the available pool and the current queue into one list. */
+    packet = device->buffer_queue_head;
+    if (packet) {
+        device->buffer_queue_tail->next = device->buffer_queue_pool;
+    } else {
+        packet = device->buffer_queue_pool;
+    }
+
+    /* Remove the queued packets from the device. */
     device->buffer_queue_tail = NULL;
     device->buffer_queue_tail = NULL;
     device->buffer_queue_head = NULL;
     device->buffer_queue_head = NULL;
     device->queued_bytes = 0;
     device->queued_bytes = 0;
+    device->buffer_queue_pool = packet;
+
+    /* Keep up to two packets in the pool to reduce future malloc pressure. */
+    if (packet) {
+        if (!packet->next) {
+            packet = NULL;  /* one packet (the only one) for the pool. */
+        } else {
+            SDL_AudioBufferQueue *next = packet->next->next;
+            packet->next->next = NULL;  /* two packets for the pool. */
+            packet = next;  /* rest will be freed. */
+        }
+    }
+
     current_audio.impl.UnlockDevice(device);
     current_audio.impl.UnlockDevice(device);
 
 
-    free_audio_queue(buffer);
+    /* free any extra packets we didn't keep in the pool. */
+    free_audio_queue(packet);
 }
 }
 
 
 
 
 /* The general mixing thread function */
 /* The general mixing thread function */
-int SDLCALL
+static int SDLCALL
 SDL_RunAudio(void *devicep)
 SDL_RunAudio(void *devicep)
 {
 {
     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
@@ -600,7 +719,9 @@ SDL_RunAudio(void *devicep)
     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
     Uint8 *stream;
     Uint8 *stream;
     void *udata = device->spec.userdata;
     void *udata = device->spec.userdata;
-    void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
+    void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
+
+    SDL_assert(!device->iscapture);
 
 
     /* The audio mixing is always a high priority thread */
     /* The audio mixing is always a high priority thread */
     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
@@ -610,11 +731,11 @@ SDL_RunAudio(void *devicep)
     current_audio.impl.ThreadInit(device);
     current_audio.impl.ThreadInit(device);
 
 
     /* Loop, filling the audio buffers */
     /* Loop, filling the audio buffers */
-    while (!device->shutdown) {
+    while (!SDL_AtomicGet(&device->shutdown)) {
         /* Fill the current buffer with sound */
         /* Fill the current buffer with sound */
         if (device->convert.needed) {
         if (device->convert.needed) {
             stream = device->convert.buf;
             stream = device->convert.buf;
-        } else if (device->enabled) {
+        } else if (SDL_AtomicGet(&device->enabled)) {
             stream = current_audio.impl.GetDeviceBuf(device);
             stream = current_audio.impl.GetDeviceBuf(device);
         } else {
         } else {
             /* if the device isn't enabled, we still write to the
             /* if the device isn't enabled, we still write to the
@@ -630,16 +751,18 @@ SDL_RunAudio(void *devicep)
         }
         }
 
 
         /* !!! FIXME: this should be LockDevice. */
         /* !!! 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);
+        if ( SDL_AtomicGet(&device->enabled) ) {
+            SDL_LockMutex(device->mixer_lock);
+            if (SDL_AtomicGet(&device->paused)) {
+                SDL_memset(stream, silence, stream_len);
+            } else {
+                (*callback) (udata, stream, stream_len);
+            }
+            SDL_UnlockMutex(device->mixer_lock);
         }
         }
-        SDL_UnlockMutex(device->mixer_lock);
 
 
         /* Convert the audio if necessary */
         /* Convert the audio if necessary */
-        if (device->enabled && device->convert.needed) {
+        if (device->convert.needed && SDL_AtomicGet(&device->enabled)) {
             SDL_ConvertAudio(&device->convert);
             SDL_ConvertAudio(&device->convert);
             stream = current_audio.impl.GetDeviceBuf(device);
             stream = current_audio.impl.GetDeviceBuf(device);
             if (stream == NULL) {
             if (stream == NULL) {
@@ -659,8 +782,91 @@ SDL_RunAudio(void *devicep)
         }
         }
     }
     }
 
 
+    current_audio.impl.PrepareToClose(device);
+
     /* Wait for the audio to drain. */
     /* Wait for the audio to drain. */
-    current_audio.impl.WaitDone(device);
+    SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
+
+    return 0;
+}
+
+/* The general capture thread function */
+static int SDLCALL
+SDL_CaptureAudio(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;
+    void *udata = device->spec.userdata;
+    void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
+
+    SDL_assert(device->iscapture);
+
+    /* The audio mixing is always a high priority thread */
+    SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+
+    /* Perform any thread setup */
+    device->threadid = SDL_ThreadID();
+    current_audio.impl.ThreadInit(device);
+
+    /* Loop, filling the audio buffers */
+    while (!SDL_AtomicGet(&device->shutdown)) {
+        int still_need;
+        Uint8 *ptr;
+
+        if (!SDL_AtomicGet(&device->enabled) || SDL_AtomicGet(&device->paused)) {
+            SDL_Delay(delay);  /* just so we don't cook the CPU. */
+            current_audio.impl.FlushCapture(device);  /* dump anything pending. */
+            continue;
+        }
+
+        /* Fill the current buffer with sound */
+        still_need = stream_len;
+        if (device->convert.needed) {
+            ptr = stream = device->convert.buf;
+        } else {
+            /* just use the "fake" stream to hold data read from the device. */
+            ptr = stream = device->fake_stream;
+        }
+
+        /* We still read from the device when "paused" to keep the state sane,
+           and block when there isn't data so this thread isn't eating CPU.
+           But we don't process it further or call the app's callback. */
+
+        while (still_need > 0) {
+            const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
+            SDL_assert(rc <= still_need);  /* device should not overflow buffer. :) */
+            if (rc > 0) {
+                still_need -= rc;
+                ptr += rc;
+            } else {  /* uhoh, device failed for some reason! */
+                SDL_OpenedAudioDeviceDisconnected(device);
+                break;
+            }
+        }
+
+        if (still_need > 0) {
+            /* Keep any data we already read, silence the rest. */
+            SDL_memset(ptr, silence, still_need);
+        }
+
+        if (device->convert.needed) {
+            SDL_ConvertAudio(&device->convert);
+        }
+
+        /* !!! FIXME: this should be LockDevice. */
+        SDL_LockMutex(device->mixer_lock);
+        if (SDL_AtomicGet(&device->paused)) {
+            current_audio.impl.FlushCapture(device);  /* one snuck in! */
+        } else {
+            (*callback)(udata, stream, stream_len);
+        }
+        SDL_UnlockMutex(device->mixer_lock);
+    }
+
+    current_audio.impl.FlushCapture(device);
 
 
     return 0;
     return 0;
 }
 }
@@ -757,7 +963,7 @@ SDL_AudioInit(const char *driver_name)
 
 
     current_audio.detectionLock = SDL_CreateMutex();
     current_audio.detectionLock = SDL_CreateMutex();
 
 
-    finalize_audio_entry_points();
+    finish_audio_entry_points_init();
 
 
     /* Make sure we have a list of devices available at startup. */
     /* Make sure we have a list of devices available at startup. */
     current_audio.impl.DetectDevices();
     current_audio.impl.DetectDevices();
@@ -872,27 +1078,38 @@ SDL_GetAudioDeviceName(int index, int iscapture)
 static void
 static void
 close_audio_device(SDL_AudioDevice * device)
 close_audio_device(SDL_AudioDevice * device)
 {
 {
-    device->enabled = 0;
-    device->shutdown = 1;
+    if (!device) {
+        return;
+    }
+
+    if (device->id > 0) {
+        SDL_AudioDevice *opendev = open_devices[device->id - 1];
+        SDL_assert((opendev == device) || (opendev == NULL));
+        if (opendev == device) {
+            open_devices[device->id - 1] = NULL;
+        }
+    }
+
+    SDL_AtomicSet(&device->shutdown, 1);
+    SDL_AtomicSet(&device->enabled, 0);
     if (device->thread != NULL) {
     if (device->thread != NULL) {
         SDL_WaitThread(device->thread, NULL);
         SDL_WaitThread(device->thread, NULL);
     }
     }
     if (device->mixer_lock != NULL) {
     if (device->mixer_lock != NULL) {
         SDL_DestroyMutex(device->mixer_lock);
         SDL_DestroyMutex(device->mixer_lock);
     }
     }
-    SDL_FreeAudioMem(device->fake_stream);
+    SDL_free(device->fake_stream);
     if (device->convert.needed) {
     if (device->convert.needed) {
-        SDL_FreeAudioMem(device->convert.buf);
+        SDL_free(device->convert.buf);
     }
     }
-    if (device->opened) {
+    if (device->hidden != NULL) {
         current_audio.impl.CloseDevice(device);
         current_audio.impl.CloseDevice(device);
-        device->opened = 0;
     }
     }
 
 
     free_audio_queue(device->buffer_queue_head);
     free_audio_queue(device->buffer_queue_head);
     free_audio_queue(device->buffer_queue_pool);
     free_audio_queue(device->buffer_queue_pool);
 
 
-    SDL_FreeAudioMem(device);
+    SDL_free(device);
 }
 }
 
 
 
 
@@ -963,12 +1180,12 @@ open_audio_device(const char *devname, int iscapture,
                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
                   int allowed_changes, int min_id)
                   int allowed_changes, int min_id)
 {
 {
+    const SDL_bool is_internal_thread = (desired->callback != NULL);
     SDL_AudioDeviceID id = 0;
     SDL_AudioDeviceID id = 0;
     SDL_AudioSpec _obtained;
     SDL_AudioSpec _obtained;
     SDL_AudioDevice *device;
     SDL_AudioDevice *device;
     SDL_bool build_cvt;
     SDL_bool build_cvt;
     void *handle = NULL;
     void *handle = NULL;
-    Uint32 stream_len;
     int i = 0;
     int i = 0;
 
 
     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
@@ -981,6 +1198,7 @@ open_audio_device(const char *devname, int iscapture,
         return 0;
         return 0;
     }
     }
 
 
+    /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
     /* Find an available device ID... */
     /* Find an available device ID... */
     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
         if (open_devices[id] == NULL) {
         if (open_devices[id] == NULL) {
@@ -1015,7 +1233,7 @@ open_audio_device(const char *devname, int iscapture,
      *  opens of the default system device.
      *  opens of the default system device.
      */
      */
 
 
-    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
+    if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
             SDL_SetError("No such device");
             SDL_SetError("No such device");
             return 0;
             return 0;
@@ -1067,17 +1285,19 @@ open_audio_device(const char *devname, int iscapture,
         }
         }
     }
     }
 
 
-    device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
+    device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
     if (device == NULL) {
     if (device == NULL) {
         SDL_OutOfMemory();
         SDL_OutOfMemory();
         return 0;
         return 0;
     }
     }
-    SDL_zerop(device);
     device->id = id + 1;
     device->id = id + 1;
     device->spec = *obtained;
     device->spec = *obtained;
-    device->enabled = 1;
-    device->paused = 1;
-    device->iscapture = iscapture;
+    device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
+    device->handle = handle;
+
+    SDL_AtomicSet(&device->shutdown, 0);  /* just in case. */
+    SDL_AtomicSet(&device->paused, 1);
+    SDL_AtomicSet(&device->enabled, 1);
 
 
     /* Create a mutex for locking the sound buffers */
     /* Create a mutex for locking the sound buffers */
     if (!current_audio.impl.SkipMixerLock) {
     if (!current_audio.impl.SkipMixerLock) {
@@ -1093,7 +1313,10 @@ open_audio_device(const char *devname, int iscapture,
         close_audio_device(device);
         close_audio_device(device);
         return 0;
         return 0;
     }
     }
-    device->opened = 1;
+
+    /* if your target really doesn't need it, set it to 0x1 or something. */
+    /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
+    SDL_assert(device->hidden != NULL);
 
 
     /* See if we need to do any conversion */
     /* See if we need to do any conversion */
     build_cvt = SDL_FALSE;
     build_cvt = SDL_FALSE;
@@ -1143,7 +1366,7 @@ open_audio_device(const char *devname, int iscapture,
                                          device->convert.len_ratio);
                                          device->convert.len_ratio);
 
 
             device->convert.buf =
             device->convert.buf =
-                (Uint8 *) SDL_AllocAudioMem(device->convert.len *
+                (Uint8 *) SDL_malloc(device->convert.len *
                                             device->convert.len_mult);
                                             device->convert.len_mult);
             if (device->convert.buf == NULL) {
             if (device->convert.buf == NULL) {
                 close_audio_device(device);
                 close_audio_device(device);
@@ -1153,19 +1376,6 @@ open_audio_device(const char *devname, int iscapture,
         }
         }
     }
     }
 
 
-    /* Allocate a fake audio memory buffer */
-    stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
-    if (device->spec.size > stream_len) {
-        stream_len = device->spec.size;
-    }
-    SDL_assert(stream_len > 0);
-    device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
-    if (device->fake_stream == NULL) {
-        close_audio_device(device);
-        SDL_OutOfMemory();
-        return 0;
-    }
-
     if (device->spec.callback == NULL) {  /* use buffer queueing? */
     if (device->spec.callback == NULL) {  /* use buffer queueing? */
         /* pool a few packets to start. Enough for two callbacks. */
         /* pool a few packets to start. Enough for two callbacks. */
         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
@@ -1181,7 +1391,7 @@ open_audio_device(const char *devname, int iscapture,
             }
             }
         }
         }
 
 
-        device->spec.callback = SDL_BufferQueueDrainCallback;
+        device->spec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
         device->spec.userdata = device;
         device->spec.userdata = device;
     }
     }
 
 
@@ -1191,21 +1401,30 @@ open_audio_device(const char *devname, int iscapture,
     /* Start the audio thread if necessary */
     /* Start the audio thread if necessary */
     if (!current_audio.impl.ProvidesOwnCallbackThread) {
     if (!current_audio.impl.ProvidesOwnCallbackThread) {
         /* Start the audio thread */
         /* Start the audio thread */
-        char name[64];
-        SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
-/* !!! FIXME: this is nasty. */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
-        device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
-#else
-        device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
-#endif
-#else
-        device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
-#endif
+        /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
+        /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
+        const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
+        char threadname[64];
+
+        /* Allocate a fake audio buffer; only used by our internal threads. */
+        Uint32 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_malloc(stream_len);
+        if (device->fake_stream == NULL) {
+            close_audio_device(device);
+            SDL_OutOfMemory();
+            return 0;
+        }
+
+        SDL_snprintf(threadname, sizeof (threadname), "SDLAudioDev%d", (int) device->id);
+        device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
+
         if (device->thread == NULL) {
         if (device->thread == NULL) {
-            SDL_CloseAudioDevice(device->id);
+            close_audio_device(device);
             SDL_SetError("Couldn't create audio thread");
             SDL_SetError("Couldn't create audio thread");
             return 0;
             return 0;
         }
         }
@@ -1258,8 +1477,8 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
 {
 {
     SDL_AudioDevice *device = get_audio_device(devid);
     SDL_AudioDevice *device = get_audio_device(devid);
     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
-    if (device && device->enabled) {
-        if (device->paused) {
+    if (device && SDL_AtomicGet(&device->enabled)) {
+        if (SDL_AtomicGet(&device->paused)) {
             status = SDL_AUDIO_PAUSED;
             status = SDL_AUDIO_PAUSED;
         } else {
         } else {
             status = SDL_AUDIO_PLAYING;
             status = SDL_AUDIO_PLAYING;
@@ -1281,7 +1500,7 @@ SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
     SDL_AudioDevice *device = get_audio_device(devid);
     SDL_AudioDevice *device = get_audio_device(devid);
     if (device) {
     if (device) {
         current_audio.impl.LockDevice(device);
         current_audio.impl.LockDevice(device);
-        device->paused = pause_on;
+        SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
         current_audio.impl.UnlockDevice(device);
         current_audio.impl.UnlockDevice(device);
     }
     }
 }
 }
@@ -1328,11 +1547,7 @@ SDL_UnlockAudio(void)
 void
 void
 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
 {
 {
-    SDL_AudioDevice *device = get_audio_device(devid);
-    if (device) {
-        close_audio_device(device);
-        open_devices[devid - 1] = NULL;
-    }
+    close_audio_device(get_audio_device(devid));
 }
 }
 
 
 void
 void
@@ -1351,9 +1566,7 @@ SDL_AudioQuit(void)
     }
     }
 
 
     for (i = 0; i < SDL_arraysize(open_devices); i++) {
     for (i = 0; i < SDL_arraysize(open_devices); i++) {
-        if (open_devices[i] != NULL) {
-            SDL_CloseAudioDevice(i+1);
-        }
+        close_audio_device(open_devices[i]);
     }
     }
 
 
     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);

+ 0 - 3
Engine/lib/sdl/src/audio/SDL_audio_c.h

@@ -29,9 +29,6 @@ extern SDL_AudioFormat SDL_NextAudioFormat(void);
 /* Function to calculate the size and silence for a SDL_AudioSpec */
 /* Function to calculate the size and silence for a SDL_AudioSpec */
 extern void SDL_CalculateAudioSpec(SDL_AudioSpec * spec);
 extern void SDL_CalculateAudioSpec(SDL_AudioSpec * spec);
 
 
-/* The actual mixing thread function */
-extern int SDLCALL SDL_RunAudio(void *audiop);
-
 /* this is used internally to access some autogenerated code. */
 /* this is used internally to access some autogenerated code. */
 typedef struct
 typedef struct
 {
 {

+ 49 - 1
Engine/lib/sdl/src/audio/SDL_mixer.c

@@ -202,6 +202,54 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
         }
         }
         break;
         break;
 
 
+    case AUDIO_U16LSB:
+        {
+            Uint16 src1, src2;
+            int dst_sample;
+            const int max_audioval = 0xFFFF;
+
+            len /= 2;
+            while (len--) {
+                src1 = ((src[1]) << 8 | src[0]);
+                ADJUST_VOLUME(src1, volume);
+                src2 = ((dst[1]) << 8 | dst[0]);
+                src += 2;
+                dst_sample = src1 + src2;
+                if (dst_sample > max_audioval) {
+                    dst_sample = max_audioval;
+                }
+                dst[0] = dst_sample & 0xFF;
+                dst_sample >>= 8;
+                dst[1] = dst_sample & 0xFF;
+                dst += 2;
+            }
+        }
+        break;
+
+    case AUDIO_U16MSB:
+        {
+            Uint16 src1, src2;
+            int dst_sample;
+            const int max_audioval = 0xFFFF;
+
+            len /= 2;
+            while (len--) {
+                src1 = ((src[0]) << 8 | src[1]);
+                ADJUST_VOLUME(src1, volume);
+                src2 = ((dst[0]) << 8 | dst[1]);
+                src += 2;
+                dst_sample = src1 + src2;
+                if (dst_sample > max_audioval) {
+                    dst_sample = max_audioval;
+                }
+                dst[1] = dst_sample & 0xFF;
+                dst_sample >>= 8;
+                dst[0] = dst_sample & 0xFF;
+                dst += 2;
+            }
+        }
+        break;
+
     case AUDIO_S32LSB:
     case AUDIO_S32LSB:
         {
         {
             const Uint32 *src32 = (Uint32 *) src;
             const Uint32 *src32 = (Uint32 *) src;
@@ -313,7 +361,7 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
         break;
         break;
 
 
     default:                   /* If this happens... FIXME! */
     default:                   /* If this happens... FIXME! */
-        SDL_SetError("SDL_MixAudio(): unknown audio format");
+        SDL_SetError("SDL_MixAudioFormat(): unknown audio format");
         return;
         return;
     }
     }
 }
 }

+ 15 - 9
Engine/lib/sdl/src/audio/SDL_sysaudio.h

@@ -26,6 +26,10 @@
 #include "SDL_mutex.h"
 #include "SDL_mutex.h"
 #include "SDL_thread.h"
 #include "SDL_thread.h"
 
 
+/* !!! FIXME: These are wordy and unlocalized... */
+#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
+#define DEFAULT_INPUT_DEVNAME "System audio capture device"
+
 /* The SDL audio driver */
 /* The SDL audio driver */
 typedef struct SDL_AudioDevice SDL_AudioDevice;
 typedef struct SDL_AudioDevice SDL_AudioDevice;
 #define _THIS   SDL_AudioDevice *_this
 #define _THIS   SDL_AudioDevice *_this
@@ -75,7 +79,9 @@ typedef struct SDL_AudioDriverImpl
     void (*PlayDevice) (_THIS);
     void (*PlayDevice) (_THIS);
     int (*GetPendingBytes) (_THIS);
     int (*GetPendingBytes) (_THIS);
     Uint8 *(*GetDeviceBuf) (_THIS);
     Uint8 *(*GetDeviceBuf) (_THIS);
-    void (*WaitDone) (_THIS);
+    int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
+    void (*FlushCapture) (_THIS);
+    void (*PrepareToClose) (_THIS);  /**< Called between run and draining wait for playback devices */
     void (*CloseDevice) (_THIS);
     void (*CloseDevice) (_THIS);
     void (*LockDevice) (_THIS);
     void (*LockDevice) (_THIS);
     void (*UnlockDevice) (_THIS);
     void (*UnlockDevice) (_THIS);
@@ -87,10 +93,10 @@ typedef struct SDL_AudioDriverImpl
     /* Some flags to push duplicate code into the core and reduce #ifdefs. */
     /* Some flags to push duplicate code into the core and reduce #ifdefs. */
     /* !!! FIXME: these should be SDL_bool */
     /* !!! FIXME: these should be SDL_bool */
     int ProvidesOwnCallbackThread;
     int ProvidesOwnCallbackThread;
-    int SkipMixerLock;  /* !!! FIXME: do we need this anymore? */
+    int SkipMixerLock;
     int HasCaptureSupport;
     int HasCaptureSupport;
     int OnlyHasDefaultOutputDevice;
     int OnlyHasDefaultOutputDevice;
-    int OnlyHasDefaultInputDevice;
+    int OnlyHasDefaultCaptureDevice;
     int AllowsArbitraryDeviceNames;
     int AllowsArbitraryDeviceNames;
 } SDL_AudioDriverImpl;
 } SDL_AudioDriverImpl;
 
 
@@ -157,12 +163,10 @@ struct SDL_AudioDevice
     SDL_AudioStreamer streamer;
     SDL_AudioStreamer streamer;
 
 
     /* Current state flags */
     /* Current state flags */
-    /* !!! FIXME: should be SDL_bool */
-    int iscapture;
-    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;
+    SDL_atomic_t shutdown; /* true if we are signaling the play thread to end. */
+    SDL_atomic_t enabled;  /* true if device is functioning and connected. */
+    SDL_atomic_t paused;
+    SDL_bool iscapture;
 
 
     /* Fake audio buffer for when the audio hardware is busy */
     /* Fake audio buffer for when the audio hardware is busy */
     Uint8 *fake_stream;
     Uint8 *fake_stream;
@@ -183,6 +187,8 @@ struct SDL_AudioDevice
     /* * * */
     /* * * */
     /* Data private to this driver */
     /* Data private to this driver */
     struct SDL_PrivateAudioData *hidden;
     struct SDL_PrivateAudioData *hidden;
+
+    void *handle;
 };
 };
 #undef _THIS
 #undef _THIS
 
 

+ 1 - 1
Engine/lib/sdl/src/audio/SDL_wave.c

@@ -504,7 +504,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
         was_error = 1;
         was_error = 1;
         goto done;
         goto done;
     }
     }
-    SDL_memset(spec, 0, (sizeof *spec));
+    SDL_zerop(spec);
     spec->freq = SDL_SwapLE32(format->frequency);
     spec->freq = SDL_SwapLE32(format->frequency);
 
 
     if (IEEE_float_encoded) {
     if (IEEE_float_encoded) {

+ 374 - 76
Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c

@@ -29,9 +29,9 @@
 #include <errno.h>
 #include <errno.h>
 #include <string.h>
 #include <string.h>
 
 
+#include "SDL_assert.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_alsa_audio.h"
 #include "SDL_alsa_audio.h"
 
 
@@ -42,8 +42,10 @@
 static int (*ALSA_snd_pcm_open)
 static int (*ALSA_snd_pcm_open)
   (snd_pcm_t **, const char *, snd_pcm_stream_t, int);
   (snd_pcm_t **, const char *, snd_pcm_stream_t, int);
 static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
 static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
-static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
+static snd_pcm_sframes_t (*ALSA_snd_pcm_writei)
   (snd_pcm_t *, const void *, snd_pcm_uframes_t);
   (snd_pcm_t *, const void *, snd_pcm_uframes_t);
+static snd_pcm_sframes_t (*ALSA_snd_pcm_readi)
+  (snd_pcm_t *, void *, snd_pcm_uframes_t);
 static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
 static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
 static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
 static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
 static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
 static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
@@ -85,6 +87,10 @@ static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
 static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
 static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
 static int (*ALSA_snd_pcm_sw_params_set_avail_min)
 static int (*ALSA_snd_pcm_sw_params_set_avail_min)
   (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
   (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
+static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
+static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
+static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
+static int (*ALSA_snd_device_name_free_hint) (void **);
 
 
 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
 #define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
 #define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
@@ -118,6 +124,7 @@ load_alsa_syms(void)
     SDL_ALSA_SYM(snd_pcm_open);
     SDL_ALSA_SYM(snd_pcm_open);
     SDL_ALSA_SYM(snd_pcm_close);
     SDL_ALSA_SYM(snd_pcm_close);
     SDL_ALSA_SYM(snd_pcm_writei);
     SDL_ALSA_SYM(snd_pcm_writei);
+    SDL_ALSA_SYM(snd_pcm_readi);
     SDL_ALSA_SYM(snd_pcm_recover);
     SDL_ALSA_SYM(snd_pcm_recover);
     SDL_ALSA_SYM(snd_pcm_prepare);
     SDL_ALSA_SYM(snd_pcm_prepare);
     SDL_ALSA_SYM(snd_pcm_drain);
     SDL_ALSA_SYM(snd_pcm_drain);
@@ -144,6 +151,11 @@ load_alsa_syms(void)
     SDL_ALSA_SYM(snd_pcm_nonblock);
     SDL_ALSA_SYM(snd_pcm_nonblock);
     SDL_ALSA_SYM(snd_pcm_wait);
     SDL_ALSA_SYM(snd_pcm_wait);
     SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
     SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
+    SDL_ALSA_SYM(snd_pcm_reset);
+    SDL_ALSA_SYM(snd_device_name_hint);
+    SDL_ALSA_SYM(snd_device_name_get_hint);
+    SDL_ALSA_SYM(snd_device_name_free_hint);
+
     return 0;
     return 0;
 }
 }
 
 
@@ -196,25 +208,27 @@ LoadALSALibrary(void)
 #endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */
 #endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */
 
 
 static const char *
 static const char *
-get_audio_device(int channels)
+get_audio_device(void *handle, const int channels)
 {
 {
     const char *device;
     const char *device;
 
 
+    if (handle != NULL) {
+        return (const char *) handle;
+    }
+
+    /* !!! FIXME: we also check "SDL_AUDIO_DEVICE_NAME" at the higher level. */
     device = SDL_getenv("AUDIODEV");    /* Is there a standard variable name? */
     device = SDL_getenv("AUDIODEV");    /* Is there a standard variable name? */
-    if (device == NULL) {
-        switch (channels) {
-        case 6:
-            device = "plug:surround51";
-            break;
-        case 4:
-            device = "plug:surround40";
-            break;
-        default:
-            device = "default";
-            break;
-        }
+    if (device != NULL) {
+        return device;
+    }
+
+    if (channels == 6) {
+        return "plug:surround51";
+    } else if (channels == 4) {
+        return "plug:surround40";
     }
     }
-    return device;
+
+    return "default";
 }
 }
 
 
 
 
@@ -232,37 +246,37 @@ ALSA_WaitDevice(_THIS)
  * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
  * "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
  *  and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
  *  and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
  */
  */
-#define SWIZ6(T) \
-    T *ptr = (T *) this->hidden->mixbuf; \
+#define SWIZ6(T, buf, numframes) \
+    T *ptr = (T *) buf; \
     Uint32 i; \
     Uint32 i; \
-    for (i = 0; i < this->spec.samples; i++, ptr += 6) { \
+    for (i = 0; i < numframes; i++, ptr += 6) { \
         T tmp; \
         T tmp; \
         tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
         tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
         tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
         tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
     }
     }
 
 
 static SDL_INLINE void
 static SDL_INLINE void
-swizzle_alsa_channels_6_64bit(_THIS)
+swizzle_alsa_channels_6_64bit(void *buffer, Uint32 bufferlen)
 {
 {
-    SWIZ6(Uint64);
+    SWIZ6(Uint64, buffer, bufferlen);
 }
 }
 
 
 static SDL_INLINE void
 static SDL_INLINE void
-swizzle_alsa_channels_6_32bit(_THIS)
+swizzle_alsa_channels_6_32bit(void *buffer, Uint32 bufferlen)
 {
 {
-    SWIZ6(Uint32);
+    SWIZ6(Uint32, buffer, bufferlen);
 }
 }
 
 
 static SDL_INLINE void
 static SDL_INLINE void
-swizzle_alsa_channels_6_16bit(_THIS)
+swizzle_alsa_channels_6_16bit(void *buffer, Uint32 bufferlen)
 {
 {
-    SWIZ6(Uint16);
+    SWIZ6(Uint16, buffer, bufferlen);
 }
 }
 
 
 static SDL_INLINE void
 static SDL_INLINE void
-swizzle_alsa_channels_6_8bit(_THIS)
+swizzle_alsa_channels_6_8bit(void *buffer, Uint32 bufferlen)
 {
 {
-    SWIZ6(Uint8);
+    SWIZ6(Uint8, buffer, bufferlen);
 }
 }
 
 
 #undef SWIZ6
 #undef SWIZ6
@@ -273,18 +287,16 @@ swizzle_alsa_channels_6_8bit(_THIS)
  *  channels from Windows/Mac order to the format alsalib will want.
  *  channels from Windows/Mac order to the format alsalib will want.
  */
  */
 static SDL_INLINE void
 static SDL_INLINE void
-swizzle_alsa_channels(_THIS)
+swizzle_alsa_channels(_THIS, void *buffer, Uint32 bufferlen)
 {
 {
     if (this->spec.channels == 6) {
     if (this->spec.channels == 6) {
-        const Uint16 fmtsize = (this->spec.format & 0xFF);      /* bits/channel. */
-        if (fmtsize == 16)
-            swizzle_alsa_channels_6_16bit(this);
-        else if (fmtsize == 8)
-            swizzle_alsa_channels_6_8bit(this);
-        else if (fmtsize == 32)
-            swizzle_alsa_channels_6_32bit(this);
-        else if (fmtsize == 64)
-            swizzle_alsa_channels_6_64bit(this);
+        switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
+            case 8: swizzle_alsa_channels_6_8bit(buffer, bufferlen); break;
+            case 16: swizzle_alsa_channels_6_16bit(buffer, bufferlen); break;
+            case 32: swizzle_alsa_channels_6_32bit(buffer, bufferlen); break;
+            case 64: swizzle_alsa_channels_6_64bit(buffer, bufferlen); break;
+            default: SDL_assert(!"unhandled bitsize"); break;
+        }
     }
     }
 
 
     /* !!! FIXME: update this for 7.1 if needed, later. */
     /* !!! FIXME: update this for 7.1 if needed, later. */
@@ -294,19 +306,29 @@ swizzle_alsa_channels(_THIS)
 static void
 static void
 ALSA_PlayDevice(_THIS)
 ALSA_PlayDevice(_THIS)
 {
 {
-    int status;
     const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
     const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
-    const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) *
+    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
                                 this->spec.channels;
                                 this->spec.channels;
     snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
     snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
 
 
-    swizzle_alsa_channels(this);
+    swizzle_alsa_channels(this, this->hidden->mixbuf, frames_left);
+
+    while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
+        int status;
+
+        /* This wait is a work-around for a hang when USB devices are
+           unplugged.  Normally it should not result in any waiting,
+           but in the case of a USB unplug, it serves as a way to
+           join the playback thread after the timeout occurs */
+        status = ALSA_snd_pcm_wait(this->hidden->pcm_handle, 1000);
+        if (status == 0) {
+            /*fprintf(stderr, "ALSA timeout waiting for available buffer space\n");*/
+            SDL_OpenedAudioDeviceDisconnected(this);
+            return;
+        }
 
 
-    while ( frames_left > 0 && this->enabled ) {
-        /* !!! FIXME: This works, but needs more testing before going live */
-        /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
         status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
         status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
-                                     sample_buf, frames_left);
+                                         sample_buf, frames_left);
 
 
         if (status < 0) {
         if (status < 0) {
             if (status == -EAGAIN) {
             if (status == -EAGAIN) {
@@ -336,20 +358,71 @@ ALSA_GetDeviceBuf(_THIS)
     return (this->hidden->mixbuf);
     return (this->hidden->mixbuf);
 }
 }
 
 
+static int
+ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    Uint8 *sample_buf = (Uint8 *) buffer;
+    const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
+                                this->spec.channels;
+    const int total_frames = buflen / frame_size;
+    snd_pcm_uframes_t frames_left = total_frames;
+
+    SDL_assert((buflen % frame_size) == 0);
+
+    while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
+        /* !!! FIXME: This works, but needs more testing before going live */
+        /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
+        int status = ALSA_snd_pcm_readi(this->hidden->pcm_handle,
+                                        sample_buf, frames_left);
+
+        if (status < 0) {
+            /*printf("ALSA: capture error %d\n", status);*/
+            if (status == -EAGAIN) {
+                /* Apparently snd_pcm_recover() doesn't handle this case -
+                   does it assume snd_pcm_wait() above? */
+                SDL_Delay(1);
+                continue;
+            }
+            status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
+            if (status < 0) {
+                /* Hmm, not much we can do - abort */
+                fprintf(stderr, "ALSA read failed (unrecoverable): %s\n",
+                        ALSA_snd_strerror(status));
+                return -1;
+            }
+            continue;
+        }
+
+        /*printf("ALSA: captured %d bytes\n", status * frame_size);*/
+        sample_buf += status * frame_size;
+        frames_left -= status;
+    }
+
+    swizzle_alsa_channels(this, buffer, total_frames - frames_left);
+
+    return (total_frames - frames_left) * frame_size;
+}
+
+static void
+ALSA_FlushCapture(_THIS)
+{
+    ALSA_snd_pcm_reset(this->hidden->pcm_handle);
+}
+
 static void
 static void
 ALSA_CloseDevice(_THIS)
 ALSA_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->pcm_handle) {
-            ALSA_snd_pcm_drain(this->hidden->pcm_handle);
-            ALSA_snd_pcm_close(this->hidden->pcm_handle);
-            this->hidden->pcm_handle = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->pcm_handle) {
+	/* Wait for the submitted audio to drain
+           ALSA_snd_pcm_drop() can hang, so don't use that.
+         */
+        Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2;
+        SDL_Delay(delay);
+
+        ALSA_snd_pcm_close(this->hidden->pcm_handle);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -482,16 +555,16 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
     /* Name of device should depend on # channels in spec */
     /* Name of device should depend on # channels in spec */
     status = ALSA_snd_pcm_open(&pcm_handle,
     status = ALSA_snd_pcm_open(&pcm_handle,
-                               get_audio_device(this->spec.channels),
-                               SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+                get_audio_device(handle, this->spec.channels),
+                iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
+                SND_PCM_NONBLOCK);
 
 
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't open audio device: %s",
         return SDL_SetError("ALSA: Couldn't open audio device: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
@@ -502,7 +575,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     snd_pcm_hw_params_alloca(&hwparams);
     snd_pcm_hw_params_alloca(&hwparams);
     status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
     status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't get hardware config: %s",
         return SDL_SetError("ALSA: Couldn't get hardware config: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
@@ -511,7 +583,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
     status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
                                                SND_PCM_ACCESS_RW_INTERLEAVED);
                                                SND_PCM_ACCESS_RW_INTERLEAVED);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set interleaved access: %s",
         return SDL_SetError("ALSA: Couldn't set interleaved access: %s",
                      ALSA_snd_strerror(status));
                      ALSA_snd_strerror(status));
     }
     }
@@ -565,7 +636,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         }
         }
     }
     }
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't find any hardware audio formats");
         return SDL_SetError("ALSA: Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
@@ -577,7 +647,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (status < 0) {
     if (status < 0) {
         status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
         status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
         if (status < 0) {
         if (status < 0) {
-            ALSA_CloseDevice(this);
             return SDL_SetError("ALSA: Couldn't set audio channels");
             return SDL_SetError("ALSA: Couldn't set audio channels");
         }
         }
         this->spec.channels = channels;
         this->spec.channels = channels;
@@ -588,7 +657,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
     status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
                                                   &rate, NULL);
                                                   &rate, NULL);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set audio frequency: %s",
         return SDL_SetError("ALSA: Couldn't set audio frequency: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
@@ -598,8 +666,8 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
     if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
          ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
          ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
         /* Failed to set desired buffer size, do the best you can... */
         /* Failed to set desired buffer size, do the best you can... */
-        if ( ALSA_set_period_size(this, hwparams, 1) < 0 ) {
-            ALSA_CloseDevice(this);
+        status = ALSA_set_period_size(this, hwparams, 1);
+        if (status < 0) {
             return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
             return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
         }
         }
     }
     }
@@ -607,26 +675,22 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     snd_pcm_sw_params_alloca(&swparams);
     snd_pcm_sw_params_alloca(&swparams);
     status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
     status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't get software config: %s",
         return SDL_SetError("ALSA: Couldn't get software config: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
     status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, this->spec.samples);
     status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, this->spec.samples);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("Couldn't set minimum available samples: %s",
         return SDL_SetError("Couldn't set minimum available samples: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
     status =
     status =
         ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
         ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("ALSA: Couldn't set start threshold: %s",
         return SDL_SetError("ALSA: Couldn't set start threshold: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
     status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
     status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
     if (status < 0) {
     if (status < 0) {
-        ALSA_CloseDevice(this);
         return SDL_SetError("Couldn't set software audio parameters: %s",
         return SDL_SetError("Couldn't set software audio parameters: %s",
                             ALSA_snd_strerror(status));
                             ALSA_snd_strerror(status));
     }
     }
@@ -635,13 +699,14 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        ALSA_CloseDevice(this);
-        return SDL_OutOfMemory();
+    if (!iscapture) {
+        this->hidden->mixlen = this->spec.size;
+        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+        if (this->hidden->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
     }
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
 
 
     /* Switch to blocking mode for playback */
     /* Switch to blocking mode for playback */
     ALSA_snd_pcm_nonblock(pcm_handle, 0);
     ALSA_snd_pcm_nonblock(pcm_handle, 0);
@@ -650,9 +715,238 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     return 0;
     return 0;
 }
 }
 
 
+typedef struct ALSA_Device
+{
+    char *name;
+    SDL_bool iscapture;
+    struct ALSA_Device *next;
+} ALSA_Device;
+
+static void
+add_device(const int iscapture, const char *name, void *hint, ALSA_Device **pSeen)
+{
+    ALSA_Device *dev = SDL_malloc(sizeof (ALSA_Device));
+    char *desc = ALSA_snd_device_name_get_hint(hint, "DESC");
+    char *handle = NULL;
+    char *ptr;
+
+    if (!desc) {
+        SDL_free(dev);
+        return;
+    } else if (!dev) {
+        free(desc);
+        return;
+    }
+
+    SDL_assert(name != NULL);
+
+    /* some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output".
+       just chop the extra lines off, this seems to get a reasonable device
+       name without extra details. */
+    if ((ptr = strchr(desc, '\n')) != NULL) {
+        *ptr = '\0';
+    }
+
+    /*printf("ALSA: adding %s device '%s' (%s)\n", iscapture ? "capture" : "output", name, desc);*/
+
+    handle = SDL_strdup(name);
+    if (!handle) {
+        free(desc);
+        SDL_free(dev);
+        return;
+    }
+
+    SDL_AddAudioDevice(iscapture, desc, handle);
+    free(desc);
+
+    dev->name = handle;
+    dev->iscapture = iscapture;
+    dev->next = *pSeen;
+    *pSeen = dev;
+}
+
+
+static SDL_atomic_t ALSA_hotplug_shutdown;
+static SDL_Thread *ALSA_hotplug_thread;
+
+static int SDLCALL
+ALSA_HotplugThread(void *arg)
+{
+    SDL_sem *first_run_semaphore = (SDL_sem *) arg;
+    ALSA_Device *devices = NULL;
+    ALSA_Device *next;
+    ALSA_Device *dev;
+    Uint32 ticks;
+
+    while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) {
+        void **hints = NULL;
+        if (ALSA_snd_device_name_hint(-1, "pcm", &hints) != -1) {
+            ALSA_Device *unseen = devices;
+            ALSA_Device *seen = NULL;
+            ALSA_Device *prev;
+            int i, j;
+            const char *match = NULL;
+            int bestmatch = 0xFFFF;
+            size_t match_len = 0;
+            int defaultdev = -1;
+            static const char * const prefixes[] = {
+                "hw:", "sysdefault:", "default:", NULL
+            };
+
+            /* Apparently there are several different ways that ALSA lists
+               actual hardware. It could be prefixed with "hw:" or "default:"
+               or "sysdefault:" and maybe others. Go through the list and see
+               if we can find a preferred prefix for the system. */
+            for (i = 0; hints[i]; i++) {
+                char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
+                if (!name) {
+                    continue;
+                }
+
+                /* full name, not a prefix */
+                if ((defaultdev == -1) && (SDL_strcmp(name, "default") == 0)) {
+                    defaultdev = i;
+                }
+
+                for (j = 0; prefixes[j]; j++) {
+                    const char *prefix = prefixes[j];
+                    const size_t prefixlen = SDL_strlen(prefix);
+                    if (SDL_strncmp(name, prefix, prefixlen) == 0) {
+                        if (j < bestmatch) {
+                            bestmatch = j;
+                            match = prefix;
+                            match_len = prefixlen;
+                        }
+                    }
+                }
+
+                free(name);
+            }
+
+            /* look through the list of device names to find matches */
+            for (i = 0; hints[i]; i++) {
+                char *name;
+
+                /* if we didn't find a device name prefix we like at all... */
+                if ((!match) && (defaultdev != i)) {
+                    continue;  /* ...skip anything that isn't the default device. */
+                }
+
+                name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
+                if (!name) {
+                    continue;
+                }
+
+                /* only want physical hardware interfaces */
+                if (!match || (SDL_strncmp(name, match, match_len) == 0)) {
+                    char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID");
+                    const SDL_bool isoutput = (ioid == NULL) || (SDL_strcmp(ioid, "Output") == 0);
+                    const SDL_bool isinput = (ioid == NULL) || (SDL_strcmp(ioid, "Input") == 0);
+                    SDL_bool have_output = SDL_FALSE;
+                    SDL_bool have_input = SDL_FALSE;
+
+                    free(ioid);
+
+                    if (!isoutput && !isinput) {
+                        free(name);
+                        continue;
+                    }
+
+                    prev = NULL;
+                    for (dev = unseen; dev; dev = next) {
+                        next = dev->next;
+                        if ( (SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->iscapture) || ((isoutput) && !dev->iscapture)) ) {
+                            if (prev) {
+                                prev->next = next;
+                            } else {
+                                unseen = next;
+                            }
+                            dev->next = seen;
+                            seen = dev;
+                            if (isinput) have_input = SDL_TRUE;
+                            if (isoutput) have_output = SDL_TRUE;
+                        } else {
+                            prev = dev;
+                        }
+                    }
+
+                    if (isinput && !have_input) {
+                        add_device(SDL_TRUE, name, hints[i], &seen);
+                    }
+                    if (isoutput && !have_output) {
+                        add_device(SDL_FALSE, name, hints[i], &seen);
+                    }
+                }
+
+                free(name);
+            }
+
+            ALSA_snd_device_name_free_hint(hints);
+
+            devices = seen;   /* now we have a known-good list of attached devices. */
+
+            /* report anything still in unseen as removed. */
+            for (dev = unseen; dev; dev = next) {
+                /*printf("ALSA: removing %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
+                next = dev->next;
+                SDL_RemoveAudioDevice(dev->iscapture, dev->name);
+                SDL_free(dev->name);
+                SDL_free(dev);
+            }
+        }
+
+        /* On first run, tell ALSA_DetectDevices() that we have a complete device list so it can return. */
+        if (first_run_semaphore) {
+            SDL_SemPost(first_run_semaphore);
+            first_run_semaphore = NULL;  /* let other thread clean it up. */
+        }
+
+        /* Block awhile before checking again, unless we're told to stop. */
+        ticks = SDL_GetTicks() + 5000;
+        while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && !SDL_TICKS_PASSED(SDL_GetTicks(), ticks)) {
+            SDL_Delay(100);
+        }
+    }
+
+    /* Shutting down! Clean up any data we've gathered. */
+    for (dev = devices; dev; dev = next) {
+        /*printf("ALSA: at shutdown, removing %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
+        next = dev->next;
+        SDL_free(dev->name);
+        SDL_free(dev);
+    }
+
+    return 0;
+}
+
+static void
+ALSA_DetectDevices(void)
+{
+    /* Start the device detection thread here, wait for an initial iteration to complete. */
+    SDL_sem *semaphore = SDL_CreateSemaphore(0);
+    if (!semaphore) {
+        return;  /* oh well. */
+    }
+
+    SDL_AtomicSet(&ALSA_hotplug_shutdown, 0);
+
+    ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", semaphore);
+    if (ALSA_hotplug_thread) {
+        SDL_SemWait(semaphore);  /* wait for the first iteration to finish. */
+    }
+
+    SDL_DestroySemaphore(semaphore);
+}
+
 static void
 static void
 ALSA_Deinitialize(void)
 ALSA_Deinitialize(void)
 {
 {
+    if (ALSA_hotplug_thread != NULL) {
+        SDL_AtomicSet(&ALSA_hotplug_shutdown, 1);
+        SDL_WaitThread(ALSA_hotplug_thread, NULL);
+        ALSA_hotplug_thread = NULL;
+    }
+
     UnloadALSALibrary();
     UnloadALSALibrary();
 }
 }
 
 
@@ -664,13 +958,17 @@ ALSA_Init(SDL_AudioDriverImpl * impl)
     }
     }
 
 
     /* Set the function pointers */
     /* Set the function pointers */
+    impl->DetectDevices = ALSA_DetectDevices;
     impl->OpenDevice = ALSA_OpenDevice;
     impl->OpenDevice = ALSA_OpenDevice;
     impl->WaitDevice = ALSA_WaitDevice;
     impl->WaitDevice = ALSA_WaitDevice;
     impl->GetDeviceBuf = ALSA_GetDeviceBuf;
     impl->GetDeviceBuf = ALSA_GetDeviceBuf;
     impl->PlayDevice = ALSA_PlayDevice;
     impl->PlayDevice = ALSA_PlayDevice;
     impl->CloseDevice = ALSA_CloseDevice;
     impl->CloseDevice = ALSA_CloseDevice;
     impl->Deinitialize = ALSA_Deinitialize;
     impl->Deinitialize = ALSA_Deinitialize;
-    impl->OnlyHasDefaultOutputDevice = 1;       /* !!! FIXME: Add device enum! */
+    impl->CaptureFromDevice = ALSA_CaptureFromDevice;
+    impl->FlushCapture = ALSA_FlushCapture;
+
+    impl->HasCaptureSupport = SDL_TRUE;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }

+ 73 - 36
Engine/lib/sdl/src/audio/android/SDL_androidaudio.c

@@ -24,6 +24,7 @@
 
 
 /* Output audio to Android */
 /* Output audio to Android */
 
 
+#include "SDL_assert.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_androidaudio.h"
 #include "SDL_androidaudio.h"
@@ -33,23 +34,22 @@
 #include <android/log.h>
 #include <android/log.h>
 
 
 static SDL_AudioDevice* audioDevice = NULL;
 static SDL_AudioDevice* audioDevice = NULL;
+static SDL_AudioDevice* captureDevice = NULL;
 
 
 static int
 static int
-AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
     SDL_AudioFormat test_format;
     SDL_AudioFormat test_format;
 
 
-    if (iscapture) {
-        /* TODO: implement capture */
-        return SDL_SetError("Capture not supported on Android");
-    }
+    SDL_assert((captureDevice == NULL) || !iscapture);
+    SDL_assert((audioDevice == NULL) || iscapture);
 
 
-    if (audioDevice != NULL) {
-        return SDL_SetError("Only one audio device at a time please!");
+    if (iscapture) {
+        captureDevice = this;
+    } else {
+        audioDevice = this;
     }
     }
 
 
-    audioDevice = this;
-    
     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
@@ -82,100 +82,137 @@ AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         this->spec.freq = 48000;
         this->spec.freq = 48000;
     }
     }
 
 
-    /* TODO: pass in/return a (Java) device ID, also whether we're opening for input or output */
-    this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
-    SDL_CalculateAudioSpec(&this->spec);
+    /* TODO: pass in/return a (Java) device ID */
+    this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
 
 
     if (this->spec.samples == 0) {
     if (this->spec.samples == 0) {
         /* Init failed? */
         /* Init failed? */
         return SDL_SetError("Java-side initialization failed!");
         return SDL_SetError("Java-side initialization failed!");
     }
     }
 
 
+    SDL_CalculateAudioSpec(&this->spec);
+
     return 0;
     return 0;
 }
 }
 
 
 static void
 static void
-AndroidAUD_PlayDevice(_THIS)
+ANDROIDAUDIO_PlayDevice(_THIS)
 {
 {
     Android_JNI_WriteAudioBuffer();
     Android_JNI_WriteAudioBuffer();
 }
 }
 
 
 static Uint8 *
 static Uint8 *
-AndroidAUD_GetDeviceBuf(_THIS)
+ANDROIDAUDIO_GetDeviceBuf(_THIS)
 {
 {
     return Android_JNI_GetAudioBuffer();
     return Android_JNI_GetAudioBuffer();
 }
 }
 
 
+static int
+ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    return Android_JNI_CaptureAudioBuffer(buffer, buflen);
+}
+
+static void
+ANDROIDAUDIO_FlushCapture(_THIS)
+{
+    Android_JNI_FlushCapturedAudio();
+}
+
 static void
 static void
-AndroidAUD_CloseDevice(_THIS)
+ANDROIDAUDIO_CloseDevice(_THIS)
 {
 {
     /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
     /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
        so it's safe to terminate the Java side buffer and AudioTrack
        so it's safe to terminate the Java side buffer and AudioTrack
      */
      */
-    Android_JNI_CloseAudioDevice();
-
-    if (audioDevice == this) {
-        if (audioDevice->hidden != NULL) {
-            SDL_free(this->hidden);
-            this->hidden = NULL;
-        }
+    Android_JNI_CloseAudioDevice(this->iscapture);
+    if (this->iscapture) {
+        SDL_assert(captureDevice == this);
+        captureDevice = NULL;
+    } else {
+        SDL_assert(audioDevice == this);
         audioDevice = NULL;
         audioDevice = NULL;
     }
     }
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
-AndroidAUD_Init(SDL_AudioDriverImpl * impl)
+ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = AndroidAUD_OpenDevice;
-    impl->PlayDevice = AndroidAUD_PlayDevice;
-    impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
-    impl->CloseDevice = AndroidAUD_CloseDevice;
+    impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
+    impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
+    impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
+    impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
+    impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
+    impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
 
 
     /* and the capabilities */
     /* and the capabilities */
-    impl->HasCaptureSupport = 0; /* TODO */
+    impl->HasCaptureSupport = SDL_TRUE;
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
-    impl->OnlyHasDefaultInputDevice = 1;
+    impl->OnlyHasDefaultCaptureDevice = 1;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 
-AudioBootStrap ANDROIDAUD_bootstrap = {
-    "android", "SDL Android audio driver", AndroidAUD_Init, 0
+AudioBootStrap ANDROIDAUDIO_bootstrap = {
+    "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
 };
 };
 
 
 /* Pause (block) all non already paused audio devices by taking their mixer lock */
 /* Pause (block) all non already paused audio devices by taking their mixer lock */
-void AndroidAUD_PauseDevices(void)
+void ANDROIDAUDIO_PauseDevices(void)
 {
 {
     /* TODO: Handle multiple devices? */
     /* TODO: Handle multiple devices? */
     struct SDL_PrivateAudioData *private;
     struct SDL_PrivateAudioData *private;
     if(audioDevice != NULL && audioDevice->hidden != NULL) {
     if(audioDevice != NULL && audioDevice->hidden != NULL) {
         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
-        if (audioDevice->paused) {
+        if (SDL_AtomicGet(&audioDevice->paused)) {
             /* The device is already paused, leave it alone */
             /* The device is already paused, leave it alone */
             private->resume = SDL_FALSE;
             private->resume = SDL_FALSE;
         }
         }
         else {
         else {
             SDL_LockMutex(audioDevice->mixer_lock);
             SDL_LockMutex(audioDevice->mixer_lock);
-            audioDevice->paused = SDL_TRUE;
+            SDL_AtomicSet(&audioDevice->paused, 1);
+            private->resume = SDL_TRUE;
+        }
+    }
+
+    if(captureDevice != NULL && captureDevice->hidden != NULL) {
+        private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
+        if (SDL_AtomicGet(&captureDevice->paused)) {
+            /* The device is already paused, leave it alone */
+            private->resume = SDL_FALSE;
+        }
+        else {
+            SDL_LockMutex(captureDevice->mixer_lock);
+            SDL_AtomicSet(&captureDevice->paused, 1);
             private->resume = SDL_TRUE;
             private->resume = SDL_TRUE;
         }
         }
     }
     }
 }
 }
 
 
 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
 /* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
-void AndroidAUD_ResumeDevices(void)
+void ANDROIDAUDIO_ResumeDevices(void)
 {
 {
     /* TODO: Handle multiple devices? */
     /* TODO: Handle multiple devices? */
     struct SDL_PrivateAudioData *private;
     struct SDL_PrivateAudioData *private;
     if(audioDevice != NULL && audioDevice->hidden != NULL) {
     if(audioDevice != NULL && audioDevice->hidden != NULL) {
         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
         private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
         if (private->resume) {
         if (private->resume) {
-            audioDevice->paused = SDL_FALSE;
+            SDL_AtomicSet(&audioDevice->paused, 0);
             private->resume = SDL_FALSE;
             private->resume = SDL_FALSE;
             SDL_UnlockMutex(audioDevice->mixer_lock);
             SDL_UnlockMutex(audioDevice->mixer_lock);
         }
         }
     }
     }
+
+    if(captureDevice != NULL && captureDevice->hidden != NULL) {
+        private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
+        if (private->resume) {
+            SDL_AtomicSet(&captureDevice->paused, 0);
+            private->resume = SDL_FALSE;
+            SDL_UnlockMutex(captureDevice->mixer_lock);
+        }
+    }
 }
 }
 
 
 
 

+ 0 - 2
Engine/lib/sdl/src/audio/android/SDL_androidaudio.h

@@ -34,8 +34,6 @@ struct SDL_PrivateAudioData
     int resume;
     int resume;
 };
 };
 
 
-static void AndroidAUD_CloseDevice(_THIS);
-
 #endif /* _SDL_androidaudio_h */
 #endif /* _SDL_androidaudio_h */
 
 
 /* vi: set ts=4 sw=4 expandtab: */
 /* vi: set ts=4 sw=4 expandtab: */

+ 7 - 26
Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c

@@ -32,7 +32,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_artsaudio.h"
 #include "SDL_artsaudio.h"
 
 
@@ -186,13 +185,6 @@ ARTS_PlayDevice(_THIS)
 #endif
 #endif
 }
 }
 
 
-static void
-ARTS_WaitDone(_THIS)
-{
-    /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
-}
-
-
 static Uint8 *
 static Uint8 *
 ARTS_GetDeviceBuf(_THIS)
 ARTS_GetDeviceBuf(_THIS)
 {
 {
@@ -203,17 +195,12 @@ ARTS_GetDeviceBuf(_THIS)
 static void
 static void
 ARTS_CloseDevice(_THIS)
 ARTS_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->stream) {
-            SDL_NAME(arts_close_stream) (this->hidden->stream);
-            this->hidden->stream = 0;
-        }
-        SDL_NAME(arts_free) ();
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->stream) {
+        SDL_NAME(arts_close_stream) (this->hidden->stream);
     }
     }
+    SDL_NAME(arts_free) ();
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -241,7 +228,7 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Try for a closest match on audio format */
     /* Try for a closest match on audio format */
     for (test_format = SDL_FirstAudioFormat(this->spec.format);
     for (test_format = SDL_FirstAudioFormat(this->spec.format);
@@ -267,19 +254,16 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         }
         }
     }
     }
     if (format == 0) {
     if (format == 0) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
 
 
     if ((rc = SDL_NAME(arts_init) ()) != 0) {
     if ((rc = SDL_NAME(arts_init) ()) != 0) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Unable to initialize ARTS: %s",
         return SDL_SetError("Unable to initialize ARTS: %s",
                             SDL_NAME(arts_error_text) (rc));
                             SDL_NAME(arts_error_text) (rc));
     }
     }
 
 
     if (!ARTS_Suspend()) {
     if (!ARTS_Suspend()) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("ARTS can not open audio device");
         return SDL_SetError("ARTS can not open audio device");
     }
     }
 
 
@@ -297,7 +281,6 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Determine the power of two of the fragment size */
     /* Determine the power of two of the fragment size */
     for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
     for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
     if ((0x01 << frag_spec) != this->spec.size) {
     if ((0x01 << frag_spec) != this->spec.size) {
-        ARTS_CloseDevice(this);
         return SDL_SetError("Fragment size must be a power of two");
         return SDL_SetError("Fragment size must be a power of two");
     }
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
@@ -316,9 +299,8 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        ARTS_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -367,7 +349,6 @@ ARTS_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice = ARTS_WaitDevice;
     impl->WaitDevice = ARTS_WaitDevice;
     impl->GetDeviceBuf = ARTS_GetDeviceBuf;
     impl->GetDeviceBuf = ARTS_GetDeviceBuf;
     impl->CloseDevice = ARTS_CloseDevice;
     impl->CloseDevice = ARTS_CloseDevice;
-    impl->WaitDone = ARTS_WaitDone;
     impl->Deinitialize = ARTS_Deinitialize;
     impl->Deinitialize = ARTS_Deinitialize;
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
 
 

+ 110 - 55
Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c

@@ -38,7 +38,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 #include "SDL_bsdaudio.h"
 #include "SDL_bsdaudio.h"
@@ -63,13 +62,17 @@ BSDAUDIO_Status(_THIS)
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
     /* *INDENT-OFF* */
     /* *INDENT-OFF* */
     audio_info_t info;
     audio_info_t info;
+    const audio_prinfo *prinfo;
 
 
     if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
     if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
         fprintf(stderr, "AUDIO_GETINFO failed.\n");
         fprintf(stderr, "AUDIO_GETINFO failed.\n");
         return;
         return;
     }
     }
+
+    prinfo = this->iscapture ? &info.play : &info.record;
+
     fprintf(stderr, "\n"
     fprintf(stderr, "\n"
-            "[play/record info]\n"
+            "[%s info]\n"
             "buffer size	:   %d bytes\n"
             "buffer size	:   %d bytes\n"
             "sample rate	:   %i Hz\n"
             "sample rate	:   %i Hz\n"
             "channels	:   %i\n"
             "channels	:   %i\n"
@@ -83,18 +86,19 @@ BSDAUDIO_Status(_THIS)
             "waiting		:   %s\n"
             "waiting		:   %s\n"
             "active		:   %s\n"
             "active		:   %s\n"
             "",
             "",
-            info.play.buffer_size,
-            info.play.sample_rate,
-            info.play.channels,
-            info.play.precision,
-            info.play.encoding,
-            info.play.seek,
-            info.play.samples,
-            info.play.eof,
-            info.play.pause ? "yes" : "no",
-            info.play.error ? "yes" : "no",
-            info.play.waiting ? "yes" : "no",
-            info.play.active ? "yes" : "no");
+            this->iscapture ? "record" : "play",
+            prinfo->buffer_size,
+            prinfo->sample_rate,
+            prinfo->channels,
+            prinfo->precision,
+            prinfo->encoding,
+            prinfo->seek,
+            prinfo->samples,
+            prinfo->eof,
+            prinfo->pause ? "yes" : "no",
+            prinfo->error ? "yes" : "no",
+            prinfo->waiting ? "yes" : "no",
+            prinfo->active ? "yes" : "no");
 
 
     fprintf(stderr, "\n"
     fprintf(stderr, "\n"
             "[audio info]\n"
             "[audio info]\n"
@@ -182,11 +186,15 @@ BSDAUDIO_PlayDevice(_THIS)
             break;
             break;
         }
         }
 
 
-        if (p < written
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Wrote %d bytes of audio data\n", written);
+#endif
+
+        if (p < this->hidden->mixlen
             || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
             || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
             SDL_Delay(1);       /* Let a little CPU time go by */
             SDL_Delay(1);       /* Let a little CPU time go by */
         }
         }
-    } while (p < written);
+    } while (p < this->hidden->mixlen);
 
 
     /* If timer synchronization is enabled, set the next write frame */
     /* If timer synchronization is enabled, set the next write frame */
     if (this->hidden->frame_ticks) {
     if (this->hidden->frame_ticks) {
@@ -197,9 +205,6 @@ BSDAUDIO_PlayDevice(_THIS)
     if (written < 0) {
     if (written < 0) {
         SDL_OpenedAudioDeviceDisconnected(this);
         SDL_OpenedAudioDeviceDisconnected(this);
     }
     }
-#ifdef DEBUG_AUDIO
-    fprintf(stderr, "Wrote %d bytes of audio data\n", written);
-#endif
 }
 }
 
 
 static Uint8 *
 static Uint8 *
@@ -208,27 +213,74 @@ BSDAUDIO_GetDeviceBuf(_THIS)
     return (this->hidden->mixbuf);
     return (this->hidden->mixbuf);
 }
 }
 
 
+
+static int
+BSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
+{
+    Uint8 *buffer = (Uint8 *) _buffer;
+    int br, p = 0;
+
+    /* Write the audio data, checking for EAGAIN on broken audio drivers */
+    do {
+        br = read(this->hidden->audio_fd, buffer + p, buflen - p);
+        if (br > 0)
+            p += br;
+        if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
+            /* Non recoverable error has occurred. It should be reported!!! */
+            perror("audio");
+            return p ? p : -1;
+        }
+
+#ifdef DEBUG_AUDIO
+        fprintf(stderr, "Captured %d bytes of audio data\n", br);
+#endif
+
+        if (p < buflen
+            || ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
+            SDL_Delay(1);       /* Let a little CPU time go by */
+        }
+    } while (p < buflen);
+}
+
 static void
 static void
-BSDAUDIO_CloseDevice(_THIS)
+BSDAUDIO_FlushCapture(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
+    audio_info_t info;
+    size_t remain;
+    Uint8 buf[512];
+
+    if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
+        return;  /* oh well. */
+    }
+
+    remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
+    while (remain > 0) {
+        const size_t len = SDL_min(sizeof (buf), remain);
+        const int br = read(this->hidden->audio_fd, buf, len);
+        if (br <= 0) {
+            return;  /* oh well. */
         }
         }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+        remain -= br;
     }
     }
 }
 }
 
 
+static void
+BSDAUDIO_CloseDevice(_THIS)
+{
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
+    }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
+}
+
 static int
 static int
 BSDAUDIO_OpenDevice(_THIS, void *handle, 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);
+    const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
     SDL_AudioFormat format = 0;
     SDL_AudioFormat format = 0;
     audio_info_t info;
     audio_info_t info;
+    audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
 
 
     /* We don't care what the devname is...we'll try to open anything. */
     /* We don't care what the devname is...we'll try to open anything. */
     /*  ...but default to first name in the list... */
     /*  ...but default to first name in the list... */
@@ -245,7 +297,7 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
     this->hidden->audio_fd = open(devname, flags, 0);
     this->hidden->audio_fd = open(devname, flags, 0);
@@ -259,9 +311,8 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Set to play mode */
     /* Set to play mode */
-    info.mode = AUMODE_PLAY;
+    info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
     if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
     if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
-        BSDAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't put device into play mode");
         return SDL_SetError("Couldn't put device into play mode");
     }
     }
 
 
@@ -270,28 +321,28 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
          format; format = SDL_NextAudioFormat()) {
          format; format = SDL_NextAudioFormat()) {
         switch (format) {
         switch (format) {
         case AUDIO_U8:
         case AUDIO_U8:
-            info.play.encoding = AUDIO_ENCODING_ULINEAR;
-            info.play.precision = 8;
+            prinfo->encoding = AUDIO_ENCODING_ULINEAR;
+            prinfo->precision = 8;
             break;
             break;
         case AUDIO_S8:
         case AUDIO_S8:
-            info.play.encoding = AUDIO_ENCODING_SLINEAR;
-            info.play.precision = 8;
+            prinfo->encoding = AUDIO_ENCODING_SLINEAR;
+            prinfo->precision = 8;
             break;
             break;
         case AUDIO_S16LSB:
         case AUDIO_S16LSB:
-            info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
-            info.play.precision = 16;
+            prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
+            prinfo->precision = 16;
             break;
             break;
         case AUDIO_S16MSB:
         case AUDIO_S16MSB:
-            info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
-            info.play.precision = 16;
+            prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
+            prinfo->precision = 16;
             break;
             break;
         case AUDIO_U16LSB:
         case AUDIO_U16LSB:
-            info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
-            info.play.precision = 16;
+            prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
+            prinfo->precision = 16;
             break;
             break;
         case AUDIO_U16MSB:
         case AUDIO_U16MSB:
-            info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
-            info.play.precision = 16;
+            prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
+            prinfo->precision = 16;
             break;
             break;
         default:
         default:
             continue;
             continue;
@@ -303,33 +354,34 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!format) {
     if (!format) {
-        BSDAUDIO_CloseDevice(this);
         return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
         return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
     }
     }
 
 
     this->spec.format = format;
     this->spec.format = format;
 
 
     AUDIO_INITINFO(&info);
     AUDIO_INITINFO(&info);
-    info.play.channels = this->spec.channels;
+    prinfo->channels = this->spec.channels;
     if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
     if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
         this->spec.channels = 1;
         this->spec.channels = 1;
     }
     }
     AUDIO_INITINFO(&info);
     AUDIO_INITINFO(&info);
-    info.play.sample_rate = this->spec.freq;
+    prinfo->sample_rate = this->spec.freq;
     info.blocksize = this->spec.size;
     info.blocksize = this->spec.size;
     info.hiwat = 5;
     info.hiwat = 5;
     info.lowat = 3;
     info.lowat = 3;
     (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
     (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
     (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
     (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
-    this->spec.freq = info.play.sample_rate;
-    /* Allocate mixing buffer */
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        BSDAUDIO_CloseDevice(this);
-        return SDL_OutOfMemory();
+    this->spec.freq = prinfo->sample_rate;
+
+    if (!iscapture) {
+        /* Allocate mixing buffer */
+        this->hidden->mixlen = this->spec.size;
+        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+        if (this->hidden->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     }
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
 
     BSDAUDIO_Status(this);
     BSDAUDIO_Status(this);
 
 
@@ -347,7 +399,10 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice = BSDAUDIO_WaitDevice;
     impl->WaitDevice = BSDAUDIO_WaitDevice;
     impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
     impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
     impl->CloseDevice = BSDAUDIO_CloseDevice;
     impl->CloseDevice = BSDAUDIO_CloseDevice;
+    impl->CaptureFromDevice = BSDAUDIO_CaptureFromDevice;
+    impl->FlushCapture = BSDAUDIO_FlushCapture;
 
 
+    impl->HasCaptureSupport = SDL_TRUE;
     impl->AllowsArbitraryDeviceNames = 1;
     impl->AllowsArbitraryDeviceNames = 1;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */

+ 13 - 3
Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h

@@ -33,9 +33,11 @@
 #include <CoreAudio/CoreAudio.h>
 #include <CoreAudio/CoreAudio.h>
 #include <CoreServices/CoreServices.h>
 #include <CoreServices/CoreServices.h>
 #else
 #else
-#include <AudioToolbox/AudioToolbox.h>
+#import <AVFoundation/AVFoundation.h>
+#import <UIKit/UIApplication.h>
 #endif
 #endif
 
 
+#include <AudioToolbox/AudioToolbox.h>
 #include <AudioUnit/AudioUnit.h>
 #include <AudioUnit/AudioUnit.h>
 
 
 /* Hidden "this" pointer for the audio functions */
 /* Hidden "this" pointer for the audio functions */
@@ -43,13 +45,21 @@
 
 
 struct SDL_PrivateAudioData
 struct SDL_PrivateAudioData
 {
 {
-    AudioUnit audioUnit;
-    int audioUnitOpened;
+    SDL_Thread *thread;
+    AudioQueueRef audioQueue;
+    AudioQueueBufferRef audioBuffer[2];
     void *buffer;
     void *buffer;
     UInt32 bufferOffset;
     UInt32 bufferOffset;
     UInt32 bufferSize;
     UInt32 bufferSize;
+    AudioStreamBasicDescription strdesc;
+    SDL_sem *ready_semaphore;
+    char *thread_error;
+    SDL_atomic_t shutdown;
 #if MACOSX_COREAUDIO
 #if MACOSX_COREAUDIO
     AudioDeviceID deviceID;
     AudioDeviceID deviceID;
+#else
+    SDL_bool interrupted;
+    CFTypeRef interruption_listener;
 #endif
 #endif
 };
 };
 
 

+ 348 - 197
Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.c → Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.m

@@ -22,19 +22,19 @@
 
 
 #if SDL_AUDIO_DRIVER_COREAUDIO
 #if SDL_AUDIO_DRIVER_COREAUDIO
 
 
+/* !!! FIXME: clean out some of the macro salsa in here. */
+
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_sysaudio.h"
 #include "../SDL_sysaudio.h"
 #include "SDL_coreaudio.h"
 #include "SDL_coreaudio.h"
 #include "SDL_assert.h"
 #include "SDL_assert.h"
+#include "../../thread/SDL_systhread.h"
 
 
 #define DEBUG_COREAUDIO 0
 #define DEBUG_COREAUDIO 0
 
 
-static void COREAUDIO_CloseDevice(_THIS);
-
 #define CHECK_RESULT(msg) \
 #define CHECK_RESULT(msg) \
     if (result != noErr) { \
     if (result != noErr) { \
-        COREAUDIO_CloseDevice(this); \
         SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
         SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
         return 0; \
         return 0; \
     }
     }
@@ -185,7 +185,7 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
 #if DEBUG_COREAUDIO
 #if DEBUG_COREAUDIO
             printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
             printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
                    ((iscapture) ? "capture" : "output"),
                    ((iscapture) ? "capture" : "output"),
-                   (int) *devCount, ptr, (int) dev);
+                   (int) i, ptr, (int) dev);
 #endif
 #endif
             addfn(ptr, iscapture, dev, addfndata);
             addfn(ptr, iscapture, dev, addfndata);
         }
         }
@@ -268,42 +268,147 @@ device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectP
 }
 }
 #endif
 #endif
 
 
-/* The CoreAudio callback */
-static OSStatus
-outputCallback(void *inRefCon,
-               AudioUnitRenderActionFlags * ioActionFlags,
-               const AudioTimeStamp * inTimeStamp,
-               UInt32 inBusNumber, UInt32 inNumberFrames,
-               AudioBufferList * ioData)
+
+static int open_playback_devices = 0;
+static int open_capture_devices = 0;
+
+#if !MACOSX_COREAUDIO
+
+static void interruption_begin(_THIS)
+{
+    if (this != NULL && this->hidden->audioQueue != NULL) {
+        this->hidden->interrupted = SDL_TRUE;
+        AudioQueuePause(this->hidden->audioQueue);
+    }
+}
+
+static void interruption_end(_THIS)
 {
 {
-    SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
-    AudioBuffer *abuf;
-    UInt32 remaining, len;
-    void *ptr;
-    UInt32 i;
-
-    /* Only do anything if audio is enabled and not paused */
-    if (!this->enabled || this->paused) {
-        for (i = 0; i < ioData->mNumberBuffers; i++) {
-            abuf = &ioData->mBuffers[i];
-            SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize);
+    if (this != NULL && this->hidden != NULL && this->hidden->audioQueue != NULL
+    && this->hidden->interrupted) {
+        this->hidden->interrupted = SDL_FALSE;
+        AudioQueueStart(this->hidden->audioQueue, NULL);
+    }
+}
+
+@interface SDLInterruptionListener : NSObject
+
+@property (nonatomic, assign) SDL_AudioDevice *device;
+
+@end
+
+@implementation SDLInterruptionListener
+
+- (void)audioSessionInterruption:(NSNotification *)note
+{
+    @synchronized (self) {
+        NSNumber *type = note.userInfo[AVAudioSessionInterruptionTypeKey];
+        if (type.unsignedIntegerValue == AVAudioSessionInterruptionTypeBegan) {
+            interruption_begin(self.device);
+        } else {
+            interruption_end(self.device);
         }
         }
-        return 0;
     }
     }
+}
+
+- (void)applicationBecameActive:(NSNotification *)note
+{
+    @synchronized (self) {
+        interruption_end(self.device);
+    }
+}
+
+@end
+
+static BOOL update_audio_session(_THIS, SDL_bool open)
+{
+    @autoreleasepool {
+        AVAudioSession *session = [AVAudioSession sharedInstance];
+        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+        NSString *category;
+        NSError *err = nil;
+
+        if (open_playback_devices && open_capture_devices) {
+            category = AVAudioSessionCategoryPlayAndRecord;
+        } else if (open_capture_devices) {
+            category = AVAudioSessionCategoryRecord;
+        } else {
+            /* Set category to ambient so that other music continues playing.
+             You can change this at runtime in your own code if you need different
+             behavior. If this is common, we can add an SDL hint for this. */
+            category = AVAudioSessionCategoryAmbient;
+        }
 
 
-    /* No SDL conversion should be needed here, ever, since we accept
-       any input format in OpenAudio, and leave the conversion to CoreAudio.
-     */
-    /*
-       SDL_assert(!this->convert.needed);
-       SDL_assert(this->spec.channels == ioData->mNumberChannels);
-     */
+        if (![session setCategory:category error:&err]) {
+            NSString *desc = err.description;
+            SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
+            return NO;
+        }
+
+        if (open_playback_devices + open_capture_devices == 1) {
+            if (![session setActive:YES error:&err]) {
+                NSString *desc = err.description;
+                SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
+                return NO;
+            }
+        } else if (!open_playback_devices && !open_capture_devices) {
+            [session setActive:NO error:nil];
+        }
+
+        if (open) {
+            SDLInterruptionListener *listener = [SDLInterruptionListener new];
+            listener.device = this;
+
+            [center addObserver:listener
+                       selector:@selector(audioSessionInterruption:)
+                           name:AVAudioSessionInterruptionNotification
+                         object:session];
+
+            /* An interruption end notification is not guaranteed to be sent if
+             we were previously interrupted... resuming if needed when the app
+             becomes active seems to be the way to go. */
+            [center addObserver:listener
+                       selector:@selector(applicationBecameActive:)
+                           name:UIApplicationDidBecomeActiveNotification
+                         object:session];
+
+            [center addObserver:listener
+                       selector:@selector(applicationBecameActive:)
+                           name:UIApplicationWillEnterForegroundNotification
+                         object:session];
+
+            this->hidden->interruption_listener = CFBridgingRetain(listener);
+        } else {
+            if (this->hidden->interruption_listener != NULL) {
+                SDLInterruptionListener *listener = nil;
+                listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
+                @synchronized (listener) {
+                    listener.device = NULL;
+                }
+                [center removeObserver:listener];
+            }
+        }
+    }
+
+    return YES;
+}
+#endif
+
+
+/* The AudioQueue callback */
+static void
+outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
+{
+    SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
+    if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
+        /* Supply silence if audio is enabled and not paused */
+        SDL_memset(inBuffer->mAudioData, this->spec.silence, inBuffer->mAudioDataBytesCapacity);
+    } else {
+        UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
+        Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
 
 
-    for (i = 0; i < ioData->mNumberBuffers; i++) {
-        abuf = &ioData->mBuffers[i];
-        remaining = abuf->mDataByteSize;
-        ptr = abuf->mData;
         while (remaining > 0) {
         while (remaining > 0) {
+            UInt32 len;
             if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
             if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
                 /* Generate the data */
                 /* Generate the data */
                 SDL_LockMutex(this->mixer_lock);
                 SDL_LockMutex(this->mixer_lock);
@@ -314,29 +419,56 @@ outputCallback(void *inRefCon,
             }
             }
 
 
             len = this->hidden->bufferSize - this->hidden->bufferOffset;
             len = this->hidden->bufferSize - this->hidden->bufferOffset;
-            if (len > remaining)
+            if (len > remaining) {
                 len = remaining;
                 len = remaining;
+            }
             SDL_memcpy(ptr, (char *)this->hidden->buffer +
             SDL_memcpy(ptr, (char *)this->hidden->buffer +
                        this->hidden->bufferOffset, len);
                        this->hidden->bufferOffset, len);
-            ptr = (char *)ptr + len;
+            ptr = ptr + len;
             remaining -= len;
             remaining -= len;
             this->hidden->bufferOffset += len;
             this->hidden->bufferOffset += len;
         }
         }
     }
     }
 
 
-    return 0;
+    if (!SDL_AtomicGet(&this->hidden->shutdown)) {
+        AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
+    }
+
+    inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
 }
 }
 
 
-static OSStatus
-inputCallback(void *inRefCon,
-              AudioUnitRenderActionFlags * ioActionFlags,
-              const AudioTimeStamp * inTimeStamp,
-              UInt32 inBusNumber, UInt32 inNumberFrames,
-              AudioBufferList * ioData)
+static void
+inputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
+              const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions,
+              const AudioStreamPacketDescription *inPacketDescs )
 {
 {
-    /* err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer); */
-    /* !!! FIXME: write me! */
-    return noErr;
+    SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
+    if (SDL_AtomicGet(&this->enabled) && !SDL_AtomicGet(&this->paused)) {  /* ignore unless we're active. */
+        const Uint8 *ptr = (const Uint8 *) inBuffer->mAudioData;
+        UInt32 remaining = inBuffer->mAudioDataByteSize;
+        while (remaining > 0) {
+            UInt32 len = this->hidden->bufferSize - this->hidden->bufferOffset;
+            if (len > remaining) {
+                len = remaining;
+            }
+
+            SDL_memcpy((char *)this->hidden->buffer + this->hidden->bufferOffset, ptr, len);
+            ptr += len;
+            remaining -= len;
+            this->hidden->bufferOffset += len;
+
+            if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
+                SDL_LockMutex(this->mixer_lock);
+                (*this->spec.callback)(this->spec.userdata, this->hidden->buffer, this->hidden->bufferSize);
+                SDL_UnlockMutex(this->mixer_lock);
+                this->hidden->bufferOffset = 0;
+            }
+        }
+    }
+
+    if (!SDL_AtomicGet(&this->hidden->shutdown)) {
+        AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
+    }
 }
 }
 
 
 
 
@@ -357,7 +489,7 @@ device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectProperty
     UInt32 size = sizeof (isAlive);
     UInt32 size = sizeof (isAlive);
     OSStatus error;
     OSStatus error;
 
 
-    if (!this->enabled) {
+    if (!SDL_AtomicGet(&this->enabled)) {
         return 0;  /* already known to be dead. */
         return 0;  /* already known to be dead. */
     }
     }
 
 
@@ -381,43 +513,46 @@ device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectProperty
 static void
 static void
 COREAUDIO_CloseDevice(_THIS)
 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;
-            const int iscapture = this->iscapture;
-            const AudioUnitElement bus =
-                ((iscapture) ? input_bus : output_bus);
-            const AudioUnitScope scope =
-                ((iscapture) ? kAudioUnitScope_Output :
-                 kAudioUnitScope_Input);
-
-            /* stop processing the audio unit */
-            AudioOutputUnitStop(this->hidden->audioUnit);
-
-            /* Remove the input callback */
-            SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
-            AudioUnitSetProperty(this->hidden->audioUnit,
-                                 kAudioUnitProperty_SetRenderCallback,
-                                 scope, bus, &callback, sizeof(callback));
-
-            #if MACOSX_COREAUDIO
-            CloseComponent(this->hidden->audioUnit);
-            #else
-            AudioComponentInstanceDispose(this->hidden->audioUnit);
-            #endif
-
-            this->hidden->audioUnitOpened = 0;
+    const SDL_bool iscapture = this->iscapture;
+    int i;
+
+/* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
+/* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
+#if MACOSX_COREAUDIO
+    /* Fire a callback if the device stops being "alive" (disconnected, etc). */
+    AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
+#endif
+
+#if !MACOSX_COREAUDIO
+    update_audio_session(this, SDL_FALSE);
+#endif
+
+    if (this->hidden->thread) {
+        SDL_AtomicSet(&this->hidden->shutdown, 1);
+        SDL_WaitThread(this->hidden->thread, NULL);
+    }
+
+    if (this->hidden->audioQueue) {
+        for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+            if (this->hidden->audioBuffer[i]) {
+                AudioQueueFreeBuffer(this->hidden->audioQueue, this->hidden->audioBuffer[i]);
+            }
         }
         }
-        SDL_free(this->hidden->buffer);
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+        AudioQueueDispose(this->hidden->audioQueue, 1);
+    }
+
+    if (this->hidden->ready_semaphore) {
+        SDL_DestroySemaphore(this->hidden->ready_semaphore);
+    }
+
+    SDL_free(this->hidden->thread_error);
+    SDL_free(this->hidden->buffer);
+    SDL_free(this->hidden);
+
+    if (iscapture) {
+        open_capture_devices--;
+    } else {
+        open_playback_devices--;
     }
     }
 }
 }
 
 
@@ -477,116 +612,105 @@ prepare_device(_THIS, void *handle, int iscapture)
 #endif
 #endif
 
 
 static int
 static int
-prepare_audiounit(_THIS, void *handle, int iscapture,
-                  const AudioStreamBasicDescription * strdesc)
+prepare_audioqueue(_THIS)
 {
 {
-    OSStatus result = noErr;
-    AURenderCallbackStruct callback;
-#if MACOSX_COREAUDIO
-    ComponentDescription desc;
-    Component comp = NULL;
-#else
-    AudioComponentDescription desc;
-    AudioComponent comp = NULL;
-#endif
-    const AudioUnitElement output_bus = 0;
-    const AudioUnitElement input_bus = 1;
-    const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
-    const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
-                                  kAudioUnitScope_Input);
-
-#if MACOSX_COREAUDIO
-    if (!prepare_device(this, handle, iscapture)) {
-        return 0;
-    }
-#endif
+    const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
+    const int iscapture = this->iscapture;
+    OSStatus result;
+    int i;
 
 
-    SDL_zero(desc);
-    desc.componentType = kAudioUnitType_Output;
-    desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+    SDL_assert(CFRunLoopGetCurrent() != NULL);
 
 
-#if MACOSX_COREAUDIO
-    desc.componentSubType = kAudioUnitSubType_DefaultOutput;
-    comp = FindNextComponent(NULL, &desc);
-#else
-    desc.componentSubType = kAudioUnitSubType_RemoteIO;
-    comp = AudioComponentFindNext(NULL, &desc);
-#endif
-
-    if (comp == NULL) {
-        SDL_SetError("Couldn't find requested CoreAudio component");
-        return 0;
+    if (iscapture) {
+        result = AudioQueueNewInput(strdesc, inputCallback, this, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &this->hidden->audioQueue);
+        CHECK_RESULT("AudioQueueNewInput");
+    } else {
+        result = AudioQueueNewOutput(strdesc, outputCallback, this, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &this->hidden->audioQueue);
+        CHECK_RESULT("AudioQueueNewOutput");
     }
     }
 
 
-    /* Open & initialize the audio unit */
-#if MACOSX_COREAUDIO
-    result = OpenAComponent(comp, &this->hidden->audioUnit);
-    CHECK_RESULT("OpenAComponent");
-#else
-    /*
-       AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6
-       We can't use OpenAComponent on iPhone because it is not present
-     */
-    result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit);
-    CHECK_RESULT("AudioComponentInstanceNew");
-#endif
-
-    this->hidden->audioUnitOpened = 1;
-
 #if MACOSX_COREAUDIO
 #if MACOSX_COREAUDIO
-    result = AudioUnitSetProperty(this->hidden->audioUnit,
-                                  kAudioOutputUnitProperty_CurrentDevice,
-                                  kAudioUnitScope_Global, 0,
-                                  &this->hidden->deviceID,
-                                  sizeof(AudioDeviceID));
-    CHECK_RESULT
-        ("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)");
+{
+    const AudioObjectPropertyAddress prop = {
+        kAudioDevicePropertyDeviceUID,
+        iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
+        kAudioObjectPropertyElementMaster
+    };
+    CFStringRef devuid;
+    UInt32 devuidsize = sizeof (devuid);
+    result = AudioObjectGetPropertyData(this->hidden->deviceID, &prop, 0, NULL, &devuidsize, &devuid);
+    CHECK_RESULT("AudioObjectGetPropertyData (kAudioDevicePropertyDeviceUID)");
+    result = AudioQueueSetProperty(this->hidden->audioQueue, kAudioQueueProperty_CurrentDevice, &devuid, devuidsize);
+    CHECK_RESULT("AudioQueueSetProperty (kAudioQueueProperty_CurrentDevice)");
+
+    /* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
+    /* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
+    /* Fire a callback if the device stops being "alive" (disconnected, etc). */
+    AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
+}
 #endif
 #endif
 
 
-    /* Set the data format of the audio unit. */
-    result = AudioUnitSetProperty(this->hidden->audioUnit,
-                                  kAudioUnitProperty_StreamFormat,
-                                  scope, bus, strdesc, sizeof(*strdesc));
-    CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
-
-    /* Set the audio callback */
-    SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
-    callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
-    callback.inputProcRefCon = this;
-    result = AudioUnitSetProperty(this->hidden->audioUnit,
-                                  kAudioUnitProperty_SetRenderCallback,
-                                  scope, bus, &callback, sizeof(callback));
-    CHECK_RESULT
-        ("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
-
     /* Calculate the final parameters for this audio specification */
     /* Calculate the final parameters for this audio specification */
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Allocate a sample buffer */
     /* Allocate a sample buffer */
-    this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
-    this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
+    this->hidden->bufferSize = this->spec.size;
+    this->hidden->bufferOffset = iscapture ? 0 : this->hidden->bufferSize;
 
 
-    result = AudioUnitInitialize(this->hidden->audioUnit);
-    CHECK_RESULT("AudioUnitInitialize");
+    this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
+    if (this->hidden->buffer == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
 
 
-    /* Finally, start processing of the audio unit */
-    result = AudioOutputUnitStart(this->hidden->audioUnit);
-    CHECK_RESULT("AudioOutputUnitStart");
+    for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+        result = AudioQueueAllocateBuffer(this->hidden->audioQueue, this->spec.size, &this->hidden->audioBuffer[i]);
+        CHECK_RESULT("AudioQueueAllocateBuffer");
+        SDL_memset(this->hidden->audioBuffer[i]->mAudioData, this->spec.silence, this->hidden->audioBuffer[i]->mAudioDataBytesCapacity);
+        this->hidden->audioBuffer[i]->mAudioDataByteSize = this->hidden->audioBuffer[i]->mAudioDataBytesCapacity;
+        result = AudioQueueEnqueueBuffer(this->hidden->audioQueue, this->hidden->audioBuffer[i], 0, NULL);
+        CHECK_RESULT("AudioQueueEnqueueBuffer");
+    }
 
 
-#if MACOSX_COREAUDIO
-    /* Fire a callback if the device stops being "alive" (disconnected, etc). */
-    AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
-#endif
+    result = AudioQueueStart(this->hidden->audioQueue, NULL);
+    CHECK_RESULT("AudioQueueStart");
 
 
     /* We're running! */
     /* We're running! */
     return 1;
     return 1;
 }
 }
 
 
+static int
+audioqueue_thread(void *arg)
+{
+    SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
+    const int rc = prepare_audioqueue(this);
+    if (!rc) {
+        this->hidden->thread_error = SDL_strdup(SDL_GetError());
+        SDL_SemPost(this->hidden->ready_semaphore);
+        return 0;
+    }
+
+    /* init was successful, alert parent thread and start running... */
+    SDL_SemPost(this->hidden->ready_semaphore);
+    while (!SDL_AtomicGet(&this->hidden->shutdown)) {
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
+    }
+
+    if (this->iscapture) {  /* just stop immediately for capture devices. */
+        AudioQueueStop(this->hidden->audioQueue, 1);
+    } else {  /* Drain off any pending playback. */
+        AudioQueueStop(this->hidden->audioQueue, 0);
+        const CFTimeInterval secs = (((this->spec.size / (SDL_AUDIO_BITSIZE(this->spec.format) / 8)) / this->spec.channels) / ((CFTimeInterval) this->spec.freq)) * 2.0;
+        CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0);
+    }
+
+    return 0;
+}
 
 
 static int
 static int
 COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
-    AudioStreamBasicDescription strdesc;
+    AudioStreamBasicDescription *strdesc;
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     int valid_datatype = 0;
     int valid_datatype = 0;
 
 
@@ -596,15 +720,29 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
+
+    strdesc = &this->hidden->strdesc;
+
+    if (iscapture) {
+        open_capture_devices++;
+    } else {
+        open_playback_devices++;
+    }
+
+#if !MACOSX_COREAUDIO
+    if (!update_audio_session(this, SDL_TRUE)) {
+        return -1;
+    }
+#endif
 
 
     /* Setup a AudioStreamBasicDescription with the requested format */
     /* Setup a AudioStreamBasicDescription with the requested format */
-    SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
-    strdesc.mFormatID = kAudioFormatLinearPCM;
-    strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
-    strdesc.mChannelsPerFrame = this->spec.channels;
-    strdesc.mSampleRate = this->spec.freq;
-    strdesc.mFramesPerPacket = 1;
+    SDL_zerop(strdesc);
+    strdesc->mFormatID = kAudioFormatLinearPCM;
+    strdesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
+    strdesc->mChannelsPerFrame = this->spec.channels;
+    strdesc->mSampleRate = this->spec.freq;
+    strdesc->mFramesPerPacket = 1;
 
 
     while ((!valid_datatype) && (test_format)) {
     while ((!valid_datatype) && (test_format)) {
         this->spec.format = test_format;
         this->spec.format = test_format;
@@ -621,34 +759,53 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         case AUDIO_F32LSB:
         case AUDIO_F32LSB:
         case AUDIO_F32MSB:
         case AUDIO_F32MSB:
             valid_datatype = 1;
             valid_datatype = 1;
-            strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
+            strdesc->mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
             if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
             if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
-                strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
+                strdesc->mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
 
 
             if (SDL_AUDIO_ISFLOAT(this->spec.format))
             if (SDL_AUDIO_ISFLOAT(this->spec.format))
-                strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
+                strdesc->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
             else if (SDL_AUDIO_ISSIGNED(this->spec.format))
             else if (SDL_AUDIO_ISSIGNED(this->spec.format))
-                strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+                strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
             break;
             break;
         }
         }
     }
     }
 
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
-        COREAUDIO_CloseDevice(this);
         return SDL_SetError("Unsupported audio format");
         return SDL_SetError("Unsupported audio format");
     }
     }
 
 
-    strdesc.mBytesPerFrame =
-        strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
-    strdesc.mBytesPerPacket =
-        strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
+    strdesc->mBytesPerFrame = strdesc->mBitsPerChannel * strdesc->mChannelsPerFrame / 8;
+    strdesc->mBytesPerPacket = strdesc->mBytesPerFrame * strdesc->mFramesPerPacket;
 
 
-    if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
-        COREAUDIO_CloseDevice(this);
-        return -1;      /* prepare_audiounit() will call SDL_SetError()... */
+#if MACOSX_COREAUDIO
+    if (!prepare_device(this, handle, iscapture)) {
+        return -1;
+    }
+#endif
+
+    /* This has to init in a new thread so it can get its own CFRunLoop. :/ */
+    SDL_AtomicSet(&this->hidden->shutdown, 0);
+    this->hidden->ready_semaphore = SDL_CreateSemaphore(0);
+    if (!this->hidden->ready_semaphore) {
+        return -1;  /* oh well. */
+    }
+
+    this->hidden->thread = SDL_CreateThreadInternal(audioqueue_thread, "AudioQueue thread", 512 * 1024, this);
+    if (!this->hidden->thread) {
+        return -1;
     }
     }
 
 
-    return 0;   /* good to go. */
+    SDL_SemWait(this->hidden->ready_semaphore);
+    SDL_DestroySemaphore(this->hidden->ready_semaphore);
+    this->hidden->ready_semaphore = NULL;
+
+    if ((this->hidden->thread != NULL) && (this->hidden->thread_error != NULL)) {
+        SDL_SetError("%s", this->hidden->thread_error);
+        return -1;
+    }
+
+    return (this->hidden->thread != NULL) ? 0 : -1;
 }
 }
 
 
 static void
 static void
@@ -674,17 +831,11 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
     AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
     AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
 #else
 #else
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
-
-    /* Set category to ambient sound so that other music continues playing.
-       You can change this at runtime in your own code if you need different
-       behavior.  If this is common, we can add an SDL hint for this.
-    */
-    AudioSessionInitialize(NULL, NULL, NULL, nil);
-    UInt32 category = kAudioSessionCategory_AmbientSound;
-    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
+    impl->OnlyHasDefaultCaptureDevice = 1;
 #endif
 #endif
 
 
     impl->ProvidesOwnCallbackThread = 1;
     impl->ProvidesOwnCallbackThread = 1;
+    impl->HasCaptureSupport = 1;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }

+ 186 - 98
Engine/lib/sdl/src/audio/directsound/SDL_directsound.c

@@ -24,6 +24,7 @@
 
 
 /* Allow access to a raw mixing buffer */
 /* Allow access to a raw mixing buffer */
 
 
+#include "SDL_assert.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_loadso.h"
 #include "SDL_loadso.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
@@ -36,11 +37,13 @@
 
 
 /* DirectX function pointers for audio */
 /* DirectX function pointers for audio */
 static void* DSoundDLL = NULL;
 static void* DSoundDLL = NULL;
-typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
-typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
-typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
+typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
+typedef HRESULT (WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
+typedef HRESULT (WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
+typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
 static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
 static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
 static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
 static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
+static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 = NULL;
 static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
 static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
 
 
 static void
 static void
@@ -48,6 +51,7 @@ DSOUND_Unload(void)
 {
 {
     pDirectSoundCreate8 = NULL;
     pDirectSoundCreate8 = NULL;
     pDirectSoundEnumerateW = NULL;
     pDirectSoundEnumerateW = NULL;
+    pDirectSoundCaptureCreate8 = NULL;
     pDirectSoundCaptureEnumerateW = NULL;
     pDirectSoundCaptureEnumerateW = NULL;
 
 
     if (DSoundDLL != NULL) {
     if (DSoundDLL != NULL) {
@@ -76,6 +80,7 @@ DSOUND_Load(void)
         loaded = 1;  /* will reset if necessary. */
         loaded = 1;  /* will reset if necessary. */
         DSOUNDLOAD(DirectSoundCreate8);
         DSOUNDLOAD(DirectSoundCreate8);
         DSOUNDLOAD(DirectSoundEnumerateW);
         DSOUNDLOAD(DirectSoundEnumerateW);
+        DSOUNDLOAD(DirectSoundCaptureCreate8);
         DSOUNDLOAD(DirectSoundCaptureEnumerateW);
         DSOUNDLOAD(DirectSoundCaptureEnumerateW);
         #undef DSOUNDLOAD
         #undef DSOUNDLOAD
 
 
@@ -155,7 +160,7 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
 {
 {
     const int iscapture = (int) ((size_t) data);
     const int iscapture = (int) ((size_t) data);
     if (guid != NULL) {  /* skip default device */
     if (guid != NULL) {  /* skip default device */
-        char *str = WIN_StringToUTF8(desc);
+        char *str = WIN_LookupAudioDeviceName(desc, guid);
         if (str != NULL) {
         if (str != NULL) {
             LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
             LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
             SDL_memcpy(cpyguid, guid, sizeof (GUID));
             SDL_memcpy(cpyguid, guid, sizeof (GUID));
@@ -197,7 +202,7 @@ DSOUND_WaitDevice(_THIS)
         return;
         return;
     }
     }
 
 
-    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
+    while ((cursor / this->spec.size) == this->hidden->lastchunk) {
         /* FIXME: find out how much time is left and sleep that long */
         /* FIXME: find out how much time is left and sleep that long */
         SDL_Delay(1);
         SDL_Delay(1);
 
 
@@ -239,9 +244,8 @@ DSOUND_PlayDevice(_THIS)
     if (this->hidden->locked_buf) {
     if (this->hidden->locked_buf) {
         IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
         IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
                                   this->hidden->locked_buf,
                                   this->hidden->locked_buf,
-                                  this->hidden->mixlen, NULL, 0);
+                                  this->spec.size, NULL, 0);
     }
     }
-
 }
 }
 
 
 static Uint8 *
 static Uint8 *
@@ -265,7 +269,7 @@ DSOUND_GetDeviceBuf(_THIS)
         SetDSerror("DirectSound GetCurrentPosition", result);
         SetDSerror("DirectSound GetCurrentPosition", result);
         return (NULL);
         return (NULL);
     }
     }
-    cursor /= this->hidden->mixlen;
+    cursor /= this->spec.size;
 #ifdef DEBUG_SOUND
 #ifdef DEBUG_SOUND
     /* Detect audio dropouts */
     /* Detect audio dropouts */
     {
     {
@@ -281,17 +285,17 @@ DSOUND_GetDeviceBuf(_THIS)
 #endif
 #endif
     this->hidden->lastchunk = cursor;
     this->hidden->lastchunk = cursor;
     cursor = (cursor + 1) % this->hidden->num_buffers;
     cursor = (cursor + 1) % this->hidden->num_buffers;
-    cursor *= this->hidden->mixlen;
+    cursor *= this->spec.size;
 
 
     /* Lock the audio buffer */
     /* Lock the audio buffer */
     result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
     result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
-                                     this->hidden->mixlen,
+                                     this->spec.size,
                                      (LPVOID *) & this->hidden->locked_buf,
                                      (LPVOID *) & this->hidden->locked_buf,
                                      &rawlen, NULL, &junk, 0);
                                      &rawlen, NULL, &junk, 0);
     if (result == DSERR_BUFFERLOST) {
     if (result == DSERR_BUFFERLOST) {
         IDirectSoundBuffer_Restore(this->hidden->mixbuf);
         IDirectSoundBuffer_Restore(this->hidden->mixbuf);
         result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
         result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
-                                         this->hidden->mixlen,
+                                         this->spec.size,
                                          (LPVOID *) & this->
                                          (LPVOID *) & this->
                                          hidden->locked_buf, &rawlen, NULL,
                                          hidden->locked_buf, &rawlen, NULL,
                                          &junk, 0);
                                          &junk, 0);
@@ -303,109 +307,106 @@ DSOUND_GetDeviceBuf(_THIS)
     return (this->hidden->locked_buf);
     return (this->hidden->locked_buf);
 }
 }
 
 
-static void
-DSOUND_WaitDone(_THIS)
+static int
+DSOUND_CaptureFromDevice(_THIS, void *buffer, int buflen)
 {
 {
-    Uint8 *stream = DSOUND_GetDeviceBuf(this);
+    struct SDL_PrivateAudioData *h = this->hidden;
+    DWORD junk, cursor, ptr1len, ptr2len;
+    VOID *ptr1, *ptr2;
+
+    SDL_assert(buflen == this->spec.size);
+
+    while (SDL_TRUE) {
+        if (SDL_AtomicGet(&this->shutdown)) {  /* in case the buffer froze... */
+            SDL_memset(buffer, this->spec.silence, buflen);
+            return buflen;
+        }
+
+        if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
+            return -1;
+        }
+        if ((cursor / this->spec.size) == h->lastchunk) {
+            SDL_Delay(1);  /* FIXME: find out how much time is left and sleep that long */
+        } else {
+            break;
+        }
+    }
+
+    if (IDirectSoundCaptureBuffer_Lock(h->capturebuf, h->lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
+        return -1;
+    }
+
+    SDL_assert(ptr1len == this->spec.size);
+    SDL_assert(ptr2 == NULL);
+    SDL_assert(ptr2len == 0);
+
+    SDL_memcpy(buffer, ptr1, ptr1len);
 
 
-    /* Wait for the playing chunk to finish */
-    if (stream != NULL) {
-        SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
-        DSOUND_PlayDevice(this);
+    if (IDirectSoundCaptureBuffer_Unlock(h->capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
+        return -1;
     }
     }
-    DSOUND_WaitDevice(this);
 
 
-    /* Stop the looping sound buffer */
-    IDirectSoundBuffer_Stop(this->hidden->mixbuf);
+    h->lastchunk = (h->lastchunk + 1) % h->num_buffers;
+
+    return ptr1len;
 }
 }
 
 
 static void
 static void
-DSOUND_CloseDevice(_THIS)
+DSOUND_FlushCapture(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->sound != NULL) {
-            if (this->hidden->mixbuf != NULL) {
-                /* Clean up the audio buffer */
-                IDirectSoundBuffer_Release(this->hidden->mixbuf);
-                this->hidden->mixbuf = NULL;
-            }
-            IDirectSound_Release(this->hidden->sound);
-            this->hidden->sound = NULL;
-        }
+    struct SDL_PrivateAudioData *h = this->hidden;
+    DWORD junk, cursor;
+    if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) == DS_OK) {
+        h->lastchunk = cursor / this->spec.size;
+    }
+}
 
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+static void
+DSOUND_CloseDevice(_THIS)
+{
+    if (this->hidden->mixbuf != NULL) {
+        IDirectSoundBuffer_Stop(this->hidden->mixbuf);
+        IDirectSoundBuffer_Release(this->hidden->mixbuf);
+    }
+    if (this->hidden->sound != NULL) {
+        IDirectSound_Release(this->hidden->sound);
     }
     }
+    if (this->hidden->capturebuf != NULL) {
+        IDirectSoundCaptureBuffer_Stop(this->hidden->capturebuf);
+        IDirectSoundCaptureBuffer_Release(this->hidden->capturebuf);
+    }
+    if (this->hidden->capture != NULL) {
+        IDirectSoundCapture_Release(this->hidden->capture);
+    }
+    SDL_free(this->hidden);
 }
 }
 
 
 /* This function tries to create a secondary audio buffer, and returns the
 /* This function tries to create a secondary audio buffer, and returns the
-   number of audio chunks available in the created buffer.
+   number of audio chunks available in the created buffer. This is for
+   playback devices, not capture.
 */
 */
 static int
 static int
-CreateSecondary(_THIS, HWND focus)
+CreateSecondary(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
 {
 {
     LPDIRECTSOUND sndObj = this->hidden->sound;
     LPDIRECTSOUND sndObj = this->hidden->sound;
     LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
     LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
-    Uint32 chunksize = this->spec.size;
-    const int numchunks = 8;
     HRESULT result = DS_OK;
     HRESULT result = DS_OK;
     DSBUFFERDESC format;
     DSBUFFERDESC format;
     LPVOID pvAudioPtr1, pvAudioPtr2;
     LPVOID pvAudioPtr1, pvAudioPtr2;
     DWORD dwAudioBytes1, dwAudioBytes2;
     DWORD dwAudioBytes1, dwAudioBytes2;
-    WAVEFORMATEX wfmt;
-
-    SDL_zero(wfmt);
-
-    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
-        wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
-    } else {
-        wfmt.wFormatTag = WAVE_FORMAT_PCM;
-    }
-
-    wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
-    wfmt.nChannels = this->spec.channels;
-    wfmt.nSamplesPerSec = this->spec.freq;
-    wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
-    wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
-
-    /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(&this->spec);
-
-    /* Try to set primary mixing privileges */
-    if (focus) {
-        result = IDirectSound_SetCooperativeLevel(sndObj,
-                                                  focus, DSSCL_PRIORITY);
-    } else {
-        result = IDirectSound_SetCooperativeLevel(sndObj,
-                                                  GetDesktopWindow(),
-                                                  DSSCL_NORMAL);
-    }
-    if (result != DS_OK) {
-        return SetDSerror("DirectSound SetCooperativeLevel", result);
-    }
 
 
     /* Try to create the secondary buffer */
     /* Try to create the secondary buffer */
     SDL_zero(format);
     SDL_zero(format);
     format.dwSize = sizeof(format);
     format.dwSize = sizeof(format);
     format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
     format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
-    if (!focus) {
-        format.dwFlags |= DSBCAPS_GLOBALFOCUS;
-    } else {
-        format.dwFlags |= DSBCAPS_STICKYFOCUS;
-    }
-    format.dwBufferBytes = numchunks * chunksize;
-    if ((format.dwBufferBytes < DSBSIZE_MIN) ||
-        (format.dwBufferBytes > DSBSIZE_MAX)) {
-        return SDL_SetError("Sound buffer size must be between %d and %d",
-                            DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
-    }
-    format.dwReserved = 0;
-    format.lpwfxFormat = &wfmt;
+    format.dwFlags |= DSBCAPS_GLOBALFOCUS;
+    format.dwBufferBytes = bufsize;
+    format.lpwfxFormat = wfmt;
     result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
     result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
     if (result != DS_OK) {
     if (result != DS_OK) {
         return SetDSerror("DirectSound CreateSoundBuffer", result);
         return SetDSerror("DirectSound CreateSoundBuffer", result);
     }
     }
-    IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
+    IDirectSoundBuffer_SetFormat(*sndbuf, wfmt);
 
 
     /* Silence the initial audio buffer */
     /* Silence the initial audio buffer */
     result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
     result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
@@ -420,31 +421,90 @@ CreateSecondary(_THIS, HWND focus)
     }
     }
 
 
     /* We're ready to go */
     /* We're ready to go */
-    return (numchunks);
+    return 0;
+}
+
+/* This function tries to create a capture buffer, and returns the
+   number of audio chunks available in the created buffer. This is for
+   capture devices, not playback.
+*/
+static int
+CreateCaptureBuffer(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
+{
+    LPDIRECTSOUNDCAPTURE capture = this->hidden->capture;
+    LPDIRECTSOUNDCAPTUREBUFFER *capturebuf = &this->hidden->capturebuf;
+    DSCBUFFERDESC format;
+//    DWORD junk, cursor;
+    HRESULT result;
+
+    SDL_zero(format);
+    format.dwSize = sizeof (format);
+    format.dwFlags = DSCBCAPS_WAVEMAPPED;
+    format.dwBufferBytes = bufsize;
+    format.lpwfxFormat = wfmt;
+
+    result = IDirectSoundCapture_CreateCaptureBuffer(capture, &format, capturebuf, NULL);
+    if (result != DS_OK) {
+        return SetDSerror("DirectSound CreateCaptureBuffer", result);
+    }
+
+    result = IDirectSoundCaptureBuffer_Start(*capturebuf, DSCBSTART_LOOPING);
+    if (result != DS_OK) {
+        IDirectSoundCaptureBuffer_Release(*capturebuf);
+        return SetDSerror("DirectSound Start", result);
+    }
+
+#if 0
+    /* presumably this starts at zero, but just in case... */
+    result = IDirectSoundCaptureBuffer_GetCurrentPosition(*capturebuf, &junk, &cursor);
+    if (result != DS_OK) {
+        IDirectSoundCaptureBuffer_Stop(*capturebuf);
+        IDirectSoundCaptureBuffer_Release(*capturebuf);
+        return SetDSerror("DirectSound GetCurrentPosition", result);
+    }
+
+    this->hidden->lastchunk = cursor / this->spec.size;
+#endif
+
+    return 0;
 }
 }
 
 
 static int
 static int
 DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
+    const DWORD numchunks = 8;
     HRESULT result;
     HRESULT result;
     SDL_bool valid_format = SDL_FALSE;
     SDL_bool valid_format = SDL_FALSE;
     SDL_bool tried_format = SDL_FALSE;
     SDL_bool tried_format = SDL_FALSE;
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
     LPGUID guid = (LPGUID) handle;
     LPGUID guid = (LPGUID) handle;
-
+	DWORD bufsize;
+	
     /* Initialize all variables that we clean on shutdown */
     /* Initialize all variables that we clean on shutdown */
     this->hidden = (struct SDL_PrivateAudioData *)
     this->hidden = (struct SDL_PrivateAudioData *)
         SDL_malloc((sizeof *this->hidden));
         SDL_malloc((sizeof *this->hidden));
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
-    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
-    if (result != DS_OK) {
-        DSOUND_CloseDevice(this);
-        return SetDSerror("DirectSoundCreate", result);
+    if (iscapture) {
+        result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture, NULL);
+        if (result != DS_OK) {
+            return SetDSerror("DirectSoundCaptureCreate8", result);
+        }
+    } else {
+        result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
+        if (result != DS_OK) {
+            return SetDSerror("DirectSoundCreate8", result);
+        }
+        result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
+                                                  GetDesktopWindow(),
+                                                  DSSCL_NORMAL);
+        if (result != DS_OK) {
+            return SetDSerror("DirectSound SetCooperativeLevel", result);
+        }
     }
     }
 
 
     while ((!valid_format) && (test_format)) {
     while ((!valid_format) && (test_format)) {
@@ -454,10 +514,38 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         case AUDIO_S32:
         case AUDIO_S32:
         case AUDIO_F32:
         case AUDIO_F32:
             tried_format = SDL_TRUE;
             tried_format = SDL_TRUE;
+
             this->spec.format = test_format;
             this->spec.format = test_format;
-            this->hidden->num_buffers = CreateSecondary(this, NULL);
-            if (this->hidden->num_buffers > 0) {
-                valid_format = SDL_TRUE;
+
+            /* Update the fragment size as size in bytes */
+            SDL_CalculateAudioSpec(&this->spec);
+
+            bufsize = numchunks * this->spec.size;
+            if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) {
+                SDL_SetError("Sound buffer size must be between %d and %d",
+                             (DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks,
+                             DSBSIZE_MAX / numchunks);
+            } else {
+                int rc;
+				WAVEFORMATEX wfmt;
+                SDL_zero(wfmt);
+                if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
+                    wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+                } else {
+                    wfmt.wFormatTag = WAVE_FORMAT_PCM;
+                }
+
+                wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+                wfmt.nChannels = this->spec.channels;
+                wfmt.nSamplesPerSec = this->spec.freq;
+                wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
+                wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
+
+                rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
+                if (rc == 0) {
+                    this->hidden->num_buffers = numchunks;
+                    valid_format = SDL_TRUE;
+                }
             }
             }
             break;
             break;
         }
         }
@@ -465,15 +553,13 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!valid_format) {
     if (!valid_format) {
-        DSOUND_CloseDevice(this);
         if (tried_format) {
         if (tried_format) {
             return -1;  /* CreateSecondary() should have called SDL_SetError(). */
             return -1;  /* CreateSecondary() should have called SDL_SetError(). */
         }
         }
         return SDL_SetError("DirectSound: Unsupported audio format");
         return SDL_SetError("DirectSound: Unsupported audio format");
     }
     }
 
 
-    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
-    this->hidden->mixlen = this->spec.size;
+    /* Playback buffers will auto-start playing in DSOUND_WaitDevice() */
 
 
     return 0;                   /* good to go. */
     return 0;                   /* good to go. */
 }
 }
@@ -498,13 +584,15 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
     impl->OpenDevice = DSOUND_OpenDevice;
     impl->OpenDevice = DSOUND_OpenDevice;
     impl->PlayDevice = DSOUND_PlayDevice;
     impl->PlayDevice = DSOUND_PlayDevice;
     impl->WaitDevice = DSOUND_WaitDevice;
     impl->WaitDevice = DSOUND_WaitDevice;
-    impl->WaitDone = DSOUND_WaitDone;
     impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
     impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
+    impl->CaptureFromDevice = DSOUND_CaptureFromDevice;
+    impl->FlushCapture = DSOUND_FlushCapture;
     impl->CloseDevice = DSOUND_CloseDevice;
     impl->CloseDevice = DSOUND_CloseDevice;
     impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
     impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
-
     impl->Deinitialize = DSOUND_Deinitialize;
     impl->Deinitialize = DSOUND_Deinitialize;
 
 
+    impl->HasCaptureSupport = SDL_TRUE;
+
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 

+ 2 - 1
Engine/lib/sdl/src/audio/directsound/SDL_directsound.h

@@ -35,8 +35,9 @@ struct SDL_PrivateAudioData
 {
 {
     LPDIRECTSOUND sound;
     LPDIRECTSOUND sound;
     LPDIRECTSOUNDBUFFER mixbuf;
     LPDIRECTSOUNDBUFFER mixbuf;
+    LPDIRECTSOUNDCAPTURE capture;
+    LPDIRECTSOUNDCAPTUREBUFFER capturebuf;
     int num_buffers;
     int num_buffers;
-    int mixlen;
     DWORD lastchunk;
     DWORD lastchunk;
     Uint8 *locked_buf;
     Uint8 *locked_buf;
 };
 };

+ 96 - 63
Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c

@@ -31,46 +31,33 @@
 #include "SDL_rwops.h"
 #include "SDL_rwops.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_diskaudio.h"
 #include "SDL_diskaudio.h"
 
 
+/* !!! FIXME: these should be SDL hints, not environment variables. */
 /* environment variables and defaults. */
 /* environment variables and defaults. */
 #define DISKENVR_OUTFILE         "SDL_DISKAUDIOFILE"
 #define DISKENVR_OUTFILE         "SDL_DISKAUDIOFILE"
 #define DISKDEFAULT_OUTFILE      "sdlaudio.raw"
 #define DISKDEFAULT_OUTFILE      "sdlaudio.raw"
-#define DISKENVR_WRITEDELAY      "SDL_DISKAUDIODELAY"
-#define DISKDEFAULT_WRITEDELAY   150
-
-static const char *
-DISKAUD_GetOutputFilename(const char *devname)
-{
-    if (devname == NULL) {
-        devname = SDL_getenv(DISKENVR_OUTFILE);
-        if (devname == NULL) {
-            devname = DISKDEFAULT_OUTFILE;
-        }
-    }
-    return devname;
-}
+#define DISKENVR_INFILE         "SDL_DISKAUDIOFILEIN"
+#define DISKDEFAULT_INFILE      "sdlaudio-in.raw"
+#define DISKENVR_IODELAY      "SDL_DISKAUDIODELAY"
 
 
 /* This function waits until it is possible to write a full sound buffer */
 /* This function waits until it is possible to write a full sound buffer */
 static void
 static void
-DISKAUD_WaitDevice(_THIS)
+DISKAUDIO_WaitDevice(_THIS)
 {
 {
-    SDL_Delay(this->hidden->write_delay);
+    SDL_Delay(this->hidden->io_delay);
 }
 }
 
 
 static void
 static void
-DISKAUD_PlayDevice(_THIS)
+DISKAUDIO_PlayDevice(_THIS)
 {
 {
-    size_t written;
-
-    /* Write the audio data */
-    written = SDL_RWwrite(this->hidden->output,
-                          this->hidden->mixbuf, 1, this->hidden->mixlen);
+    const size_t written = SDL_RWwrite(this->hidden->io,
+                                       this->hidden->mixbuf,
+                                       1, this->spec.size);
 
 
     /* If we couldn't write, assume fatal error for now */
     /* If we couldn't write, assume fatal error for now */
-    if (written != this->hidden->mixlen) {
+    if (written != this->spec.size) {
         SDL_OpenedAudioDeviceDisconnected(this);
         SDL_OpenedAudioDeviceDisconnected(this);
     }
     }
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
@@ -79,63 +66,105 @@ DISKAUD_PlayDevice(_THIS)
 }
 }
 
 
 static Uint8 *
 static Uint8 *
-DISKAUD_GetDeviceBuf(_THIS)
+DISKAUDIO_GetDeviceBuf(_THIS)
 {
 {
     return (this->hidden->mixbuf);
     return (this->hidden->mixbuf);
 }
 }
 
 
+static int
+DISKAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    struct SDL_PrivateAudioData *h = this->hidden;
+    const int origbuflen = buflen;
+
+    SDL_Delay(h->io_delay);
+
+    if (h->io) {
+        const size_t br = SDL_RWread(h->io, buffer, 1, buflen);
+        buflen -= (int) br;
+        buffer = ((Uint8 *) buffer) + br;
+        if (buflen > 0) {  /* EOF (or error, but whatever). */
+            SDL_RWclose(h->io);
+            h->io = NULL;
+        }
+    }
+
+    /* if we ran out of file, just write silence. */
+    SDL_memset(buffer, this->spec.silence, buflen);
+
+    return origbuflen;
+}
+
 static void
 static void
-DISKAUD_CloseDevice(_THIS)
+DISKAUDIO_FlushCapture(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->output != NULL) {
-            SDL_RWclose(this->hidden->output);
-            this->hidden->output = NULL;
+    /* no op...we don't advance the file pointer or anything. */
+}
+
+
+static void
+DISKAUDIO_CloseDevice(_THIS)
+{
+    if (this->hidden->io != NULL) {
+        SDL_RWclose(this->hidden->io);
+    }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
+}
+
+
+static const char *
+get_filename(const int iscapture, const char *devname)
+{
+    if (devname == NULL) {
+        devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
+        if (devname == NULL) {
+            devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
         }
         }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
     }
     }
+    return devname;
 }
 }
 
 
 static int
 static int
-DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+DISKAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
     /* handle != NULL means "user specified the placeholder name on the fake detected device list" */
     /* handle != NULL means "user specified the placeholder name on the fake detected device list" */
-    const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
-    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
+    const char *fname = get_filename(iscapture, handle ? NULL : devname);
+    const char *envr = SDL_getenv(DISKENVR_IODELAY);
 
 
     this->hidden = (struct SDL_PrivateAudioData *)
     this->hidden = (struct SDL_PrivateAudioData *)
         SDL_malloc(sizeof(*this->hidden));
         SDL_malloc(sizeof(*this->hidden));
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+    SDL_zerop(this->hidden);
 
 
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->write_delay =
-        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
+    if (envr != NULL) {
+        this->hidden->io_delay = SDL_atoi(envr);
+    } else {
+        this->hidden->io_delay = ((this->spec.samples * 1000) / this->spec.freq);
+    }
 
 
     /* Open the audio device */
     /* Open the audio device */
-    this->hidden->output = SDL_RWFromFile(fname, "wb");
-    if (this->hidden->output == NULL) {
-        DISKAUD_CloseDevice(this);
+    this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
+    if (this->hidden->io == NULL) {
         return -1;
         return -1;
     }
     }
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        DISKAUD_CloseDevice(this);
-        return -1;
+    if (!iscapture) {
+        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
+        if (this->hidden->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     }
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
 
 #if HAVE_STDIO_H
 #if HAVE_STDIO_H
     fprintf(stderr,
     fprintf(stderr,
-            "WARNING: You are using the SDL disk writer audio driver!\n"
-            " Writing to file [%s].\n", fname);
+            "WARNING: You are using the SDL disk i/o audio driver!\n"
+            " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
+            fname);
 #endif
 #endif
 
 
     /* We're ready to rock and roll. :-) */
     /* We're ready to rock and roll. :-) */
@@ -143,30 +172,34 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 }
 }
 
 
 static void
 static void
-DISKAUD_DetectDevices(void)
+DISKAUDIO_DetectDevices(void)
 {
 {
-    /* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
-    SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
+    SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
+    SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
 }
 }
 
 
 static int
 static int
-DISKAUD_Init(SDL_AudioDriverImpl * impl)
+DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = DISKAUD_OpenDevice;
-    impl->WaitDevice = DISKAUD_WaitDevice;
-    impl->PlayDevice = DISKAUD_PlayDevice;
-    impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
-    impl->CloseDevice = DISKAUD_CloseDevice;
-    impl->DetectDevices = DISKAUD_DetectDevices;
+    impl->OpenDevice = DISKAUDIO_OpenDevice;
+    impl->WaitDevice = DISKAUDIO_WaitDevice;
+    impl->PlayDevice = DISKAUDIO_PlayDevice;
+    impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf;
+    impl->CaptureFromDevice = DISKAUDIO_CaptureFromDevice;
+    impl->FlushCapture = DISKAUDIO_FlushCapture;
+
+    impl->CloseDevice = DISKAUDIO_CloseDevice;
+    impl->DetectDevices = DISKAUDIO_DetectDevices;
 
 
     impl->AllowsArbitraryDeviceNames = 1;
     impl->AllowsArbitraryDeviceNames = 1;
+    impl->HasCaptureSupport = SDL_TRUE;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 
-AudioBootStrap DISKAUD_bootstrap = {
-    "disk", "direct-to-disk audio", DISKAUD_Init, 1
+AudioBootStrap DISKAUDIO_bootstrap = {
+    "disk", "direct-to-disk audio", DISKAUDIO_Init, 1
 };
 };
 
 
 #endif /* SDL_AUDIO_DRIVER_DISK */
 #endif /* SDL_AUDIO_DRIVER_DISK */

+ 2 - 3
Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h

@@ -32,10 +32,9 @@
 struct SDL_PrivateAudioData
 struct SDL_PrivateAudioData
 {
 {
     /* The file descriptor for the audio device */
     /* The file descriptor for the audio device */
-    SDL_RWops *output;
+    SDL_RWops *io;
+    Uint32 io_delay;
     Uint8 *mixbuf;
     Uint8 *mixbuf;
-    Uint32 mixlen;
-    Uint32 write_delay;
 };
 };
 
 
 #endif /* _SDL_diskaudio_h */
 #endif /* _SDL_diskaudio_h */

+ 43 - 31
Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c

@@ -44,7 +44,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 #include "SDL_dspaudio.h"
 #include "SDL_dspaudio.h"
@@ -60,16 +59,11 @@ DSP_DetectDevices(void)
 static void
 static void
 DSP_CloseDevice(_THIS)
 DSP_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 
 
@@ -106,23 +100,20 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
     this->hidden->audio_fd = open(devname, flags, 0);
     this->hidden->audio_fd = open(devname, flags, 0);
     if (this->hidden->audio_fd < 0) {
     if (this->hidden->audio_fd < 0) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
     }
     }
-    this->hidden->mixbuf = NULL;
 
 
-    /* Make the file descriptor use blocking writes with fcntl() */
+    /* Make the file descriptor use blocking i/o with fcntl() */
     {
     {
         long ctlflags;
         long ctlflags;
         ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
         ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
         ctlflags &= ~O_NONBLOCK;
         ctlflags &= ~O_NONBLOCK;
         if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
         if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
-            DSP_CloseDevice(this);
             return SDL_SetError("Couldn't set audio blocking mode");
             return SDL_SetError("Couldn't set audio blocking mode");
         }
         }
     }
     }
@@ -130,7 +121,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Get a list of supported hardware formats */
     /* Get a list of supported hardware formats */
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
         perror("SNDCTL_DSP_GETFMTS");
         perror("SNDCTL_DSP_GETFMTS");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't get audio format list");
         return SDL_SetError("Couldn't get audio format list");
     }
     }
 
 
@@ -187,7 +177,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         }
         }
     }
     }
     if (format == 0) {
     if (format == 0) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
@@ -197,7 +186,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
     if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
         (value != format)) {
         (value != format)) {
         perror("SNDCTL_DSP_SETFMT");
         perror("SNDCTL_DSP_SETFMT");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't set audio format");
         return SDL_SetError("Couldn't set audio format");
     }
     }
 
 
@@ -205,7 +193,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     value = this->spec.channels;
     value = this->spec.channels;
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
         perror("SNDCTL_DSP_CHANNELS");
         perror("SNDCTL_DSP_CHANNELS");
-        DSP_CloseDevice(this);
         return SDL_SetError("Cannot set the number of channels");
         return SDL_SetError("Cannot set the number of channels");
     }
     }
     this->spec.channels = value;
     this->spec.channels = value;
@@ -214,7 +201,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     value = this->spec.freq;
     value = this->spec.freq;
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
     if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
         perror("SNDCTL_DSP_SPEED");
         perror("SNDCTL_DSP_SPEED");
-        DSP_CloseDevice(this);
         return SDL_SetError("Couldn't set audio frequency");
         return SDL_SetError("Couldn't set audio frequency");
     }
     }
     this->spec.freq = value;
     this->spec.freq = value;
@@ -225,7 +211,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Determine the power of two of the fragment size */
     /* Determine the power of two of the fragment size */
     for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
     for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
     if ((0x01U << frag_spec) != this->spec.size) {
     if ((0x01U << frag_spec) != this->spec.size) {
-        DSP_CloseDevice(this);
         return SDL_SetError("Fragment size must be a power of two");
         return SDL_SetError("Fragment size must be a power of two");
     }
     }
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
     frag_spec |= 0x00020000;    /* two fragments, for low latency */
@@ -250,13 +235,14 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 #endif
 #endif
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        DSP_CloseDevice(this);
-        return SDL_OutOfMemory();
+    if (!iscapture) {
+        this->hidden->mixlen = this->spec.size;
+        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+        if (this->hidden->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     }
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
 
     /* We're ready to rock and roll. :-) */
     /* We're ready to rock and roll. :-) */
     return 0;
     return 0;
@@ -266,14 +252,13 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 static void
 static void
 DSP_PlayDevice(_THIS)
 DSP_PlayDevice(_THIS)
 {
 {
-    const Uint8 *mixbuf = this->hidden->mixbuf;
-    const int mixlen = this->hidden->mixlen;
-    if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
+    struct SDL_PrivateAudioData *h = this->hidden;
+    if (write(h->audio_fd, h->mixbuf, h->mixlen) == -1) {
         perror("Audio write");
         perror("Audio write");
         SDL_OpenedAudioDeviceDisconnected(this);
         SDL_OpenedAudioDeviceDisconnected(this);
     }
     }
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
-    fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
+    fprintf(stderr, "Wrote %d bytes of audio data\n", h->mixlen);
 #endif
 #endif
 }
 }
 
 
@@ -283,6 +268,30 @@ DSP_GetDeviceBuf(_THIS)
     return (this->hidden->mixbuf);
     return (this->hidden->mixbuf);
 }
 }
 
 
+static int
+DSP_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    return (int) read(this->hidden->audio_fd, buffer, buflen);
+}
+
+static void
+DSP_FlushCapture(_THIS)
+{
+    struct SDL_PrivateAudioData *h = this->hidden;
+    audio_buf_info info;
+    if (ioctl(h->audio_fd, SNDCTL_DSP_GETISPACE, &info) == 0) {
+        while (info.bytes > 0) {
+            char buf[512];
+            const size_t len = SDL_min(sizeof (buf), info.bytes);
+            const ssize_t br = read(h->audio_fd, buf, len);
+            if (br <= 0) {
+                break;
+            }
+            info.bytes -= br;
+        }
+    }
+}
+
 static int
 static int
 DSP_Init(SDL_AudioDriverImpl * impl)
 DSP_Init(SDL_AudioDriverImpl * impl)
 {
 {
@@ -292,8 +301,11 @@ DSP_Init(SDL_AudioDriverImpl * impl)
     impl->PlayDevice = DSP_PlayDevice;
     impl->PlayDevice = DSP_PlayDevice;
     impl->GetDeviceBuf = DSP_GetDeviceBuf;
     impl->GetDeviceBuf = DSP_GetDeviceBuf;
     impl->CloseDevice = DSP_CloseDevice;
     impl->CloseDevice = DSP_CloseDevice;
+    impl->CaptureFromDevice = DSP_CaptureFromDevice;
+    impl->FlushCapture = DSP_FlushCapture;
 
 
     impl->AllowsArbitraryDeviceNames = 1;
     impl->AllowsArbitraryDeviceNames = 1;
+    impl->HasCaptureSupport = SDL_TRUE;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }

+ 22 - 5
Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c

@@ -22,27 +22,44 @@
 
 
 /* Output audio to nowhere... */
 /* Output audio to nowhere... */
 
 
+#include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_dummyaudio.h"
 #include "SDL_dummyaudio.h"
 
 
 static int
 static int
-DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+DUMMYAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
     return 0;                   /* always succeeds. */
     return 0;                   /* always succeeds. */
 }
 }
 
 
 static int
 static int
-DUMMYAUD_Init(SDL_AudioDriverImpl * impl)
+DUMMYAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    /* Delay to make this sort of simulate real audio input. */
+    SDL_Delay((this->spec.samples * 1000) / this->spec.freq);
+
+    /* always return a full buffer of silence. */
+    SDL_memset(buffer, this->spec.silence, buflen);
+    return buflen;
+}
+
+static int
+DUMMYAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = DUMMYAUD_OpenDevice;
+    impl->OpenDevice = DUMMYAUDIO_OpenDevice;
+    impl->CaptureFromDevice = DUMMYAUDIO_CaptureFromDevice;
+
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
+    impl->OnlyHasDefaultCaptureDevice = 1;
+    impl->HasCaptureSupport = SDL_TRUE;
+
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 
-AudioBootStrap DUMMYAUD_bootstrap = {
-    "dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1
+AudioBootStrap DUMMYAUDIO_bootstrap = {
+    "dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, 1
 };
 };
 
 
 /* vi: set ts=4 sw=4 expandtab: */
 /* vi: set ts=4 sw=4 expandtab: */

+ 225 - 61
Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c

@@ -61,16 +61,15 @@ HandleAudioProcess(_THIS)
     Uint8 *buf = NULL;
     Uint8 *buf = NULL;
     int byte_len = 0;
     int byte_len = 0;
     int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
     int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
-    int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
 
 
-    /* Only do soemthing if audio is enabled */
-    if (!this->enabled)
-        return;
-
-    if (this->paused)
+    /* Only do something if audio is enabled */
+    if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
         return;
         return;
+    }
 
 
     if (this->convert.needed) {
     if (this->convert.needed) {
+        const int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
+
         if (this->hidden->conv_in_len != 0) {
         if (this->hidden->conv_in_len != 0) {
             this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
             this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
         }
         }
@@ -128,7 +127,7 @@ HandleAudioProcess(_THIS)
                 }
                 }
 
 
                 for (var j = 0; j < $1; ++j) {
                 for (var j = 0; j < $1; ++j) {
-                    channelData[j] = getValue($0 + (j*numChannels + c)*4, 'float');
+                    channelData[j] = HEAPF32[$0 + ((j*numChannels + c) << 2) >> 2];
                 }
                 }
             }
             }
         }, buf, byte_len / bytes / this->spec.channels);
         }, buf, byte_len / bytes / this->spec.channels);
@@ -136,29 +135,147 @@ HandleAudioProcess(_THIS)
 }
 }
 
 
 static void
 static void
-Emscripten_CloseDevice(_THIS)
+HandleCaptureProcess(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            /* Clean up the audio buffer */
-            SDL_free(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
+    Uint8 *buf;
+    int buflen;
+
+    /* Only do something if audio is enabled */
+    if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
+        return;
+    }
+
+    if (this->convert.needed) {
+        buf = this->convert.buf;
+        buflen = this->convert.len_cvt;
+    } else {
+        if (!this->hidden->mixbuf) {
+            this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
+            if (!this->hidden->mixbuf) {
+                return;  /* oh well. */
+            }
+        }
+        buf = this->hidden->mixbuf;
+        buflen = this->spec.size;
+    }
+
+    EM_ASM_ARGS({
+        var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
+        if (numChannels == 1) {  /* fastpath this a little for the common (mono) case. */
+            var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(0);
+            if (channelData.length != $1) {
+                throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
+            }
+            for (var j = 0; j < $1; ++j) {
+                setValue($0 + (j * 4), channelData[j], 'float');
+            }
+        } else {
+            for (var c = 0; c < numChannels; ++c) {
+                var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c);
+                if (channelData.length != $1) {
+                    throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
+                }
+
+                for (var j = 0; j < $1; ++j) {
+                    setValue($0 + (((j * numChannels) + c) * 4), channelData[j], 'float');
+                }
+            }
         }
         }
+    }, buf, (this->spec.size / sizeof (float)) / this->spec.channels);
+
+    /* okay, we've got an interleaved float32 array in C now. */
 
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->convert.needed) {
+        SDL_ConvertAudio(&this->convert);
     }
     }
+
+    /* Send it to the app. */
+    (*this->spec.callback) (this->spec.userdata, buf, buflen);
+}
+
+
+
+static void
+EMSCRIPTENAUDIO_CloseDevice(_THIS)
+{
+    EM_ASM_({
+        if ($0) {
+            if (SDL2.capture.silenceTimer !== undefined) {
+                clearTimeout(SDL2.capture.silenceTimer);
+            }
+            if (SDL2.capture.stream !== undefined) {
+                var tracks = SDL2.capture.stream.getAudioTracks();
+                for (var i = 0; i < tracks.length; i++) {
+                    SDL2.capture.stream.removeTrack(tracks[i]);
+                }
+                SDL2.capture.stream = undefined;
+            }
+            if (SDL2.capture.scriptProcessorNode !== undefined) {
+                SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
+                SDL2.capture.scriptProcessorNode.disconnect();
+                SDL2.capture.scriptProcessorNode = undefined;
+            }
+            if (SDL2.capture.mediaStreamNode !== undefined) {
+                SDL2.capture.mediaStreamNode.disconnect();
+                SDL2.capture.mediaStreamNode = undefined;
+            }
+            if (SDL2.capture.silenceBuffer !== undefined) {
+                SDL2.capture.silenceBuffer = undefined
+            }
+            SDL2.capture = undefined;
+        } else {
+            if (SDL2.audio.scriptProcessorNode != undefined) {
+                SDL2.audio.scriptProcessorNode.disconnect();
+                SDL2.audio.scriptProcessorNode = undefined;
+            }
+            SDL2.audio = undefined;
+        }
+        if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
+            SDL2.audioContext.close();
+            SDL2.audioContext = undefined;
+        }
+    }, this->iscapture);
+
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
-Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
     SDL_bool valid_format = SDL_FALSE;
     SDL_bool valid_format = SDL_FALSE;
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
+    SDL_AudioFormat test_format;
     int i;
     int i;
     float f;
     float f;
     int result;
     int result;
 
 
+    /* based on parts of library_sdl.js */
+
+    /* create context (TODO: this puts stuff in the global namespace...)*/
+    result = EM_ASM_INT({
+        if(typeof(SDL2) === 'undefined') {
+            SDL2 = {};
+        }
+        if (!$0) {
+            SDL2.audio = {};
+        } else {
+            SDL2.capture = {};
+        }
+
+        if (!SDL2.audioContext) {
+            if (typeof(AudioContext) !== 'undefined') {
+                SDL2.audioContext = new AudioContext();
+            } else if (typeof(webkitAudioContext) !== 'undefined') {
+                SDL2.audioContext = new webkitAudioContext();
+            }
+        }
+        return SDL2.audioContext === undefined ? -1 : 0;
+    }, iscapture);
+    if (result < 0) {
+        return SDL_SetError("Web Audio API is not available!");
+    }
+
+    test_format = SDL_FirstAudioFormat(this->spec.format);
     while ((!valid_format) && (test_format)) {
     while ((!valid_format) && (test_format)) {
         switch (test_format) {
         switch (test_format) {
         case AUDIO_F32: /* web audio only supports floats */
         case AUDIO_F32: /* web audio only supports floats */
@@ -181,36 +298,11 @@ Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* based on parts of library_sdl.js */
-
-    /* create context (TODO: this puts stuff in the global namespace...)*/
-    result = EM_ASM_INT_V({
-        if(typeof(SDL2) === 'undefined')
-            SDL2 = {};
-
-        if(typeof(SDL2.audio) === 'undefined')
-            SDL2.audio = {};
-
-        if (!SDL2.audioContext) {
-            if (typeof(AudioContext) !== 'undefined') {
-                SDL2.audioContext = new AudioContext();
-            } else if (typeof(webkitAudioContext) !== 'undefined') {
-                SDL2.audioContext = new webkitAudioContext();
-            } else {
-                return -1;
-            }
-        }
-        return 0;
-    });
-    if (result < 0) {
-        return SDL_SetError("Web Audio API is not available!");
-    }
+    SDL_zerop(this->hidden);
 
 
     /* limit to native freq */
     /* limit to native freq */
-    int sampleRate = EM_ASM_INT_V({
-        return SDL2.audioContext['sampleRate'];
+    const int sampleRate = EM_ASM_INT_V({
+        return SDL2.audioContext.sampleRate;
     });
     });
 
 
     if(this->spec.freq != sampleRate) {
     if(this->spec.freq != sampleRate) {
@@ -227,26 +319,86 @@ Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
-    /* setup a ScriptProcessorNode */
-    EM_ASM_ARGS({
-        SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
-        SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
-            SDL2.audio.currentOutputBuffer = e['outputBuffer'];
-            Runtime.dynCall('vi', $2, [$3]);
-        };
-        SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
-    }, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
+    if (iscapture) {
+        /* The idea is to take the capture media stream, hook it up to an
+           audio graph where we can pass it through a ScriptProcessorNode
+           to access the raw PCM samples and push them to the SDL app's
+           callback. From there, we "process" the audio data into silence
+           and forget about it. */
+
+        /* This should, strictly speaking, use MediaRecorder for capture, but
+           this API is cleaner to use and better supported, and fires a
+           callback whenever there's enough data to fire down into the app.
+           The downside is that we are spending CPU time silencing a buffer
+           that the audiocontext uselessly mixes into any output. On the
+           upside, both of those things are not only run in native code in
+           the browser, they're probably SIMD code, too. MediaRecorder
+           feels like it's a pretty inefficient tapdance in similar ways,
+           to be honest. */
+
+        EM_ASM_({
+            var have_microphone = function(stream) {
+                //console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
+                if (SDL2.capture.silenceTimer !== undefined) {
+                    clearTimeout(SDL2.capture.silenceTimer);
+                    SDL2.capture.silenceTimer = undefined;
+                }
+                SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream);
+                SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
+                SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
+                    if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; }
+                    audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
+                    SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
+                    Runtime.dynCall('vi', $2, [$3]);
+                };
+                SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
+                SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
+                SDL2.capture.stream = stream;
+            };
+
+            var no_microphone = function(error) {
+                //console.log('SDL audio capture: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.');
+            };
+
+            /* we write silence to the audio callback until the microphone is available (user approves use, etc). */
+            SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
+            SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
+            var silence_callback = function() {
+                SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
+                Runtime.dynCall('vi', $2, [$3]);
+            };
+
+            SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
+
+            if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
+                navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone);
+            } else if (navigator.webkitGetUserMedia !== undefined) {
+                navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone);
+            }
+        }, this->spec.channels, this->spec.samples, HandleCaptureProcess, this);
+    } else {
+        /* setup a ScriptProcessorNode */
+        EM_ASM_ARGS({
+            SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
+            SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
+                if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; }
+                SDL2.audio.currentOutputBuffer = e['outputBuffer'];
+                Runtime.dynCall('vi', $2, [$3]);
+            };
+            SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
+        }, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
+    }
+
     return 0;
     return 0;
 }
 }
 
 
 static int
 static int
-Emscripten_Init(SDL_AudioDriverImpl * impl)
+EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = Emscripten_OpenDevice;
-    impl->CloseDevice = Emscripten_CloseDevice;
+    impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
+    impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice;
 
 
-    /* only one output */
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
 
 
     /* no threads here */
     /* no threads here */
@@ -254,7 +406,7 @@ Emscripten_Init(SDL_AudioDriverImpl * impl)
     impl->ProvidesOwnCallbackThread = 1;
     impl->ProvidesOwnCallbackThread = 1;
 
 
     /* check availability */
     /* check availability */
-    int available = EM_ASM_INT_V({
+    const int available = EM_ASM_INT_V({
         if (typeof(AudioContext) !== 'undefined') {
         if (typeof(AudioContext) !== 'undefined') {
             return 1;
             return 1;
         } else if (typeof(webkitAudioContext) !== 'undefined') {
         } else if (typeof(webkitAudioContext) !== 'undefined') {
@@ -267,11 +419,23 @@ Emscripten_Init(SDL_AudioDriverImpl * impl)
         SDL_SetError("No audio context available");
         SDL_SetError("No audio context available");
     }
     }
 
 
+    const int capture_available = available && EM_ASM_INT_V({
+        if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
+            return 1;
+        } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
+            return 1;
+        }
+        return 0;
+    });
+
+    impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE;
+    impl->OnlyHasDefaultCaptureDevice = capture_available ? SDL_TRUE : SDL_FALSE;
+
     return available;
     return available;
 }
 }
 
 
-AudioBootStrap EmscriptenAudio_bootstrap = {
-    "emscripten", "SDL emscripten audio driver", Emscripten_Init, 0
+AudioBootStrap EMSCRIPTENAUDIO_bootstrap = {
+    "emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
 };
 };
 
 
 #endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */
 #endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */

+ 6 - 16
Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c

@@ -32,7 +32,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_esdaudio.h"
 #include "SDL_esdaudio.h"
 
 
@@ -174,17 +173,11 @@ ESD_GetDeviceBuf(_THIS)
 static void
 static void
 ESD_CloseDevice(_THIS)
 ESD_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            SDL_NAME(esd_close) (this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        SDL_NAME(esd_close) (this->hidden->audio_fd);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 /* Try to get the name of the program */
 /* Try to get the name of the program */
@@ -227,7 +220,7 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
     this->hidden->audio_fd = -1;
     this->hidden->audio_fd = -1;
 
 
     /* Convert audio spec to the ESD audio format */
     /* Convert audio spec to the ESD audio format */
@@ -252,7 +245,6 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!found) {
     if (!found) {
-        ESD_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
 
 
@@ -271,7 +263,6 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
                                    get_progname());
                                    get_progname());
 
 
     if (this->hidden->audio_fd < 0) {
     if (this->hidden->audio_fd < 0) {
-        ESD_CloseDevice(this);
         return SDL_SetError("Couldn't open ESD connection");
         return SDL_SetError("Couldn't open ESD connection");
     }
     }
 
 
@@ -283,9 +274,8 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        ESD_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);

+ 11 - 28
Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c

@@ -22,6 +22,8 @@
 
 
 #if SDL_AUDIO_DRIVER_FUSIONSOUND
 #if SDL_AUDIO_DRIVER_FUSIONSOUND
 
 
+/* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
+
 /* Allow access to a raw mixing buffer */
 /* Allow access to a raw mixing buffer */
 
 
 #ifdef HAVE_SIGNAL_H
 #ifdef HAVE_SIGNAL_H
@@ -31,7 +33,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_fsaudio.h"
 #include "SDL_fsaudio.h"
 
 
@@ -150,13 +151,6 @@ SDL_FS_PlayDevice(_THIS)
 #endif
 #endif
 }
 }
 
 
-static void
-SDL_FS_WaitDone(_THIS)
-{
-    this->hidden->stream->Wait(this->hidden->stream,
-                               this->hidden->mixsamples * FUSION_BUFFERS);
-}
-
 
 
 static Uint8 *
 static Uint8 *
 SDL_FS_GetDeviceBuf(_THIS)
 SDL_FS_GetDeviceBuf(_THIS)
@@ -168,20 +162,14 @@ SDL_FS_GetDeviceBuf(_THIS)
 static void
 static void
 SDL_FS_CloseDevice(_THIS)
 SDL_FS_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->stream) {
-            this->hidden->stream->Release(this->hidden->stream);
-            this->hidden->stream = NULL;
-        }
-        if (this->hidden->fs) {
-            this->hidden->fs->Release(this->hidden->fs);
-            this->hidden->fs = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->stream) {
+        this->hidden->stream->Release(this->hidden->stream);
+    }
+    if (this->hidden->fs) {
+        this->hidden->fs->Release(this->hidden->fs);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 
 
@@ -200,7 +188,7 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Try for a closest match on audio format */
     /* Try for a closest match on audio format */
     for (test_format = SDL_FirstAudioFormat(this->spec.format);
     for (test_format = SDL_FirstAudioFormat(this->spec.format);
@@ -239,7 +227,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (format == 0) {
     if (format == 0) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
@@ -247,7 +234,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Retrieve the main sound interface. */
     /* Retrieve the main sound interface. */
     ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
     ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
     if (ret) {
     if (ret) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Unable to initialize FusionSound: %d", ret);
         return SDL_SetError("Unable to initialize FusionSound: %d", ret);
     }
     }
 
 
@@ -266,7 +252,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         this->hidden->fs->CreateStream(this->hidden->fs, &desc,
         this->hidden->fs->CreateStream(this->hidden->fs, &desc,
                                        &this->hidden->stream);
                                        &this->hidden->stream);
     if (ret) {
     if (ret) {
-        SDL_FS_CloseDevice(this);
         return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
         return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
     }
     }
 
 
@@ -285,9 +270,8 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        SDL_FS_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -328,7 +312,6 @@ SDL_FS_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice = SDL_FS_WaitDevice;
     impl->WaitDevice = SDL_FS_WaitDevice;
     impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
     impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
     impl->CloseDevice = SDL_FS_CloseDevice;
     impl->CloseDevice = SDL_FS_CloseDevice;
-    impl->WaitDone = SDL_FS_WaitDone;
     impl->Deinitialize = SDL_FS_Deinitialize;
     impl->Deinitialize = SDL_FS_Deinitialize;
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
 
 

+ 9 - 15
Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc

@@ -49,10 +49,11 @@ FillSound(void *device, void *stream, size_t len,
     SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
     SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
 
 
     /* Only do soemthing if audio is enabled */
     /* Only do soemthing if audio is enabled */
-    if (!audio->enabled)
+    if (!SDL_AtomicGet(&audio->enabled)) {
         return;
         return;
+    }
 
 
-    if (!audio->paused) {
+    if (!SDL_AtomicGet(&audio->paused)) {
         if (audio->convert.needed) {
         if (audio->convert.needed) {
             SDL_LockMutex(audio->mixer_lock);
             SDL_LockMutex(audio->mixer_lock);
             (*audio->spec.callback) (audio->spec.userdata,
             (*audio->spec.callback) (audio->spec.userdata,
@@ -73,16 +74,11 @@ FillSound(void *device, void *stream, size_t len,
 static void
 static void
 HAIKUAUDIO_CloseDevice(_THIS)
 HAIKUAUDIO_CloseDevice(_THIS)
 {
 {
-    if (_this->hidden != NULL) {
-        if (_this->hidden->audio_obj) {
-            _this->hidden->audio_obj->Stop();
-            delete _this->hidden->audio_obj;
-            _this->hidden->audio_obj = NULL;
-        }
-
-        delete _this->hidden;
-        _this->hidden = NULL;
+    if (_this->hidden->audio_obj) {
+        _this->hidden->audio_obj->Stop();
+        delete _this->hidden->audio_obj;
     }
     }
+    delete _this->hidden;
 }
 }
 
 
 
 
@@ -122,10 +118,10 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (_this->hidden == NULL) {
     if (_this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
+    SDL_zerop(_this->hidden);
 
 
     /* Parse the audio format and fill the Be raw audio format */
     /* Parse the audio format and fill the Be raw audio format */
-    SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
+    SDL_zero(format);
     format.byte_order = B_MEDIA_LITTLE_ENDIAN;
     format.byte_order = B_MEDIA_LITTLE_ENDIAN;
     format.frame_rate = (float) _this->spec.freq;
     format.frame_rate = (float) _this->spec.freq;
     format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
     format.channel_count = _this->spec.channels;        /* !!! FIXME: support > 2? */
@@ -176,7 +172,6 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
     if (!valid_datatype) {      /* shouldn't happen, but just in case... */
-        HAIKUAUDIO_CloseDevice(_this);
         return SDL_SetError("Unsupported audio format");
         return SDL_SetError("Unsupported audio format");
     }
     }
 
 
@@ -195,7 +190,6 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
     if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
         _this->hidden->audio_obj->SetHasData(true);
         _this->hidden->audio_obj->SetHasData(true);
     } else {
     } else {
-        HAIKUAUDIO_CloseDevice(_this);
         return SDL_SetError("Unable to start Be audio");
         return SDL_SetError("Unable to start Be audio");
     }
     }
 
 

+ 17 - 20
Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c

@@ -27,7 +27,6 @@
 
 
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "SDL_mutex.h"
 #include "SDL_mutex.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 
 
@@ -38,22 +37,20 @@
 #include "ppapi_simple/ps_event.h"
 #include "ppapi_simple/ps_event.h"
 
 
 /* The tag name used by NACL audio */
 /* The tag name used by NACL audio */
-#define NACLAUD_DRIVER_NAME         "nacl"
+#define NACLAUDIO_DRIVER_NAME         "nacl"
 
 
 #define SAMPLE_FRAME_COUNT 4096
 #define SAMPLE_FRAME_COUNT 4096
 
 
 /* Audio driver functions */
 /* Audio driver functions */
-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);
 static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
 
 
 /* FIXME: Make use of latency if needed */
 /* FIXME: Make use of latency if needed */
 static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
 static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
     SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
     SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
     
     
-    SDL_LockMutex(private->mutex);
+    SDL_LockMutex(private->mutex);  /* !!! FIXME: is this mutex necessary? */
 
 
-    if (_this->enabled && !_this->paused) {
+    if (SDL_AtomicGet(&_this->enabled) && !SDL_AtomicGet(&_this->paused)) {
         if (_this->convert.needed) {
         if (_this->convert.needed) {
             SDL_LockMutex(_this->mixer_lock);
             SDL_LockMutex(_this->mixer_lock);
             (*_this->spec.callback) (_this->spec.userdata,
             (*_this->spec.callback) (_this->spec.userdata,
@@ -68,13 +65,13 @@ static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelt
             SDL_UnlockMutex(_this->mixer_lock);
             SDL_UnlockMutex(_this->mixer_lock);
         }
         }
     } else {
     } else {
-        SDL_memset(samples, 0, buffer_size);
+        SDL_memset(samples, _this->spec.silence, buffer_size);
     }
     }
     
     
-    return;
+    SDL_UnlockMutex(private->mutex);
 }
 }
 
 
-static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
+static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
     const PPB_Core *core = PSInterfaceCore();
     const PPB_Core *core = PSInterfaceCore();
     const PPB_Audio *ppb_audio = PSInterfaceAudio();
     const PPB_Audio *ppb_audio = PSInterfaceAudio();
     SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
     SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
@@ -85,7 +82,7 @@ static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
 }
 }
 
 
 static int
 static int
-NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
+NACLAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
     PP_Instance instance = PSGetInstanceId();
     PP_Instance instance = PSGetInstanceId();
     const PPB_Audio *ppb_audio = PSInterfaceAudio();
     const PPB_Audio *ppb_audio = PSInterfaceAudio();
     const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
     const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
@@ -121,30 +118,30 @@ NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
 }
 }
 
 
 static int
 static int
-NACLAUD_Init(SDL_AudioDriverImpl * impl)
+NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
     if (PSGetInstanceId() == 0) {
     if (PSGetInstanceId() == 0) {
         return 0;
         return 0;
     }
     }
     
     
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = NACLAUD_OpenDevice;
-    impl->CloseDevice = NACLAUD_CloseDevice;
+    impl->OpenDevice = NACLAUDIO_OpenDevice;
+    impl->CloseDevice = NACLAUDIO_CloseDevice;
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->ProvidesOwnCallbackThread = 1;
     impl->ProvidesOwnCallbackThread = 1;
     /*
     /*
-     *    impl->WaitDevice = NACLAUD_WaitDevice;
-     *    impl->GetDeviceBuf = NACLAUD_GetDeviceBuf;
-     *    impl->PlayDevice = NACLAUD_PlayDevice;
-     *    impl->Deinitialize = NACLAUD_Deinitialize;
+     *    impl->WaitDevice = NACLAUDIO_WaitDevice;
+     *    impl->GetDeviceBuf = NACLAUDIO_GetDeviceBuf;
+     *    impl->PlayDevice = NACLAUDIO_PlayDevice;
+     *    impl->Deinitialize = NACLAUDIO_Deinitialize;
      */
      */
     
     
     return 1;
     return 1;
 }
 }
 
 
-AudioBootStrap NACLAUD_bootstrap = {
-    NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
-    NACLAUD_Init, 0
+AudioBootStrap NACLAUDIO_bootstrap = {
+    NACLAUDIO_DRIVER_NAME, "SDL NaCl Audio Driver",
+    NACLAUDIO_Init, 0
 };
 };
 
 
 #endif /* SDL_AUDIO_DRIVER_NACL */
 #endif /* SDL_AUDIO_DRIVER_NACL */

+ 116 - 50
Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c

@@ -30,22 +30,21 @@
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "SDL_loadso.h"
 #include "SDL_loadso.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_nasaudio.h"
 #include "SDL_nasaudio.h"
 
 
-static struct SDL_PrivateAudioData *this2 = NULL;
-
-
 static void (*NAS_AuCloseServer) (AuServer *);
 static void (*NAS_AuCloseServer) (AuServer *);
 static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
 static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
 static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
 static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
+static void (*NAS_AuHandleEvents) (AuServer *);
 static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
 static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
 static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
 static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
 static void (*NAS_AuSetElements)
 static void (*NAS_AuSetElements)
   (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
   (AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
 static void (*NAS_AuWriteElement)
 static void (*NAS_AuWriteElement)
   (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
   (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
+static AuUint32 (*NAS_AuReadElement)
+  (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuStatus *);
 static AuServer *(*NAS_AuOpenServer)
 static AuServer *(*NAS_AuOpenServer)
   (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
   (_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
 static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
 static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
@@ -80,10 +79,12 @@ load_nas_syms(void)
     SDL_NAS_SYM(AuCloseServer);
     SDL_NAS_SYM(AuCloseServer);
     SDL_NAS_SYM(AuNextEvent);
     SDL_NAS_SYM(AuNextEvent);
     SDL_NAS_SYM(AuDispatchEvent);
     SDL_NAS_SYM(AuDispatchEvent);
+    SDL_NAS_SYM(AuHandleEvents);
     SDL_NAS_SYM(AuCreateFlow);
     SDL_NAS_SYM(AuCreateFlow);
     SDL_NAS_SYM(AuStartFlow);
     SDL_NAS_SYM(AuStartFlow);
     SDL_NAS_SYM(AuSetElements);
     SDL_NAS_SYM(AuSetElements);
     SDL_NAS_SYM(AuWriteElement);
     SDL_NAS_SYM(AuWriteElement);
+    SDL_NAS_SYM(AuReadElement);
     SDL_NAS_SYM(AuOpenServer);
     SDL_NAS_SYM(AuOpenServer);
     SDL_NAS_SYM(AuRegisterEventHandler);
     SDL_NAS_SYM(AuRegisterEventHandler);
     return 0;
     return 0;
@@ -187,19 +188,53 @@ NAS_GetDeviceBuf(_THIS)
     return (this->hidden->mixbuf);
     return (this->hidden->mixbuf);
 }
 }
 
 
+static int
+NAS_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+    struct SDL_PrivateAudioData *h = this->hidden;
+    int retval;
+
+    while (SDL_TRUE) {
+        /* just keep the event queue moving and the server chattering. */
+        NAS_AuHandleEvents(h->aud);
+    
+        retval = (int) NAS_AuReadElement(h->aud, h->flow, 1, buflen, buffer, NULL);
+        /*printf("read %d capture bytes\n", (int) retval);*/
+        if (retval == 0) {
+            SDL_Delay(10);  /* don't burn the CPU if we're waiting for data. */
+        } else {
+            break;
+        }
+    }
+
+    return retval;
+}
+
+static void
+NAS_FlushCapture(_THIS)
+{
+    struct SDL_PrivateAudioData *h = this->hidden;
+    AuUint32 total = 0;
+    AuUint32 br;
+    Uint8 buf[512];
+
+    do {
+        /* just keep the event queue moving and the server chattering. */
+        NAS_AuHandleEvents(h->aud);
+        br = NAS_AuReadElement(h->aud, h->flow, 1, sizeof (buf), buf, NULL);
+        /*printf("flushed %d capture bytes\n", (int) br);*/
+        total += br;
+    } while ((br == sizeof (buf)) && (total < this->spec.size));
+}
+
 static void
 static void
 NAS_CloseDevice(_THIS)
 NAS_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->aud) {
-            NAS_AuCloseServer(this->hidden->aud);
-            this->hidden->aud = 0;
-        }
-        SDL_free(this->hidden);
-        this2 = this->hidden = NULL;
+    if (this->hidden->aud) {
+        NAS_AuCloseServer(this->hidden->aud);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static unsigned char
 static unsigned char
@@ -225,6 +260,12 @@ sdlformat_to_auformat(unsigned int fmt)
 static AuBool
 static AuBool
 event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
 event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
 {
 {
+    SDL_AudioDevice *this = (SDL_AudioDevice *) hnd->data;
+    struct SDL_PrivateAudioData *h = this->hidden;
+    if (this->iscapture) {
+        return AuTrue;  /* we don't (currently) care about any of this for capture devices */
+    }
+
     switch (ev->type) {
     switch (ev->type) {
     case AuEventTypeElementNotify:
     case AuEventTypeElementNotify:
         {
         {
@@ -232,24 +273,24 @@ event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
 
 
             switch (event->kind) {
             switch (event->kind) {
             case AuElementNotifyKindLowWater:
             case AuElementNotifyKindLowWater:
-                if (this2->buf_free >= 0) {
-                    this2->really += event->num_bytes;
-                    gettimeofday(&this2->last_tv, 0);
-                    this2->buf_free += event->num_bytes;
+                if (h->buf_free >= 0) {
+                    h->really += event->num_bytes;
+                    gettimeofday(&h->last_tv, 0);
+                    h->buf_free += event->num_bytes;
                 } else {
                 } else {
-                    this2->buf_free = event->num_bytes;
+                    h->buf_free = event->num_bytes;
                 }
                 }
                 break;
                 break;
             case AuElementNotifyKindState:
             case AuElementNotifyKindState:
                 switch (event->cur_state) {
                 switch (event->cur_state) {
                 case AuStatePause:
                 case AuStatePause:
                     if (event->reason != AuReasonUser) {
                     if (event->reason != AuReasonUser) {
-                        if (this2->buf_free >= 0) {
-                            this2->really += event->num_bytes;
-                            gettimeofday(&this2->last_tv, 0);
-                            this2->buf_free += event->num_bytes;
+                        if (h->buf_free >= 0) {
+                            h->really += event->num_bytes;
+                            gettimeofday(&h->last_tv, 0);
+                            h->buf_free += event->num_bytes;
                         } else {
                         } else {
-                            this2->buf_free = event->num_bytes;
+                            h->buf_free = event->num_bytes;
                         }
                         }
                     }
                     }
                     break;
                     break;
@@ -261,15 +302,29 @@ event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
 }
 }
 
 
 static AuDeviceID
 static AuDeviceID
-find_device(_THIS, int nch)
+find_device(_THIS)
 {
 {
     /* These "Au" things are all macros, not functions... */
     /* These "Au" things are all macros, not functions... */
+    struct SDL_PrivateAudioData *h = this->hidden;
+    const unsigned int devicekind = this->iscapture ? AuComponentKindPhysicalInput : AuComponentKindPhysicalOutput;
+    const int numdevs = AuServerNumDevices(h->aud);
+    const int nch = this->spec.channels;
     int i;
     int i;
-    for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
-        if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
-             AuComponentKindPhysicalOutput) &&
-            AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
-            return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
+
+    /* Try to find exact match on channels first... */
+    for (i = 0; i < numdevs; i++) {
+        const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
+        if ((AuDeviceKind(dev) == devicekind) && (AuDeviceNumTracks(dev) == nch)) {
+            return AuDeviceIdentifier(dev);
+        }
+    }
+
+    /* Take anything, then... */
+    for (i = 0; i < numdevs; i++) {
+        const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
+        if (AuDeviceKind(dev) == devicekind) {
+            this->spec.channels = AuDeviceNumTracks(dev);
+            return AuDeviceIdentifier(dev);
         }
         }
     }
     }
     return AuNone;
     return AuNone;
@@ -288,7 +343,7 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Try for a closest match on audio format */
     /* Try for a closest match on audio format */
     format = 0;
     format = 0;
@@ -300,21 +355,18 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         }
         }
     }
     }
     if (format == 0) {
     if (format == 0) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't find any hardware audio formats");
         return SDL_SetError("NAS: Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
 
 
     this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
     this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
     if (this->hidden->aud == 0) {
     if (this->hidden->aud == 0) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't open connection to NAS server");
         return SDL_SetError("NAS: Couldn't open connection to NAS server");
     }
     }
 
 
-    this->hidden->dev = find_device(this, this->spec.channels);
+    this->hidden->dev = find_device(this);
     if ((this->hidden->dev == AuNone)
     if ((this->hidden->dev == AuNone)
         || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
         || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
-        NAS_CloseDevice(this);
         return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
         return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
     }
     }
 
 
@@ -328,29 +380,38 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Calculate the final parameters for this audio specification */
     /* Calculate the final parameters for this audio specification */
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
-    this2 = this->hidden;
+    if (iscapture) {
+        AuMakeElementImportDevice(elms, this->spec.freq, this->hidden->dev,
+                                  AuUnlimitedSamples, 0, NULL);
+        AuMakeElementExportClient(elms + 1, 0, this->spec.freq, format,
+                                  this->spec.channels, AuTrue, buffer_size,
+                                  buffer_size, 0, NULL);
+    } else {
+        AuMakeElementImportClient(elms, this->spec.freq, format,
+                                  this->spec.channels, AuTrue, buffer_size,
+                                  buffer_size / 4, 0, NULL);
+        AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
+                                  AuUnlimitedSamples, 0, NULL);
+    }
+
+    NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue,
+                      2, elms, NULL);
 
 
-    AuMakeElementImportClient(elms, this->spec.freq, format,
-                              this->spec.channels, AuTrue, buffer_size,
-                              buffer_size / 4, 0, NULL);
-    AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
-                              AuUnlimitedSamples, 0, NULL);
-    NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
-                      NULL);
     NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
     NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
                                this->hidden->flow, event_handler,
                                this->hidden->flow, event_handler,
-                               (AuPointer) NULL);
+                               (AuPointer) this);
 
 
     NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
     NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
-    if (this->hidden->mixbuf == NULL) {
-        NAS_CloseDevice(this);
-        return SDL_OutOfMemory();
+    if (!iscapture) {
+        this->hidden->mixlen = this->spec.size;
+        this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+        if (this->hidden->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     }
     }
-    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
 
 
     /* We're ready to rock and roll. :-) */
     /* We're ready to rock and roll. :-) */
     return 0;
     return 0;
@@ -381,9 +442,14 @@ NAS_Init(SDL_AudioDriverImpl * impl)
     impl->PlayDevice = NAS_PlayDevice;
     impl->PlayDevice = NAS_PlayDevice;
     impl->WaitDevice = NAS_WaitDevice;
     impl->WaitDevice = NAS_WaitDevice;
     impl->GetDeviceBuf = NAS_GetDeviceBuf;
     impl->GetDeviceBuf = NAS_GetDeviceBuf;
+    impl->CaptureFromDevice = NAS_CaptureFromDevice;
+    impl->FlushCapture = NAS_FlushCapture;
     impl->CloseDevice = NAS_CloseDevice;
     impl->CloseDevice = NAS_CloseDevice;
     impl->Deinitialize = NAS_Deinitialize;
     impl->Deinitialize = NAS_Deinitialize;
-    impl->OnlyHasDefaultOutputDevice = 1;       /* !!! FIXME: is this true? */
+
+    impl->OnlyHasDefaultOutputDevice = 1;
+    impl->OnlyHasDefaultCaptureDevice = 1;
+    impl->HasCaptureSupport = SDL_TRUE;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }

+ 6 - 18
Engine/lib/sdl/src/audio/paudio/SDL_paudio.c

@@ -35,7 +35,6 @@
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "SDL_stdinc.h"
 #include "SDL_stdinc.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_paudio.h"
 #include "SDL_paudio.h"
 
 
@@ -228,16 +227,11 @@ PAUDIO_GetDeviceBuf(_THIS)
 static void
 static void
 PAUDIO_CloseDevice(_THIS)
 PAUDIO_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -262,13 +256,12 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
     fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
     fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
     this->hidden->audio_fd = fd;
     this->hidden->audio_fd = fd;
     if (fd < 0) {
     if (fd < 0) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
         return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
     }
     }
 
 
@@ -277,7 +270,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
      * that we can have.
      * that we can have.
      */
      */
     if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
     if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't get audio buffer information");
         return SDL_SetError("Couldn't get audio buffer information");
     }
     }
 
 
@@ -391,7 +383,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Couldn't find any hardware audio formats\n");
         fprintf(stderr, "Couldn't find any hardware audio formats\n");
 #endif
 #endif
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
@@ -449,15 +440,13 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (err != NULL) {
     if (err != NULL) {
-        PAUDIO_CloseDevice(this);
         return SDL_SetError("Paudio: %s", err);
         return SDL_SetError("Paudio: %s", err);
     }
     }
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        PAUDIO_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -492,7 +481,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     paud_control.ioctl_request = AUDIO_START;
     paud_control.ioctl_request = AUDIO_START;
     paud_control.position = 0;
     paud_control.position = 0;
     if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
     if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
-        PAUDIO_CloseDevice(this);
 #ifdef DEBUG_AUDIO
 #ifdef DEBUG_AUDIO
         fprintf(stderr, "Can't start audio play\n");
         fprintf(stderr, "Can't start audio play\n");
 #endif
 #endif

+ 22 - 41
Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c

@@ -30,7 +30,6 @@
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "SDL_error.h"
 #include "SDL_error.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_sysaudio.h"
 #include "../SDL_sysaudio.h"
@@ -40,10 +39,10 @@
 #include <pspthreadman.h>
 #include <pspthreadman.h>
 
 
 /* The tag name used by PSP audio */
 /* The tag name used by PSP audio */
-#define PSPAUD_DRIVER_NAME         "psp"
+#define PSPAUDIO_DRIVER_NAME         "psp"
 
 
 static int
 static int
-PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+PSPAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 {
 {
     int format, mixlen, i;
     int format, mixlen, i;
     this->hidden = (struct SDL_PrivateAudioData *)
     this->hidden = (struct SDL_PrivateAudioData *)
@@ -51,7 +50,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+    SDL_zerop(this->hidden);
     switch (this->spec.format & 0xff) {
     switch (this->spec.format & 0xff) {
         case 8:
         case 8:
         case 16:
         case 16:
@@ -66,20 +65,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     this->spec.freq = 44100;
     this->spec.freq = 44100;
 
 
     /* Update the fragment size as size in bytes. */
     /* Update the fragment size as size in bytes. */
-/*  SDL_CalculateAudioSpec(this->spec); MOD */
-    switch (this->spec.format) {
-    case AUDIO_U8:
-        this->spec.silence = 0x80;
-        break;
-    default:
-        this->spec.silence = 0x00;
-        break;
-    }
-    this->spec.size = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
-    this->spec.size *= this->spec.channels;
-    this->spec.size *= this->spec.samples;
-
-/* ========================================== */
+    SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Allocate the mixing buffer.  Its size and starting address must
     /* Allocate the mixing buffer.  Its size and starting address must
        be a multiple of 64 bytes.  Our sample count is already a multiple of
        be a multiple of 64 bytes.  Our sample count is already a multiple of
@@ -112,7 +98,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     return 0;
     return 0;
 }
 }
 
 
-static void PSPAUD_PlayDevice(_THIS)
+static void PSPAUDIO_PlayDevice(_THIS)
 {
 {
     Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
     Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
 
 
@@ -126,28 +112,25 @@ static void PSPAUD_PlayDevice(_THIS)
 }
 }
 
 
 /* This function waits until it is possible to write a full sound buffer */
 /* This function waits until it is possible to write a full sound buffer */
-static void PSPAUD_WaitDevice(_THIS)
+static void PSPAUDIO_WaitDevice(_THIS)
 {
 {
     /* Because we block when sending audio, there's no need for this function to do anything. */
     /* Because we block when sending audio, there's no need for this function to do anything. */
 }
 }
-static Uint8 *PSPAUD_GetDeviceBuf(_THIS)
+static Uint8 *PSPAUDIO_GetDeviceBuf(_THIS)
 {
 {
     return this->hidden->mixbufs[this->hidden->next_buffer];
     return this->hidden->mixbufs[this->hidden->next_buffer];
 }
 }
 
 
-static void PSPAUD_CloseDevice(_THIS)
+static void PSPAUDIO_CloseDevice(_THIS)
 {
 {
     if (this->hidden->channel >= 0) {
     if (this->hidden->channel >= 0) {
         sceAudioChRelease(this->hidden->channel);
         sceAudioChRelease(this->hidden->channel);
-        this->hidden->channel = -1;
-    }
-
-    if (this->hidden->rawbuf != NULL) {
-        free(this->hidden->rawbuf);
-        this->hidden->rawbuf = NULL;
     }
     }
+    free(this->hidden->rawbuf);  /* this uses memalign(), not SDL_malloc(). */
+    SDL_free(this->hidden);
 }
 }
-static void PSPAUD_ThreadInit(_THIS)
+
+static void PSPAUDIO_ThreadInit(_THIS)
 {
 {
     /* Increase the priority of this audio thread by 1 to put it
     /* Increase the priority of this audio thread by 1 to put it
        ahead of other SDL threads. */
        ahead of other SDL threads. */
@@ -162,24 +145,22 @@ static void PSPAUD_ThreadInit(_THIS)
 
 
 
 
 static int
 static int
-PSPAUD_Init(SDL_AudioDriverImpl * impl)
+PSPAUDIO_Init(SDL_AudioDriverImpl * impl)
 {
 {
-
     /* Set the function pointers */
     /* Set the function pointers */
-    impl->OpenDevice = PSPAUD_OpenDevice;
-    impl->PlayDevice = PSPAUD_PlayDevice;
-    impl->WaitDevice = PSPAUD_WaitDevice;
-    impl->GetDeviceBuf = PSPAUD_GetDeviceBuf;
-    impl->WaitDone = PSPAUD_WaitDevice;
-    impl->CloseDevice = PSPAUD_CloseDevice;
-    impl->ThreadInit = PSPAUD_ThreadInit;
+    impl->OpenDevice = PSPAUDIO_OpenDevice;
+    impl->PlayDevice = PSPAUDIO_PlayDevice;
+    impl->WaitDevice = PSPAUDIO_WaitDevice;
+    impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf;
+    impl->CloseDevice = PSPAUDIO_CloseDevice;
+    impl->ThreadInit = PSPAUDIO_ThreadInit;
 
 
     /* PSP audio device */
     /* PSP audio device */
     impl->OnlyHasDefaultOutputDevice = 1;
     impl->OnlyHasDefaultOutputDevice = 1;
 /*
 /*
     impl->HasCaptureSupport = 1;
     impl->HasCaptureSupport = 1;
 
 
-    impl->OnlyHasDefaultInputDevice = 1;
+    impl->OnlyHasDefaultCaptureDevice = 1;
 */
 */
     /*
     /*
     impl->DetectDevices = DSOUND_DetectDevices;
     impl->DetectDevices = DSOUND_DetectDevices;
@@ -188,8 +169,8 @@ PSPAUD_Init(SDL_AudioDriverImpl * impl)
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 
-AudioBootStrap PSPAUD_bootstrap = {
-    "psp", "PSP audio driver", PSPAUD_Init, 0
+AudioBootStrap PSPAUDIO_bootstrap = {
+    "psp", "PSP audio driver", PSPAUDIO_Init, 0
 };
 };
 
 
  /* SDL_AUDI */
  /* SDL_AUDI */

+ 132 - 59
Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c

@@ -42,10 +42,10 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_pulseaudio.h"
 #include "SDL_pulseaudio.h"
 #include "SDL_loadso.h"
 #include "SDL_loadso.h"
+#include "../../thread/SDL_systhread.h"
 
 
 #if (PA_API_VERSION < 12)
 #if (PA_API_VERSION < 12)
 /** Return non-zero if the passed state is one of the connected states */
 /** Return non-zero if the passed state is one of the connected states */
@@ -99,12 +99,19 @@ static pa_stream * (*PULSEAUDIO_pa_stream_new) (pa_context *, const char *,
     const pa_sample_spec *, const pa_channel_map *);
     const pa_sample_spec *, const pa_channel_map *);
 static int (*PULSEAUDIO_pa_stream_connect_playback) (pa_stream *, const char *,
 static int (*PULSEAUDIO_pa_stream_connect_playback) (pa_stream *, const char *,
     const pa_buffer_attr *, pa_stream_flags_t, pa_cvolume *, pa_stream *);
     const pa_buffer_attr *, pa_stream_flags_t, pa_cvolume *, pa_stream *);
+static int (*PULSEAUDIO_pa_stream_connect_record) (pa_stream *, const char *,
+    const pa_buffer_attr *, pa_stream_flags_t);
 static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state) (pa_stream *);
 static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state) (pa_stream *);
 static size_t (*PULSEAUDIO_pa_stream_writable_size) (pa_stream *);
 static size_t (*PULSEAUDIO_pa_stream_writable_size) (pa_stream *);
+static size_t (*PULSEAUDIO_pa_stream_readable_size) (pa_stream *);
 static int (*PULSEAUDIO_pa_stream_write) (pa_stream *, const void *, size_t,
 static int (*PULSEAUDIO_pa_stream_write) (pa_stream *, const void *, size_t,
     pa_free_cb_t, int64_t, pa_seek_mode_t);
     pa_free_cb_t, int64_t, pa_seek_mode_t);
 static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
 static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
     pa_stream_success_cb_t, void *);
     pa_stream_success_cb_t, void *);
+static int (*PULSEAUDIO_pa_stream_peek) (pa_stream *, const void **, size_t *);
+static int (*PULSEAUDIO_pa_stream_drop) (pa_stream *);
+static pa_operation * (*PULSEAUDIO_pa_stream_flush)	(pa_stream *,
+    pa_stream_success_cb_t, void *);
 static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
 static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
 static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
 static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
 
 
@@ -205,11 +212,16 @@ load_pulseaudio_syms(void)
     SDL_PULSEAUDIO_SYM(pa_context_unref);
     SDL_PULSEAUDIO_SYM(pa_context_unref);
     SDL_PULSEAUDIO_SYM(pa_stream_new);
     SDL_PULSEAUDIO_SYM(pa_stream_new);
     SDL_PULSEAUDIO_SYM(pa_stream_connect_playback);
     SDL_PULSEAUDIO_SYM(pa_stream_connect_playback);
+    SDL_PULSEAUDIO_SYM(pa_stream_connect_record);
     SDL_PULSEAUDIO_SYM(pa_stream_get_state);
     SDL_PULSEAUDIO_SYM(pa_stream_get_state);
     SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
     SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
+    SDL_PULSEAUDIO_SYM(pa_stream_readable_size);
     SDL_PULSEAUDIO_SYM(pa_stream_write);
     SDL_PULSEAUDIO_SYM(pa_stream_write);
     SDL_PULSEAUDIO_SYM(pa_stream_drain);
     SDL_PULSEAUDIO_SYM(pa_stream_drain);
     SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
     SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
+    SDL_PULSEAUDIO_SYM(pa_stream_peek);
+    SDL_PULSEAUDIO_SYM(pa_stream_drop);
+    SDL_PULSEAUDIO_SYM(pa_stream_flush);
     SDL_PULSEAUDIO_SYM(pa_stream_unref);
     SDL_PULSEAUDIO_SYM(pa_stream_unref);
     SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
     SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
     SDL_PULSEAUDIO_SYM(pa_strerror);
     SDL_PULSEAUDIO_SYM(pa_strerror);
@@ -238,6 +250,12 @@ getAppName(void)
     return "SDL Application";  /* oh well. */
     return "SDL Application";  /* oh well. */
 }
 }
 
 
+static void
+stream_operation_complete_no_op(pa_stream *s, int success, void *userdata)
+{
+    /* no-op for pa_stream_drain(), etc, to use for callback. */
+}
+
 static void
 static void
 WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
 WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
 {
 {
@@ -325,7 +343,7 @@ PULSEAUDIO_WaitDevice(_THIS)
 {
 {
     struct SDL_PrivateAudioData *h = this->hidden;
     struct SDL_PrivateAudioData *h = this->hidden;
 
 
-    while (this->enabled) {
+    while (SDL_AtomicGet(&this->enabled)) {
         if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
         if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
             PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
             PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
             PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
             PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
@@ -343,66 +361,110 @@ PULSEAUDIO_PlayDevice(_THIS)
 {
 {
     /* Write the audio data */
     /* Write the audio data */
     struct SDL_PrivateAudioData *h = this->hidden;
     struct SDL_PrivateAudioData *h = this->hidden;
-    if (this->enabled) {
+    if (SDL_AtomicGet(&this->enabled)) {
         if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
         if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
             SDL_OpenedAudioDeviceDisconnected(this);
             SDL_OpenedAudioDeviceDisconnected(this);
         }
         }
     }
     }
 }
 }
 
 
-static void
-stream_drain_complete(pa_stream *s, int success, void *userdata)
+static Uint8 *
+PULSEAUDIO_GetDeviceBuf(_THIS)
 {
 {
-    /* no-op for pa_stream_drain() to use for callback. */
+    return (this->hidden->mixbuf);
 }
 }
 
 
-static void
-PULSEAUDIO_WaitDone(_THIS)
+
+static int
+PULSEAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
 {
 {
-    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;
-                }
+    struct SDL_PrivateAudioData *h = this->hidden;
+    const void *data = NULL;
+    size_t nbytes = 0;
+
+    while (SDL_AtomicGet(&this->enabled)) {
+        if (h->capturebuf != NULL) {
+            const int cpy = SDL_min(buflen, h->capturelen);
+            SDL_memcpy(buffer, h->capturebuf, cpy);
+            /*printf("PULSEAUDIO: fed %d captured bytes\n", cpy);*/
+            h->capturebuf += cpy;
+            h->capturelen -= cpy;
+            if (h->capturelen == 0) {
+                h->capturebuf = NULL;
+                PULSEAUDIO_pa_stream_drop(h->stream);  /* done with this fragment. */
             }
             }
-            PULSEAUDIO_pa_operation_unref(o);
+            return cpy;  /* new data, return it. */
+        }
+
+        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 -1;  /* uhoh, pulse failed! */
+        }
+
+        if (PULSEAUDIO_pa_stream_readable_size(h->stream) == 0) {
+            continue;  /* no data available yet. */
+        }
+
+        /* a new fragment is available! */
+        PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
+        SDL_assert(nbytes > 0);
+        if (data == NULL) {  /* NULL==buffer had a hole. Ignore that. */
+            PULSEAUDIO_pa_stream_drop(h->stream);  /* drop this fragment. */
+        } else {
+            /* store this fragment's data, start feeding it to SDL. */
+            /*printf("PULSEAUDIO: captured %d new bytes\n", (int) nbytes);*/
+            h->capturebuf = (const Uint8 *) data;
+            h->capturelen = nbytes;
         }
         }
     }
     }
+
+    return -1;  /* not enabled? */
 }
 }
 
 
+static void
+PULSEAUDIO_FlushCapture(_THIS)
+{
+    struct SDL_PrivateAudioData *h = this->hidden;
 
 
+    if (h->capturebuf != NULL) {
+        PULSEAUDIO_pa_stream_drop(h->stream);
+        h->capturebuf = NULL;
+        h->capturelen = 0;
+    }
 
 
-static Uint8 *
-PULSEAUDIO_GetDeviceBuf(_THIS)
-{
-    return (this->hidden->mixbuf);
+    WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_stream_flush(h->stream, stream_operation_complete_no_op, NULL));
 }
 }
 
 
-
 static void
 static void
 PULSEAUDIO_CloseDevice(_THIS)
 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);
+    if (this->hidden->stream) {
+        if (this->hidden->capturebuf != NULL) {
+            PULSEAUDIO_pa_stream_drop(this->hidden->stream);
         }
         }
-        DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+        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->mixbuf);
+    SDL_free(this->hidden->device_name);
+    SDL_free(this->hidden);
 }
 }
 
 
 static void
 static void
-DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
+SinkDeviceNameCallback(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 void
+SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
 {
 {
     if (i) {
     if (i) {
         char **devname = (char **) data;
         char **devname = (char **) data;
@@ -411,7 +473,7 @@ DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data
 }
 }
 
 
 static SDL_bool
 static SDL_bool
-FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
+FindDeviceName(struct SDL_PrivateAudioData *h, const int iscapture, void *handle)
 {
 {
     const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
     const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
 
 
@@ -419,7 +481,16 @@ FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
         return SDL_TRUE;
         return SDL_TRUE;
     }
     }
 
 
-    WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name));
+    if (iscapture) {
+        WaitForPulseOperation(h->mainloop,
+            PULSEAUDIO_pa_context_get_source_info_by_index(h->context, idx,
+                SourceDeviceNameCallback, &h->device_name));
+    } else {
+        WaitForPulseOperation(h->mainloop,
+            PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx,
+                SinkDeviceNameCallback, &h->device_name));
+    }
+
     return (h->device_name != NULL);
     return (h->device_name != NULL);
 }
 }
 
 
@@ -433,15 +504,15 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     pa_channel_map pacmap;
     pa_channel_map pacmap;
     pa_stream_flags_t flags = 0;
     pa_stream_flags_t flags = 0;
     int state = 0;
     int state = 0;
+    int rc = 0;
 
 
     /* Initialize all variables that we clean on shutdown */
     /* Initialize all variables that we clean on shutdown */
-    this->hidden = (struct SDL_PrivateAudioData *)
+    h = this->hidden = (struct SDL_PrivateAudioData *)
         SDL_malloc((sizeof *this->hidden));
         SDL_malloc((sizeof *this->hidden));
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-    h = this->hidden;
+    SDL_zerop(this->hidden);
 
 
     paspec.format = PA_SAMPLE_INVALID;
     paspec.format = PA_SAMPLE_INVALID;
 
 
@@ -482,7 +553,6 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         }
         }
     }
     }
     if (paspec.format == PA_SAMPLE_INVALID) {
     if (paspec.format == PA_SAMPLE_INVALID) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Couldn't find any hardware audio formats");
         return SDL_SetError("Couldn't find any hardware audio formats");
     }
     }
     this->spec.format = test_format;
     this->spec.format = test_format;
@@ -494,13 +564,14 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    h->mixlen = this->spec.size;
-    h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen);
-    if (h->mixbuf == NULL) {
-        PULSEAUDIO_CloseDevice(this);
-        return SDL_OutOfMemory();
+    if (!iscapture) {
+        h->mixlen = this->spec.size;
+        h->mixbuf = (Uint8 *) SDL_malloc(h->mixlen);
+        if (h->mixbuf == NULL) {
+            return SDL_OutOfMemory();
+        }
+        SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
     }
     }
-    SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
 
 
     paspec.channels = this->spec.channels;
     paspec.channels = this->spec.channels;
     paspec.rate = this->spec.freq;
     paspec.rate = this->spec.freq;
@@ -522,13 +593,11 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 #endif
 #endif
 
 
     if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
     if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Could not connect to PulseAudio server");
         return SDL_SetError("Could not connect to PulseAudio server");
     }
     }
 
 
-    if (!FindDeviceName(h, handle)) {
-        PULSEAUDIO_CloseDevice(this);
-        return SDL_SetError("Requested PulseAudio sink missing?");
+    if (!FindDeviceName(h, iscapture, handle)) {
+        return SDL_SetError("Requested PulseAudio sink/source missing?");
     }
     }
 
 
     /* The SDL ALSA output hints us that we use Windows' channel mapping */
     /* The SDL ALSA output hints us that we use Windows' channel mapping */
@@ -544,7 +613,6 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         );
         );
 
 
     if (h->stream == NULL) {
     if (h->stream == NULL) {
-        PULSEAUDIO_CloseDevice(this);
         return SDL_SetError("Could not set up PulseAudio stream");
         return SDL_SetError("Could not set up PulseAudio stream");
     }
     }
 
 
@@ -554,20 +622,22 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         flags |= PA_STREAM_DONT_MOVE;
         flags |= PA_STREAM_DONT_MOVE;
     }
     }
 
 
-    if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags,
-            NULL, NULL) < 0) {
-        PULSEAUDIO_CloseDevice(this);
+    if (iscapture) {
+        rc = PULSEAUDIO_pa_stream_connect_record(h->stream, h->device_name, &paattr, flags);
+    } else {
+        rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL);
+    }
+
+    if (rc < 0) {
         return SDL_SetError("Could not connect PulseAudio stream");
         return SDL_SetError("Could not connect PulseAudio stream");
     }
     }
 
 
     do {
     do {
         if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
         if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
-            PULSEAUDIO_CloseDevice(this);
             return SDL_SetError("pa_mainloop_iterate() failed");
             return SDL_SetError("pa_mainloop_iterate() failed");
         }
         }
         state = PULSEAUDIO_pa_stream_get_state(h->stream);
         state = PULSEAUDIO_pa_stream_get_state(h->stream);
         if (!PA_STREAM_IS_GOOD(state)) {
         if (!PA_STREAM_IS_GOOD(state)) {
-            PULSEAUDIO_CloseDevice(this);
             return SDL_SetError("Could not connect PulseAudio stream");
             return SDL_SetError("Could not connect PulseAudio stream");
         }
         }
     } while (state != PA_STREAM_READY);
     } while (state != PA_STREAM_READY);
@@ -646,7 +716,7 @@ PULSEAUDIO_DetectDevices()
     WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, 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... */
     /* ok, we have a sane list, let's set up hotplug notifications now... */
-    hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL);
+    hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, NULL);
 }
 }
 
 
 static void
 static void
@@ -684,8 +754,11 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice = PULSEAUDIO_WaitDevice;
     impl->WaitDevice = PULSEAUDIO_WaitDevice;
     impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf;
     impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf;
     impl->CloseDevice = PULSEAUDIO_CloseDevice;
     impl->CloseDevice = PULSEAUDIO_CloseDevice;
-    impl->WaitDone = PULSEAUDIO_WaitDone;
     impl->Deinitialize = PULSEAUDIO_Deinitialize;
     impl->Deinitialize = PULSEAUDIO_Deinitialize;
+    impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice;
+    impl->FlushCapture = PULSEAUDIO_FlushCapture;
+
+    impl->HasCaptureSupport = SDL_TRUE;
 
 
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }

+ 3 - 0
Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h

@@ -42,6 +42,9 @@ struct SDL_PrivateAudioData
     /* Raw mixing buffer */
     /* Raw mixing buffer */
     Uint8 *mixbuf;
     Uint8 *mixbuf;
     int mixlen;
     int mixlen;
+
+    const Uint8 *capturebuf;
+    int capturelen;
 };
 };
 
 
 #endif /* _SDL_pulseaudio_h */
 #endif /* _SDL_pulseaudio_h */

+ 27 - 65
Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c

@@ -45,7 +45,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_qsa_audio.h"
 #include "SDL_qsa_audio.h"
 
 
@@ -138,8 +137,7 @@ QSA_ThreadInit(_THIS)
 static void
 static void
 QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
 QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
 {
 {
-    SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t));
-
+    SDL_zerop(cpars);
     cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
     cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
     cpars->mode = SND_PCM_MODE_BLOCK;
     cpars->mode = SND_PCM_MODE_BLOCK;
     cpars->start_mode = SND_PCM_START_DATA;
     cpars->start_mode = SND_PCM_START_DATA;
@@ -229,7 +227,7 @@ QSA_PlayDevice(_THIS)
     int towrite;
     int towrite;
     void *pcmbuffer;
     void *pcmbuffer;
 
 
-    if ((!this->enabled) || (!this->hidden)) {
+    if (!SDL_AtomicGet(&this->enabled) || !this->hidden) {
         return;
         return;
     }
     }
 
 
@@ -262,7 +260,7 @@ QSA_PlayDevice(_THIS)
                 continue;
                 continue;
             } else {
             } else {
                 if ((errno == EINVAL) || (errno == EIO)) {
                 if ((errno == EINVAL) || (errno == EIO)) {
-                    SDL_memset(&cstatus, 0, sizeof(cstatus));
+                    SDL_zero(cstatus);
                     if (!this->hidden->iscapture) {
                     if (!this->hidden->iscapture) {
                         cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                         cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                     } else {
                     } else {
@@ -305,7 +303,7 @@ QSA_PlayDevice(_THIS)
             towrite -= written;
             towrite -= written;
             pcmbuffer += written * this->spec.channels;
             pcmbuffer += written * this->spec.channels;
         }
         }
-    } while ((towrite > 0) && (this->enabled));
+    } while ((towrite > 0) && SDL_AtomicGet(&this->enabled));
 
 
     /* If we couldn't write, assume fatal error for now */
     /* If we couldn't write, assume fatal error for now */
     if (towrite != 0) {
     if (towrite != 0) {
@@ -322,27 +320,21 @@ QSA_GetDeviceBuf(_THIS)
 static void
 static void
 QSA_CloseDevice(_THIS)
 QSA_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        if (this->hidden->audio_handle != NULL) {
-            if (!this->hidden->iscapture) {
-                /* Finish playing available samples */
-                snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                     SND_PCM_CHANNEL_PLAYBACK);
-            } else {
-                /* Cancel unread samples during capture */
-                snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                     SND_PCM_CHANNEL_CAPTURE);
-            }
-            snd_pcm_close(this->hidden->audio_handle);
-            this->hidden->audio_handle = NULL;
+    if (this->hidden->audio_handle != NULL) {
+        if (!this->hidden->iscapture) {
+            /* Finish playing available samples */
+            snd_pcm_plugin_flush(this->hidden->audio_handle,
+                                 SND_PCM_CHANNEL_PLAYBACK);
+        } else {
+            /* Cancel unread samples during capture */
+            snd_pcm_plugin_flush(this->hidden->audio_handle,
+                                 SND_PCM_CHANNEL_CAPTURE);
         }
         }
-
-        SDL_FreeAudioMem(this->hidden->pcm_buf);
-        this->hidden->pcm_buf = NULL;
-
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+        snd_pcm_close(this->hidden->audio_handle);
     }
     }
+
+    SDL_free(this->hidden->pcm_buf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -365,13 +357,13 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));
+    SDL_zerop(this->hidden);
 
 
     /* Initialize channel transfer parameters to default */
     /* Initialize channel transfer parameters to default */
     QSA_InitAudioParams(&cparams);
     QSA_InitAudioParams(&cparams);
 
 
     /* Initialize channel direction: capture or playback */
     /* Initialize channel direction: capture or playback */
-    this->hidden->iscapture = iscapture;
+    this->hidden->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
 
 
     if (device != NULL) {
     if (device != NULL) {
         /* Open requested audio device */
         /* Open requested audio device */
@@ -391,7 +383,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Check if requested device is opened */
     /* Check if requested device is opened */
     if (status < 0) {
     if (status < 0) {
         this->hidden->audio_handle = NULL;
         this->hidden->audio_handle = NULL;
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_open", status);
         return QSA_SetError("snd_pcm_open", status);
     }
     }
 
 
@@ -401,7 +392,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
             snd_pcm_plugin_set_disable(this->hidden->audio_handle,
             snd_pcm_plugin_set_disable(this->hidden->audio_handle,
                                        PLUGIN_DISABLE_MMAP);
                                        PLUGIN_DISABLE_MMAP);
         if (status < 0) {
         if (status < 0) {
-            QSA_CloseDevice(this);
             return QSA_SetError("snd_pcm_plugin_set_disable", status);
             return QSA_SetError("snd_pcm_plugin_set_disable", status);
         }
         }
     }
     }
@@ -487,7 +477,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* assumes test_format not 0 on success */
     /* assumes test_format not 0 on success */
     if (test_format == 0) {
     if (test_format == 0) {
-        QSA_CloseDevice(this);
         return SDL_SetError("QSA: Couldn't find any hardware audio formats");
         return SDL_SetError("QSA: Couldn't find any hardware audio formats");
     }
     }
 
 
@@ -505,12 +494,11 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Setup the transfer parameters according to cparams */
     /* Setup the transfer parameters according to cparams */
     status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
     status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
     if (status < 0) {
     if (status < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_channel_params", status);
         return QSA_SetError("snd_pcm_channel_params", status);
     }
     }
 
 
     /* Make sure channel is setup right one last time */
     /* Make sure channel is setup right one last time */
-    SDL_memset(&csetup, 0, sizeof(csetup));
+    SDL_zero(csetup);
     if (!this->hidden->iscapture) {
     if (!this->hidden->iscapture) {
         csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
         csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
     } else {
     } else {
@@ -519,7 +507,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* Setup an audio channel */
     /* Setup an audio channel */
     if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
     if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
-        QSA_CloseDevice(this);
         return SDL_SetError("QSA: Unable to setup channel");
         return SDL_SetError("QSA: Unable to setup channel");
     }
     }
 
 
@@ -540,9 +527,8 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
      *  closest multiple)
      *  closest multiple)
      */
      */
     this->hidden->pcm_buf =
     this->hidden->pcm_buf =
-        (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
+        (Uint8 *) SDL_malloc(this->hidden->pcm_len);
     if (this->hidden->pcm_buf == NULL) {
     if (this->hidden->pcm_buf == NULL) {
-        QSA_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->pcm_buf, this->spec.silence,
     SDL_memset(this->hidden->pcm_buf, this->spec.silence,
@@ -560,7 +546,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (this->hidden->audio_fd < 0) {
     if (this->hidden->audio_fd < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_file_descriptor", status);
         return QSA_SetError("snd_pcm_file_descriptor", status);
     }
     }
 
 
@@ -578,7 +563,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (status < 0) {
     if (status < 0) {
-        QSA_CloseDevice(this);
         return QSA_SetError("snd_pcm_plugin_prepare", status);
         return QSA_SetError("snd_pcm_plugin_prepare", status);
     }
     }
 
 
@@ -724,32 +708,13 @@ QSA_DetectDevices(void)
     }
     }
 }
 }
 
 
-static void
-QSA_WaitDone(_THIS)
-{
-    if (!this->hidden->iscapture) {
-        if (this->hidden->audio_handle != NULL) {
-            /* Wait till last fragment is played and stop channel */
-            snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                 SND_PCM_CHANNEL_PLAYBACK);
-        }
-    } else {
-        if (this->hidden->audio_handle != NULL) {
-            /* Discard all unread data and stop channel */
-            snd_pcm_plugin_flush(this->hidden->audio_handle,
-                                 SND_PCM_CHANNEL_CAPTURE);
-        }
-    }
-}
-
 static void
 static void
 QSA_Deinitialize(void)
 QSA_Deinitialize(void)
 {
 {
     /* Clear devices array on shutdown */
     /* Clear devices array on shutdown */
-    SDL_memset(qsa_playback_device, 0x00,
-               sizeof(QSA_Device) * QSA_MAX_DEVICES);
-    SDL_memset(qsa_capture_device, 0x00,
-               sizeof(QSA_Device) * QSA_MAX_DEVICES);
+    /* !!! FIXME: we zero these on init...any reason to do it here? */
+    SDL_zero(qsa_playback_device);
+    SDL_zero(qsa_capture_device);
     qsa_playback_devices = 0;
     qsa_playback_devices = 0;
     qsa_capture_devices = 0;
     qsa_capture_devices = 0;
 }
 }
@@ -761,10 +726,8 @@ QSA_Init(SDL_AudioDriverImpl * impl)
     int32_t status = 0;
     int32_t status = 0;
 
 
     /* Clear devices array */
     /* Clear devices array */
-    SDL_memset(qsa_playback_device, 0x00,
-               sizeof(QSA_Device) * QSA_MAX_DEVICES);
-    SDL_memset(qsa_capture_device, 0x00,
-               sizeof(QSA_Device) * QSA_MAX_DEVICES);
+    SDL_zero(qsa_playback_device);
+    SDL_zero(qsa_capture_device);
     qsa_playback_devices = 0;
     qsa_playback_devices = 0;
     qsa_capture_devices = 0;
     qsa_capture_devices = 0;
 
 
@@ -778,7 +741,6 @@ QSA_Init(SDL_AudioDriverImpl * impl)
     impl->PlayDevice = QSA_PlayDevice;
     impl->PlayDevice = QSA_PlayDevice;
     impl->GetDeviceBuf = QSA_GetDeviceBuf;
     impl->GetDeviceBuf = QSA_GetDeviceBuf;
     impl->CloseDevice = QSA_CloseDevice;
     impl->CloseDevice = QSA_CloseDevice;
-    impl->WaitDone = QSA_WaitDone;
     impl->Deinitialize = QSA_Deinitialize;
     impl->Deinitialize = QSA_Deinitialize;
     impl->LockDevice = NULL;
     impl->LockDevice = NULL;
     impl->UnlockDevice = NULL;
     impl->UnlockDevice = NULL;
@@ -788,7 +750,7 @@ QSA_Init(SDL_AudioDriverImpl * impl)
     impl->SkipMixerLock = 0;
     impl->SkipMixerLock = 0;
     impl->HasCaptureSupport = 1;
     impl->HasCaptureSupport = 1;
     impl->OnlyHasDefaultOutputDevice = 0;
     impl->OnlyHasDefaultOutputDevice = 0;
-    impl->OnlyHasDefaultInputDevice = 0;
+    impl->OnlyHasDefaultCaptureDevice = 0;
 
 
     /* Check if io-audio manager is running or not */
     /* Check if io-audio manager is running or not */
     status = snd_cards();
     status = snd_cards();

+ 1 - 1
Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h

@@ -34,7 +34,7 @@
 struct SDL_PrivateAudioData
 struct SDL_PrivateAudioData
 {
 {
     /* SDL capture state */
     /* SDL capture state */
-    int iscapture;
+    SDL_bool iscapture;
 
 
     /* The audio device handle */
     /* The audio device handle */
     int cardno;
     int cardno;

+ 7 - 24
Engine/lib/sdl/src/audio/sdlgenaudiocvt.pl

@@ -36,7 +36,6 @@
 #include <unistd.h>
 #include <unistd.h>
 
 
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "SDL_sndioaudio.h"
 #include "SDL_sndioaudio.h"
 
 
@@ -171,25 +170,15 @@ SNDIO_GetDeviceBuf(_THIS)
     return this->hidden->mixbuf;
     return this->hidden->mixbuf;
 }
 }
 
 
-static void
-SNDIO_WaitDone(_THIS)
-{
-    SNDIO_sio_stop(this->hidden->dev);
-}
-
 static void
 static void
 SNDIO_CloseDevice(_THIS)
 SNDIO_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        if ( this->hidden->dev != NULL ) {
-            SNDIO_sio_close(this->hidden->dev);
-            this->hidden->dev = NULL;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if ( this->hidden->dev != NULL ) {
+        SNDIO_sio_stop(this->hidden->dev);
+        SNDIO_sio_close(this->hidden->dev);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -204,13 +193,12 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+    SDL_zerop(this->hidden);
 
 
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
 
 
     /* !!! FIXME: SIO_DEVANY can be a specific device... */
     /* !!! FIXME: SIO_DEVANY can be a specific device... */
     if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
     if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sio_open() failed");
         return SDL_SetError("sio_open() failed");
     }
     }
 
 
@@ -233,7 +221,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
                 continue;
                 continue;
             }
             }
             if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
             if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
-                SNDIO_CloseDevice(this);
                 return SDL_SetError("sio_getpar() failed");
                 return SDL_SetError("sio_getpar() failed");
             }
             }
             if (par.bps != SIO_BPS(par.bits)) {
             if (par.bps != SIO_BPS(par.bits)) {
@@ -248,7 +235,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (status < 0) {
     if (status < 0) {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sndio: Couldn't find any hardware audio formats");
         return SDL_SetError("sndio: Couldn't find any hardware audio formats");
     }
     }
 
 
@@ -269,7 +255,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     else if ((par.bps == 1) && (!par.sig))
     else if ((par.bps == 1) && (!par.sig))
         this->spec.format = AUDIO_U8;
         this->spec.format = AUDIO_U8;
     else {
     else {
-        SNDIO_CloseDevice(this);
         return SDL_SetError("sndio: Got unsupported hardware audio format.");
         return SDL_SetError("sndio: Got unsupported hardware audio format.");
     }
     }
 
 
@@ -282,9 +267,8 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        SNDIO_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
     SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
@@ -315,7 +299,6 @@ SNDIO_Init(SDL_AudioDriverImpl * impl)
     impl->WaitDevice = SNDIO_WaitDevice;
     impl->WaitDevice = SNDIO_WaitDevice;
     impl->PlayDevice = SNDIO_PlayDevice;
     impl->PlayDevice = SNDIO_PlayDevice;
     impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
     impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
-    impl->WaitDone = SNDIO_WaitDone;
     impl->CloseDevice = SNDIO_CloseDevice;
     impl->CloseDevice = SNDIO_CloseDevice;
     impl->Deinitialize = SNDIO_Deinitialize;
     impl->Deinitialize = SNDIO_Deinitialize;
     impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: sndio can handle multiple devices. */
     impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: sndio can handle multiple devices. */

+ 7 - 14
Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c

@@ -40,7 +40,6 @@
 
 
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
-#include "../SDL_audiomem.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audiodev_c.h"
 #include "../SDL_audiodev_c.h"
 #include "SDL_sunaudio.h"
 #include "SDL_sunaudio.h"
@@ -183,18 +182,12 @@ SUNAUDIO_GetDeviceBuf(_THIS)
 static void
 static void
 SUNAUDIO_CloseDevice(_THIS)
 SUNAUDIO_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        SDL_FreeAudioMem(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
-        SDL_free(this->hidden->ulaw_buf);
-        this->hidden->ulaw_buf = NULL;
-        if (this->hidden->audio_fd >= 0) {
-            close(this->hidden->audio_fd);
-            this->hidden->audio_fd = -1;
-        }
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    SDL_free(this->hidden->ulaw_buf);
+    if (this->hidden->audio_fd >= 0) {
+        close(this->hidden->audio_fd);
     }
     }
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -219,7 +212,7 @@ SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Open the audio device */
     /* Open the audio device */
     this->hidden->audio_fd = open(devname, flags, 0);
     this->hidden->audio_fd = open(devname, flags, 0);
@@ -340,7 +333,7 @@ SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_CalculateAudioSpec(&this->spec);
     SDL_CalculateAudioSpec(&this->spec);
 
 
     /* Allocate mixing buffer */
     /* Allocate mixing buffer */
-    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size);
+    this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }

+ 121 - 63
Engine/lib/sdl/src/audio/winmm/SDL_winmm.c

@@ -27,6 +27,7 @@
 #include "../../core/windows/SDL_windows.h"
 #include "../../core/windows/SDL_windows.h"
 #include <mmsystem.h>
 #include <mmsystem.h>
 
 
+#include "SDL_assert.h"
 #include "SDL_timer.h"
 #include "SDL_timer.h"
 #include "SDL_audio.h"
 #include "SDL_audio.h"
 #include "../SDL_audio_c.h"
 #include "../SDL_audio_c.h"
@@ -40,11 +41,11 @@
 static void DetectWave##typ##Devs(void) { \
 static void DetectWave##typ##Devs(void) { \
     const UINT iscapture = iscap ? 1 : 0; \
     const UINT iscapture = iscap ? 1 : 0; \
     const UINT devcount = wave##typ##GetNumDevs(); \
     const UINT devcount = wave##typ##GetNumDevs(); \
-    capstyp caps; \
+    capstyp##2W caps; \
     UINT i; \
     UINT i; \
     for (i = 0; i < devcount; i++) { \
     for (i = 0; i < devcount; i++) { \
-        if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
-            char *name = WIN_StringToUTF8(caps.szPname); \
+	if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
+            char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
             if (name != NULL) { \
             if (name != NULL) { \
                 SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
                 SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
                 SDL_free(name); \
                 SDL_free(name); \
@@ -134,63 +135,87 @@ WINMM_PlayDevice(_THIS)
     this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
     this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
 }
 }
 
 
-static void
-WINMM_WaitDone(_THIS)
+static int
+WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen)
 {
 {
-    int i, left;
+    const int nextbuf = this->hidden->next_buffer;
+    MMRESULT result;
 
 
-    do {
-        left = NUM_BUFFERS;
-        for (i = 0; i < NUM_BUFFERS; ++i) {
-            if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
-                --left;
-            }
-        }
-        if (left > 0) {
-            SDL_Delay(100);
-        }
-    } while (left > 0);
+    SDL_assert(buflen == this->spec.size);
+
+    /* Wait for an audio chunk to finish */
+    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
+
+    /* Copy it to caller's buffer... */
+    SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
+
+    /* requeue the buffer that just finished. */
+    result = waveInAddBuffer(this->hidden->hin,
+                             &this->hidden->wavebuf[nextbuf],
+                             sizeof (this->hidden->wavebuf[nextbuf]));
+    if (result != MMSYSERR_NOERROR) {
+        return -1;  /* uhoh! Disable the device. */
+    }
+
+    /* queue the next buffer in sequence, next time. */
+    this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
+    return this->spec.size;
+}
+
+static void
+WINMM_FlushCapture(_THIS)
+{
+    /* Wait for an audio chunk to finish */
+    if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
+        const int nextbuf = this->hidden->next_buffer;
+        /* requeue the buffer that just finished without reading from it. */
+        waveInAddBuffer(this->hidden->hin,
+                        &this->hidden->wavebuf[nextbuf],
+                        sizeof (this->hidden->wavebuf[nextbuf]));
+        this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
+    }
 }
 }
 
 
 static void
 static void
 WINMM_CloseDevice(_THIS)
 WINMM_CloseDevice(_THIS)
 {
 {
-    /* Close up audio */
-    if (this->hidden != NULL) {
-        int i;
+    int i;
 
 
-        if (this->hidden->audio_sem) {
-            CloseHandle(this->hidden->audio_sem);
-            this->hidden->audio_sem = 0;
-        }
+    if (this->hidden->hout) {
+        waveOutReset(this->hidden->hout);
 
 
         /* Clean up mixing buffers */
         /* Clean up mixing buffers */
         for (i = 0; i < NUM_BUFFERS; ++i) {
         for (i = 0; i < NUM_BUFFERS; ++i) {
             if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
             if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
                 waveOutUnprepareHeader(this->hidden->hout,
                 waveOutUnprepareHeader(this->hidden->hout,
                                        &this->hidden->wavebuf[i],
                                        &this->hidden->wavebuf[i],
-                                       sizeof(this->hidden->wavebuf[i]));
-                this->hidden->wavebuf[i].dwUser = 0xFFFF;
+                                       sizeof (this->hidden->wavebuf[i]));
             }
             }
         }
         }
 
 
-        /* Free raw mixing buffer */
-        SDL_free(this->hidden->mixbuf);
-        this->hidden->mixbuf = NULL;
+        waveOutClose(this->hidden->hout);
+    }
 
 
-        if (this->hidden->hin) {
-            waveInClose(this->hidden->hin);
-            this->hidden->hin = 0;
-        }
+    if (this->hidden->hin) {
+        waveInReset(this->hidden->hin);
 
 
-        if (this->hidden->hout) {
-            waveOutClose(this->hidden->hout);
-            this->hidden->hout = 0;
+        /* Clean up mixing buffers */
+        for (i = 0; i < NUM_BUFFERS; ++i) {
+            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
+                waveInUnprepareHeader(this->hidden->hin,
+                                       &this->hidden->wavebuf[i],
+                                       sizeof (this->hidden->wavebuf[i]));
+            }
         }
         }
+        waveInClose(this->hidden->hin);
+    }
 
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (this->hidden->audio_sem) {
+        CloseHandle(this->hidden->audio_sem);
     }
     }
+
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static SDL_bool
 static SDL_bool
@@ -239,7 +264,7 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     if (this->hidden == NULL) {
     if (this->hidden == NULL) {
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     /* Initialize the wavebuf structures for closing */
     /* Initialize the wavebuf structures for closing */
     for (i = 0; i < NUM_BUFFERS; ++i)
     for (i = 0; i < NUM_BUFFERS; ++i)
@@ -269,7 +294,6 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!valid_datatype) {
     if (!valid_datatype) {
-        WINMM_CloseDevice(this);
         return SDL_SetError("Unsupported audio format");
         return SDL_SetError("Unsupported audio format");
     }
     }
 
 
@@ -281,36 +305,45 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         result = waveInOpen(&this->hidden->hin, devId, &waveformat,
         result = waveInOpen(&this->hidden->hin, devId, &waveformat,
                              (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
                              (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
                              CALLBACK_FUNCTION);
                              CALLBACK_FUNCTION);
+        if (result != MMSYSERR_NOERROR) {
+            return SetMMerror("waveInOpen()", result);
+        }
     } else {
     } else {
         result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
         result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
                              (DWORD_PTR) FillSound, (DWORD_PTR) this,
                              (DWORD_PTR) FillSound, (DWORD_PTR) this,
                              CALLBACK_FUNCTION);
                              CALLBACK_FUNCTION);
+        if (result != MMSYSERR_NOERROR) {
+            return SetMMerror("waveOutOpen()", result);
+        }
     }
     }
 
 
-    if (result != MMSYSERR_NOERROR) {
-        WINMM_CloseDevice(this);
-        return SetMMerror("waveOutOpen()", result);
-    }
 #ifdef SOUND_DEBUG
 #ifdef SOUND_DEBUG
     /* Check the sound device we retrieved */
     /* Check the sound device we retrieved */
     {
     {
-        WAVEOUTCAPS caps;
-
-        result = waveOutGetDevCaps((UINT) this->hidden->hout,
-                                   &caps, sizeof(caps));
-        if (result != MMSYSERR_NOERROR) {
-            WINMM_CloseDevice(this);
-            return SetMMerror("waveOutGetDevCaps()", result);
+        if (iscapture) {
+            WAVEINCAPS caps;
+            result = waveInGetDevCaps((UINT) this->hidden->hout,
+                                      &caps, sizeof (caps));
+            if (result != MMSYSERR_NOERROR) {
+                return SetMMerror("waveInGetDevCaps()", result);
+            }
+            printf("Audio device: %s\n", caps.szPname);
+        } else {
+            WAVEOUTCAPS caps;
+            result = waveOutGetDevCaps((UINT) this->hidden->hout,
+                                       &caps, sizeof(caps));
+            if (result != MMSYSERR_NOERROR) {
+                return SetMMerror("waveOutGetDevCaps()", result);
+            }
+            printf("Audio device: %s\n", caps.szPname);
         }
         }
-        printf("Audio device: %s\n", caps.szPname);
     }
     }
 #endif
 #endif
 
 
     /* Create the audio buffer semaphore */
     /* Create the audio buffer semaphore */
     this->hidden->audio_sem =
     this->hidden->audio_sem =
-        CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+		CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
     if (this->hidden->audio_sem == NULL) {
     if (this->hidden->audio_sem == NULL) {
-        WINMM_CloseDevice(this);
         return SDL_SetError("Couldn't create semaphore");
         return SDL_SetError("Couldn't create semaphore");
     }
     }
 
 
@@ -318,22 +351,44 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     this->hidden->mixbuf =
     this->hidden->mixbuf =
         (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
         (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        WINMM_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
+
+    SDL_zero(this->hidden->wavebuf);
     for (i = 0; i < NUM_BUFFERS; ++i) {
     for (i = 0; i < NUM_BUFFERS; ++i) {
-        SDL_memset(&this->hidden->wavebuf[i], 0,
-                   sizeof(this->hidden->wavebuf[i]));
         this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
         this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
         this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
         this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
         this->hidden->wavebuf[i].lpData =
         this->hidden->wavebuf[i].lpData =
             (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
             (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
-        result = waveOutPrepareHeader(this->hidden->hout,
-                                      &this->hidden->wavebuf[i],
-                                      sizeof(this->hidden->wavebuf[i]));
+
+        if (iscapture) {
+            result = waveInPrepareHeader(this->hidden->hin,
+                                          &this->hidden->wavebuf[i],
+                                          sizeof(this->hidden->wavebuf[i]));
+            if (result != MMSYSERR_NOERROR) {
+                return SetMMerror("waveInPrepareHeader()", result);
+            }
+
+            result = waveInAddBuffer(this->hidden->hin,
+                                     &this->hidden->wavebuf[i],
+                                     sizeof(this->hidden->wavebuf[i]));
+            if (result != MMSYSERR_NOERROR) {
+                return SetMMerror("waveInAddBuffer()", result);
+            }
+        } else {
+            result = waveOutPrepareHeader(this->hidden->hout,
+                                          &this->hidden->wavebuf[i],
+                                          sizeof(this->hidden->wavebuf[i]));
+            if (result != MMSYSERR_NOERROR) {
+                return SetMMerror("waveOutPrepareHeader()", result);
+            }
+        }
+    }
+
+    if (iscapture) {
+        result = waveInStart(this->hidden->hin);
         if (result != MMSYSERR_NOERROR) {
         if (result != MMSYSERR_NOERROR) {
-            WINMM_CloseDevice(this);
-            return SetMMerror("waveOutPrepareHeader()", result);
+            return SetMMerror("waveInStart()", result);
         }
         }
     }
     }
 
 
@@ -349,10 +404,13 @@ WINMM_Init(SDL_AudioDriverImpl * impl)
     impl->OpenDevice = WINMM_OpenDevice;
     impl->OpenDevice = WINMM_OpenDevice;
     impl->PlayDevice = WINMM_PlayDevice;
     impl->PlayDevice = WINMM_PlayDevice;
     impl->WaitDevice = WINMM_WaitDevice;
     impl->WaitDevice = WINMM_WaitDevice;
-    impl->WaitDone = WINMM_WaitDone;
     impl->GetDeviceBuf = WINMM_GetDeviceBuf;
     impl->GetDeviceBuf = WINMM_GetDeviceBuf;
+    impl->CaptureFromDevice = WINMM_CaptureFromDevice;
+    impl->FlushCapture = WINMM_FlushCapture;
     impl->CloseDevice = WINMM_CloseDevice;
     impl->CloseDevice = WINMM_CloseDevice;
 
 
+    impl->HasCaptureSupport = SDL_TRUE;
+
     return 1;   /* this audio target is available. */
     return 1;   /* this audio target is available. */
 }
 }
 
 

+ 30 - 54
Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c

@@ -195,7 +195,7 @@ XAUDIO2_PlayDevice(_THIS)
     IXAudio2SourceVoice *source = this->hidden->source;
     IXAudio2SourceVoice *source = this->hidden->source;
     HRESULT result = S_OK;
     HRESULT result = S_OK;
 
 
-    if (!this->enabled) { /* shutting down? */
+    if (!SDL_AtomicGet(&this->enabled)) { /* shutting down? */
         return;
         return;
     }
     }
 
 
@@ -226,64 +226,47 @@ XAUDIO2_PlayDevice(_THIS)
 static void
 static void
 XAUDIO2_WaitDevice(_THIS)
 XAUDIO2_WaitDevice(_THIS)
 {
 {
-    if (this->enabled) {
+    if (SDL_AtomicGet(&this->enabled)) {
         SDL_SemWait(this->hidden->semaphore);
         SDL_SemWait(this->hidden->semaphore);
     }
     }
 }
 }
 
 
 static void
 static void
-XAUDIO2_WaitDone(_THIS)
+XAUDIO2_PrepareToClose(_THIS)
 {
 {
     IXAudio2SourceVoice *source = this->hidden->source;
     IXAudio2SourceVoice *source = this->hidden->source;
-    XAUDIO2_VOICE_STATE state;
-    SDL_assert(!this->enabled);  /* flag that stops playing. */
-    IXAudio2SourceVoice_Discontinuity(source);
-#if SDL_XAUDIO2_WIN8
-    IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
-#else
-    IXAudio2SourceVoice_GetState(source, &state);
-#endif
-    while (state.BuffersQueued > 0) {
-        SDL_SemWait(this->hidden->semaphore);
-#if SDL_XAUDIO2_WIN8
-        IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
-#else
-        IXAudio2SourceVoice_GetState(source, &state);
-#endif
+    if (source) {
+        IXAudio2SourceVoice_Discontinuity(source);
     }
     }
 }
 }
 
 
-
 static void
 static void
 XAUDIO2_CloseDevice(_THIS)
 XAUDIO2_CloseDevice(_THIS)
 {
 {
-    if (this->hidden != NULL) {
-        IXAudio2 *ixa2 = this->hidden->ixa2;
-        IXAudio2SourceVoice *source = this->hidden->source;
-        IXAudio2MasteringVoice *mastering = this->hidden->mastering;
-
-        if (source != NULL) {
-            IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
-            IXAudio2SourceVoice_FlushSourceBuffers(source);
-            IXAudio2SourceVoice_DestroyVoice(source);
-        }
-        if (ixa2 != NULL) {
-            IXAudio2_StopEngine(ixa2);
-        }
-        if (mastering != NULL) {
-            IXAudio2MasteringVoice_DestroyVoice(mastering);
-        }
-        if (ixa2 != NULL) {
-            IXAudio2_Release(ixa2);
-        }
-        SDL_free(this->hidden->mixbuf);
-        if (this->hidden->semaphore != NULL) {
-            SDL_DestroySemaphore(this->hidden->semaphore);
-        }
+    IXAudio2 *ixa2 = this->hidden->ixa2;
+    IXAudio2SourceVoice *source = this->hidden->source;
+    IXAudio2MasteringVoice *mastering = this->hidden->mastering;
 
 
-        SDL_free(this->hidden);
-        this->hidden = NULL;
+    if (source != NULL) {
+        IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
+        IXAudio2SourceVoice_FlushSourceBuffers(source);
+        IXAudio2SourceVoice_DestroyVoice(source);
+    }
+    if (ixa2 != NULL) {
+        IXAudio2_StopEngine(ixa2);
     }
     }
+    if (mastering != NULL) {
+        IXAudio2MasteringVoice_DestroyVoice(mastering);
+    }
+    if (ixa2 != NULL) {
+        IXAudio2_Release(ixa2);
+    }
+    if (this->hidden->semaphore != NULL) {
+        SDL_DestroySemaphore(this->hidden->semaphore);
+    }
+
+    SDL_free(this->hidden->mixbuf);
+    SDL_free(this->hidden);
 }
 }
 
 
 static int
 static int
@@ -345,12 +328,11 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
         IXAudio2_Release(ixa2);
         IXAudio2_Release(ixa2);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+    SDL_zerop(this->hidden);
 
 
     this->hidden->ixa2 = ixa2;
     this->hidden->ixa2 = ixa2;
     this->hidden->semaphore = SDL_CreateSemaphore(1);
     this->hidden->semaphore = SDL_CreateSemaphore(1);
     if (this->hidden->semaphore == NULL) {
     if (this->hidden->semaphore == NULL) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: CreateSemaphore() failed!");
         return SDL_SetError("XAudio2: CreateSemaphore() failed!");
     }
     }
 
 
@@ -368,7 +350,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     }
     }
 
 
     if (!valid_format) {
     if (!valid_format) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Unsupported audio format");
         return SDL_SetError("XAudio2: Unsupported audio format");
     }
     }
 
 
@@ -379,11 +360,10 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixlen = this->spec.size;
     this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
     this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
     if (this->hidden->mixbuf == NULL) {
     if (this->hidden->mixbuf == NULL) {
-        XAUDIO2_CloseDevice(this);
         return SDL_OutOfMemory();
         return SDL_OutOfMemory();
     }
     }
     this->hidden->nextbuf = this->hidden->mixbuf;
     this->hidden->nextbuf = this->hidden->mixbuf;
-    SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen);
+    SDL_memset(this->hidden->mixbuf, this->spec.silence, 2 * this->hidden->mixlen);
 
 
     /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On
     /* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On
        Xbox360, this means 5.1 output, but on Windows, it means "figure out
        Xbox360, this means 5.1 output, but on Windows, it means "figure out
@@ -401,7 +381,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
                                            this->spec.freq, 0, devId, NULL);
                                            this->spec.freq, 0, devId, NULL);
 #endif
 #endif
     if (result != S_OK) {
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't create mastering voice");
         return SDL_SetError("XAudio2: Couldn't create mastering voice");
     }
     }
 
 
@@ -436,7 +415,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
 
 
 #endif
 #endif
     if (result != S_OK) {
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't create source voice");
         return SDL_SetError("XAudio2: Couldn't create source voice");
     }
     }
     this->hidden->source = source;
     this->hidden->source = source;
@@ -444,13 +422,11 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     /* Start everything playing! */
     /* Start everything playing! */
     result = IXAudio2_StartEngine(ixa2);
     result = IXAudio2_StartEngine(ixa2);
     if (result != S_OK) {
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't start engine");
         return SDL_SetError("XAudio2: Couldn't start engine");
     }
     }
 
 
     result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
     result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
     if (result != S_OK) {
     if (result != S_OK) {
-        XAUDIO2_CloseDevice(this);
         return SDL_SetError("XAudio2: Couldn't start source voice");
         return SDL_SetError("XAudio2: Couldn't start source voice");
     }
     }
 
 
@@ -499,7 +475,7 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
     impl->OpenDevice = XAUDIO2_OpenDevice;
     impl->OpenDevice = XAUDIO2_OpenDevice;
     impl->PlayDevice = XAUDIO2_PlayDevice;
     impl->PlayDevice = XAUDIO2_PlayDevice;
     impl->WaitDevice = XAUDIO2_WaitDevice;
     impl->WaitDevice = XAUDIO2_WaitDevice;
-    impl->WaitDone = XAUDIO2_WaitDone;
+    impl->PrepareToClose = XAUDIO2_PrepareToClose;
     impl->GetDeviceBuf = XAUDIO2_GetDeviceBuf;
     impl->GetDeviceBuf = XAUDIO2_GetDeviceBuf;
     impl->CloseDevice = XAUDIO2_CloseDevice;
     impl->CloseDevice = XAUDIO2_CloseDevice;
     impl->Deinitialize = XAUDIO2_Deinitialize;
     impl->Deinitialize = XAUDIO2_Deinitialize;

+ 242 - 90
Engine/lib/sdl/src/core/android/SDL_android.c

@@ -71,10 +71,14 @@ static jclass mActivityClass;
 
 
 /* method signatures */
 /* method signatures */
 static jmethodID midGetNativeSurface;
 static jmethodID midGetNativeSurface;
-static jmethodID midAudioInit;
+static jmethodID midAudioOpen;
 static jmethodID midAudioWriteShortBuffer;
 static jmethodID midAudioWriteShortBuffer;
 static jmethodID midAudioWriteByteBuffer;
 static jmethodID midAudioWriteByteBuffer;
-static jmethodID midAudioQuit;
+static jmethodID midAudioClose;
+static jmethodID midCaptureOpen;
+static jmethodID midCaptureReadShortBuffer;
+static jmethodID midCaptureReadByteBuffer;
+static jmethodID midCaptureClose;
 static jmethodID midPollInputDevices;
 static jmethodID midPollInputDevices;
 
 
 /* Accelerometer data storage */
 /* Accelerometer data storage */
@@ -118,34 +122,45 @@ JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
 
 
     midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
     midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
                                 "getNativeSurface","()Landroid/view/Surface;");
                                 "getNativeSurface","()Landroid/view/Surface;");
-    midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioInit", "(IZZI)I");
+    midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioOpen", "(IZZI)I");
     midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
     midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
                                 "audioWriteShortBuffer", "([S)V");
                                 "audioWriteShortBuffer", "([S)V");
     midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
     midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
                                 "audioWriteByteBuffer", "([B)V");
                                 "audioWriteByteBuffer", "([B)V");
-    midAudioQuit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioQuit", "()V");
+    midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioClose", "()V");
+    midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "captureOpen", "(IZZI)I");
+    midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "captureReadShortBuffer", "([SZ)I");
+    midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "captureReadByteBuffer", "([BZ)I");
+    midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "captureClose", "()V");
     midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
     midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
                                 "pollInputDevices", "()V");
                                 "pollInputDevices", "()V");
 
 
     bHasNewData = SDL_FALSE;
     bHasNewData = SDL_FALSE;
 
 
-    if (!midGetNativeSurface || !midAudioInit ||
-       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit || !midPollInputDevices) {
+    if (!midGetNativeSurface ||
+       !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
+       !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
+       !midPollInputDevices) {
         __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
         __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
     }
     }
     __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
     __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
 }
 }
 
 
 /* Drop file */
 /* Drop file */
-void Java_org_libsdl_app_SDLActivity_onNativeDropFile(
+JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeDropFile(
                                     JNIEnv* env, jclass jcls,
                                     JNIEnv* env, jclass jcls,
                                     jstring filename)
                                     jstring filename)
 {
 {
     const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
     const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
-    SDL_SendDropFile(path);
+    SDL_SendDropFile(NULL, path);
     (*env)->ReleaseStringUTFChars(env, filename, path);
     (*env)->ReleaseStringUTFChars(env, filename, path);
+    SDL_SendDropComplete(NULL);
 }
 }
 
 
 /* Resize */
 /* Resize */
@@ -555,11 +570,15 @@ int Android_JNI_SetupThread(void)
 static jboolean audioBuffer16Bit = JNI_FALSE;
 static jboolean audioBuffer16Bit = JNI_FALSE;
 static jobject audioBuffer = NULL;
 static jobject audioBuffer = NULL;
 static void* audioBufferPinned = NULL;
 static void* audioBufferPinned = NULL;
+static jboolean captureBuffer16Bit = JNI_FALSE;
+static jobject captureBuffer = NULL;
 
 
-int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
+int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
 {
 {
     jboolean audioBufferStereo;
     jboolean audioBufferStereo;
     int audioBufferFrames;
     int audioBufferFrames;
+    jobject jbufobj = NULL;
+    jboolean isCopy;
 
 
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
 
 
@@ -568,14 +587,24 @@ int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, i
     }
     }
     Android_JNI_SetupThread();
     Android_JNI_SetupThread();
 
 
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
-    audioBuffer16Bit = is16Bit;
     audioBufferStereo = channelCount > 1;
     audioBufferStereo = channelCount > 1;
 
 
-    if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
-        /* Error during audio initialization */
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
-        return 0;
+    if (iscapture) {
+        __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture");
+        captureBuffer16Bit = is16Bit;
+        if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+            /* Error during audio initialization */
+            __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioRecord initialization!");
+            return 0;
+        }
+    } else {
+        __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
+        audioBuffer16Bit = is16Bit;
+        if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+            /* Error during audio initialization */
+            __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
+            return 0;
+        }
     }
     }
 
 
     /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
     /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
@@ -584,31 +613,43 @@ int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, i
     if (is16Bit) {
     if (is16Bit) {
         jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
         jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
         if (audioBufferLocal) {
         if (audioBufferLocal) {
-            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
             (*env)->DeleteLocalRef(env, audioBufferLocal);
             (*env)->DeleteLocalRef(env, audioBufferLocal);
         }
         }
     }
     }
     else {
     else {
         jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
         jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
         if (audioBufferLocal) {
         if (audioBufferLocal) {
-            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
             (*env)->DeleteLocalRef(env, audioBufferLocal);
             (*env)->DeleteLocalRef(env, audioBufferLocal);
         }
         }
     }
     }
 
 
-    if (audioBuffer == NULL) {
+    if (jbufobj == NULL) {
         __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
         __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
         return 0;
         return 0;
     }
     }
 
 
-    jboolean isCopy = JNI_FALSE;
-    if (audioBuffer16Bit) {
-        audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+    if (iscapture) {
+        captureBuffer = jbufobj;
+    } else {
+        audioBuffer = jbufobj;
+    }
+
+    isCopy = JNI_FALSE;
+
+    if (is16Bit) {
+        if (!iscapture) {
+            audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+        }
         audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
         audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
     } else {
     } else {
-        audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+        if (!iscapture) {
+            audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+        }
         audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
         audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
     }
     }
+
     if (audioBufferStereo) {
     if (audioBufferStereo) {
         audioBufferFrames /= 2;
         audioBufferFrames /= 2;
     }
     }
@@ -636,16 +677,71 @@ void Android_JNI_WriteAudioBuffer(void)
     /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
     /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
 }
 }
 
 
-void Android_JNI_CloseAudioDevice(void)
+int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
+    jboolean isCopy = JNI_FALSE;
+    jint br;
+
+    if (captureBuffer16Bit) {
+        SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
+        br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
+        if (br > 0) {
+            jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
+            br *= 2;
+            SDL_memcpy(buffer, ptr, br);
+            (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
+        }
+    } else {
+        SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
+        br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
+        if (br > 0) {
+            jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
+            SDL_memcpy(buffer, ptr, br);
+            (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
+        }
+    }
 
 
-    (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioQuit);
+    return (int) br;
+}
 
 
-    if (audioBuffer) {
-        (*env)->DeleteGlobalRef(env, audioBuffer);
-        audioBuffer = NULL;
-        audioBufferPinned = NULL;
+void Android_JNI_FlushCapturedAudio(void)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    #if 0  /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */
+    if (captureBuffer16Bit) {
+        const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
+        while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
+    } else {
+        const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
+        while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
+    }
+    #else
+    if (captureBuffer16Bit) {
+        (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
+    } else {
+        (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
+    }
+    #endif
+}
+
+void Android_JNI_CloseAudioDevice(const int iscapture)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    if (iscapture) {
+        (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
+        if (captureBuffer) {
+            (*env)->DeleteGlobalRef(env, captureBuffer);
+            captureBuffer = NULL;
+        }
+    } else {
+        (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
+        if (audioBuffer) {
+            (*env)->DeleteGlobalRef(env, audioBuffer);
+            audioBuffer = NULL;
+            audioBufferPinned = NULL;
+        }
     }
     }
 }
 }
 
 
@@ -653,10 +749,12 @@ void Android_JNI_CloseAudioDevice(void)
 /* If the parameter silent is truthy then SDL_SetError() will not be called. */
 /* If the parameter silent is truthy then SDL_SetError() will not be called. */
 static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
 static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
 {
 {
-    SDL_assert(LocalReferenceHolder_IsActive());
     JNIEnv *mEnv = Android_JNI_GetEnv();
     JNIEnv *mEnv = Android_JNI_GetEnv();
+    jthrowable exception;
 
 
-    jthrowable exception = (*mEnv)->ExceptionOccurred(mEnv);
+    SDL_assert(LocalReferenceHolder_IsActive());
+
+    exception = (*mEnv)->ExceptionOccurred(mEnv);
     if (exception != NULL) {
     if (exception != NULL) {
         jmethodID mid;
         jmethodID mid;
 
 
@@ -666,13 +764,16 @@ static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
         if (!silent) {
         if (!silent) {
             jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
             jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
             jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
             jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
+            jstring exceptionName;
+            const char* exceptionNameUTF8;
+            jstring exceptionMessage;
 
 
             mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
             mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
-            jstring exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
-            const char* exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
+            exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
+            exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
 
 
             mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
             mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
-            jstring exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
+            exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
 
 
             if (exceptionMessage != NULL) {
             if (exceptionMessage != NULL) {
                 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
                 const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
@@ -855,6 +956,7 @@ int Android_JNI_FileOpen(SDL_RWops* ctx,
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     JNIEnv *mEnv = Android_JNI_GetEnv();
     JNIEnv *mEnv = Android_JNI_GetEnv();
     int retval;
     int retval;
+    jstring fileNameJString;
 
 
     if (!LocalReferenceHolder_Init(&refs, mEnv)) {
     if (!LocalReferenceHolder_Init(&refs, mEnv)) {
         LocalReferenceHolder_Cleanup(&refs);        
         LocalReferenceHolder_Cleanup(&refs);        
@@ -866,7 +968,7 @@ int Android_JNI_FileOpen(SDL_RWops* ctx,
         return -1;
         return -1;
     }
     }
 
 
-    jstring fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
+    fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
     ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
     ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
     ctx->hidden.androidio.inputStreamRef = NULL;
     ctx->hidden.androidio.inputStreamRef = NULL;
     ctx->hidden.androidio.readableByteChannelRef = NULL;
     ctx->hidden.androidio.readableByteChannelRef = NULL;
@@ -885,10 +987,11 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
 
 
     if (ctx->hidden.androidio.assetFileDescriptorRef) {
     if (ctx->hidden.androidio.assetFileDescriptorRef) {
         size_t bytesMax = size * maxnum;
         size_t bytesMax = size * maxnum;
+        size_t result;
         if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
         if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
             bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
             bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
         }
         }
-        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
+        result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
         if (result > 0) {
         if (result > 0) {
             ctx->hidden.androidio.position += result;
             ctx->hidden.androidio.position += result;
             LocalReferenceHolder_Cleanup(&refs);
             LocalReferenceHolder_Cleanup(&refs);
@@ -900,19 +1003,23 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
         jlong bytesRemaining = (jlong) (size * maxnum);
         jlong bytesRemaining = (jlong) (size * maxnum);
         jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
         jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
         int bytesRead = 0;
         int bytesRead = 0;
+        JNIEnv *mEnv;
+        jobject readableByteChannel;
+        jmethodID readMethod;
+        jobject byteBuffer;
 
 
         /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
         /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
         if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
         if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
 
 
-        JNIEnv *mEnv = Android_JNI_GetEnv();
+        mEnv = Android_JNI_GetEnv();
         if (!LocalReferenceHolder_Init(&refs, mEnv)) {
         if (!LocalReferenceHolder_Init(&refs, mEnv)) {
             LocalReferenceHolder_Cleanup(&refs);            
             LocalReferenceHolder_Cleanup(&refs);            
             return 0;
             return 0;
         }
         }
 
 
-        jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
-        jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
-        jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
+        readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
+        readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
+        byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
 
 
         while (bytesRemaining > 0) {
         while (bytesRemaining > 0) {
             /* result = readableByteChannel.read(...); */
             /* result = readableByteChannel.read(...); */
@@ -1002,6 +1109,7 @@ Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
 Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
 Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
 {
 {
     if (ctx->hidden.androidio.assetFileDescriptorRef) {
     if (ctx->hidden.androidio.assetFileDescriptorRef) {
+        off_t ret;
         switch (whence) {
         switch (whence) {
             case RW_SEEK_SET:
             case RW_SEEK_SET:
                 if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
                 if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
@@ -1020,11 +1128,12 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
         }
         }
         whence = SEEK_SET;
         whence = SEEK_SET;
 
 
-        off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
+        ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
         if (ret == -1) return -1;
         if (ret == -1) return -1;
         ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
         ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
     } else {
     } else {
         Sint64 newPosition;
         Sint64 newPosition;
+        Sint64 movement;
 
 
         switch (whence) {
         switch (whence) {
             case RW_SEEK_SET:
             case RW_SEEK_SET:
@@ -1048,17 +1157,18 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
             newPosition = ctx->hidden.androidio.size;
             newPosition = ctx->hidden.androidio.size;
         }
         }
 
 
-        Sint64 movement = newPosition - ctx->hidden.androidio.position;
+        movement = newPosition - ctx->hidden.androidio.position;
         if (movement > 0) {
         if (movement > 0) {
             unsigned char buffer[4096];
             unsigned char buffer[4096];
 
 
             /* The easy case where we're seeking forwards */
             /* The easy case where we're seeking forwards */
             while (movement > 0) {
             while (movement > 0) {
                 Sint64 amount = sizeof (buffer);
                 Sint64 amount = sizeof (buffer);
+                size_t result;
                 if (amount > movement) {
                 if (amount > movement) {
                     amount = movement;
                     amount = movement;
                 }
                 }
-                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
+                result = Android_JNI_FileRead(ctx, buffer, 1, amount);
                 if (result <= 0) {
                 if (result <= 0) {
                     /* Failed to read/skip the required amount, so fail */
                     /* Failed to read/skip the required amount, so fail */
                     return -1;
                     return -1;
@@ -1091,21 +1201,23 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     JNIEnv* env = Android_JNI_GetEnv();
     JNIEnv* env = Android_JNI_GetEnv();
     jobject retval = NULL;
     jobject retval = NULL;
+    jstring service;
+    jmethodID mid;
+    jobject context;
+    jobject manager;
 
 
     if (!LocalReferenceHolder_Init(&refs, env)) {
     if (!LocalReferenceHolder_Init(&refs, env)) {
         LocalReferenceHolder_Cleanup(&refs);
         LocalReferenceHolder_Cleanup(&refs);
         return NULL;
         return NULL;
     }
     }
 
 
-    jstring service = (*env)->NewStringUTF(env, name);
-
-    jmethodID mid;
+    service = (*env)->NewStringUTF(env, name);
 
 
     mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
     mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+    context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
 
 
     mid = (*env)->GetMethodID(env, mActivityClass, "getSystemServiceFromUiThread", "(Ljava/lang/String;)Ljava/lang/Object;");
     mid = (*env)->GetMethodID(env, mActivityClass, "getSystemServiceFromUiThread", "(Ljava/lang/String;)Ljava/lang/Object;");
-    jobject manager = (*env)->CallObjectMethod(env, context, mid, service);
+    manager = (*env)->CallObjectMethod(env, context, mid, service);
 
 
     (*env)->DeleteLocalRef(env, service);
     (*env)->DeleteLocalRef(env, service);
 
 
@@ -1117,11 +1229,12 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
 #define SETUP_CLIPBOARD(error) \
 #define SETUP_CLIPBOARD(error) \
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
     JNIEnv* env = Android_JNI_GetEnv(); \
     JNIEnv* env = Android_JNI_GetEnv(); \
+    jobject clipboard; \
     if (!LocalReferenceHolder_Init(&refs, env)) { \
     if (!LocalReferenceHolder_Init(&refs, env)) { \
         LocalReferenceHolder_Cleanup(&refs); \
         LocalReferenceHolder_Cleanup(&refs); \
         return error; \
         return error; \
     } \
     } \
-    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
+    clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
     if (!clipboard) { \
     if (!clipboard) { \
         LocalReferenceHolder_Cleanup(&refs); \
         LocalReferenceHolder_Cleanup(&refs); \
         return error; \
         return error; \
@@ -1132,14 +1245,17 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
 
 
 int Android_JNI_SetClipboardText(const char* text)
 int Android_JNI_SetClipboardText(const char* text)
 {
 {
+    /* Watch out for C89 scoping rules because of the macro */
     SETUP_CLIPBOARD(-1)
     SETUP_CLIPBOARD(-1)
 
 
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
-    jstring string = (*env)->NewStringUTF(env, text);
-    (*env)->CallVoidMethod(env, clipboard, mid, string);
-    (*env)->DeleteGlobalRef(env, clipboard);
-    (*env)->DeleteLocalRef(env, string);
-
+    /* Nest the following in a scope to avoid C89 declaration rules triggered by the macro */
+    {
+        jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
+        jstring string = (*env)->NewStringUTF(env, text);
+        (*env)->CallVoidMethod(env, clipboard, mid, string);
+        (*env)->DeleteGlobalRef(env, clipboard);
+        (*env)->DeleteLocalRef(env, string);
+    }
     CLEANUP_CLIPBOARD();
     CLEANUP_CLIPBOARD();
 
 
     return 0;
     return 0;
@@ -1147,25 +1263,30 @@ int Android_JNI_SetClipboardText(const char* text)
 
 
 char* Android_JNI_GetClipboardText(void)
 char* Android_JNI_GetClipboardText(void)
 {
 {
+    /* Watch out for C89 scoping rules because of the macro */
     SETUP_CLIPBOARD(SDL_strdup(""))
     SETUP_CLIPBOARD(SDL_strdup(""))
 
 
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
-    jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
-    (*env)->DeleteGlobalRef(env, clipboard);
-    if (sequence) {
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
-        jstring string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
-        const char* utf = (*env)->GetStringUTFChars(env, string, 0);
-        if (utf) {
-            char* text = SDL_strdup(utf);
-            (*env)->ReleaseStringUTFChars(env, string, utf);
-
-            CLEANUP_CLIPBOARD();
-
-            return text;
+    /* Nest the following in a scope to avoid C89 declaration rules triggered by the macro */
+    {
+        jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
+        jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
+        (*env)->DeleteGlobalRef(env, clipboard);
+        if (sequence) {
+            jstring string;
+            const char* utf;
+            mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
+            string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
+            utf = (*env)->GetStringUTFChars(env, string, 0);
+            if (utf) {
+                char* text = SDL_strdup(utf);
+                (*env)->ReleaseStringUTFChars(env, string, utf);
+
+                CLEANUP_CLIPBOARD();
+
+                return text;
+            }
         }
         }
     }
     }
-
     CLEANUP_CLIPBOARD();    
     CLEANUP_CLIPBOARD();    
 
 
     return SDL_strdup("");
     return SDL_strdup("");
@@ -1173,10 +1294,13 @@ char* Android_JNI_GetClipboardText(void)
 
 
 SDL_bool Android_JNI_HasClipboardText(void)
 SDL_bool Android_JNI_HasClipboardText(void)
 {
 {
+    jmethodID mid;
+    jboolean has;
+    /* Watch out for C89 scoping rules because of the macro */
     SETUP_CLIPBOARD(SDL_FALSE)
     SETUP_CLIPBOARD(SDL_FALSE)
 
 
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
-    jboolean has = (*env)->CallBooleanMethod(env, clipboard, mid);
+    mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
+    has = (*env)->CallBooleanMethod(env, clipboard, mid);
     (*env)->DeleteGlobalRef(env, clipboard);
     (*env)->DeleteGlobalRef(env, clipboard);
 
 
     CLEANUP_CLIPBOARD();
     CLEANUP_CLIPBOARD();
@@ -1193,49 +1317,61 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
 {
 {
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
     JNIEnv* env = Android_JNI_GetEnv();
     JNIEnv* env = Android_JNI_GetEnv();
+    jmethodID mid;
+    jobject context;
+    jstring action;
+    jclass cls;
+    jobject filter;
+    jobject intent;
+    jstring iname;
+    jmethodID imid;
+    jstring bname;
+    jmethodID bmid;
     if (!LocalReferenceHolder_Init(&refs, env)) {
     if (!LocalReferenceHolder_Init(&refs, env)) {
         LocalReferenceHolder_Cleanup(&refs);
         LocalReferenceHolder_Cleanup(&refs);
         return -1;
         return -1;
     }
     }
 
 
-    jmethodID mid;
 
 
     mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
     mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+    context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
 
 
-    jstring action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
+    action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
 
 
-    jclass cls = (*env)->FindClass(env, "android/content/IntentFilter");
+    cls = (*env)->FindClass(env, "android/content/IntentFilter");
 
 
     mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
     mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
-    jobject filter = (*env)->NewObject(env, cls, mid, action);
+    filter = (*env)->NewObject(env, cls, mid, action);
 
 
     (*env)->DeleteLocalRef(env, action);
     (*env)->DeleteLocalRef(env, action);
 
 
     mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
     mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
-    jobject intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
+    intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
 
 
     (*env)->DeleteLocalRef(env, filter);
     (*env)->DeleteLocalRef(env, filter);
 
 
     cls = (*env)->GetObjectClass(env, intent);
     cls = (*env)->GetObjectClass(env, intent);
 
 
-    jstring iname;
-    jmethodID imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+    imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
 
 
+    /* Watch out for C89 scoping rules because of the macro */
 #define GET_INT_EXTRA(var, key) \
 #define GET_INT_EXTRA(var, key) \
+    int var; \
     iname = (*env)->NewStringUTF(env, key); \
     iname = (*env)->NewStringUTF(env, key); \
-    int var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
+    var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
     (*env)->DeleteLocalRef(env, iname);
     (*env)->DeleteLocalRef(env, iname);
 
 
-    jstring bname;
-    jmethodID bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+    bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
 
 
+    /* Watch out for C89 scoping rules because of the macro */
 #define GET_BOOL_EXTRA(var, key) \
 #define GET_BOOL_EXTRA(var, key) \
+    int var; \
     bname = (*env)->NewStringUTF(env, key); \
     bname = (*env)->NewStringUTF(env, key); \
-    int var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
+    var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
     (*env)->DeleteLocalRef(env, bname);
     (*env)->DeleteLocalRef(env, bname);
 
 
     if (plugged) {
     if (plugged) {
+        /* Watch out for C89 scoping rules because of the macro */
         GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */
         GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */
         if (plug == -1) {
         if (plug == -1) {
             LocalReferenceHolder_Cleanup(&refs);
             LocalReferenceHolder_Cleanup(&refs);
@@ -1247,6 +1383,7 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
     }
     }
 
 
     if (charged) {
     if (charged) {
+        /* Watch out for C89 scoping rules because of the macro */
         GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */
         GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */
         if (status == -1) {
         if (status == -1) {
             LocalReferenceHolder_Cleanup(&refs);
             LocalReferenceHolder_Cleanup(&refs);
@@ -1266,8 +1403,20 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
     }
     }
 
 
     if (percent) {
     if (percent) {
-        GET_INT_EXTRA(level, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
-        GET_INT_EXTRA(scale, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
+        int level;
+        int scale;
+        
+        /* Watch out for C89 scoping rules because of the macro */
+        {
+            GET_INT_EXTRA(level_temp, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
+            level = level_temp;
+        }
+        /* Watch out for C89 scoping rules because of the macro */
+        {
+            GET_INT_EXTRA(scale_temp, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
+            scale = scale_temp;
+        }
+        
         if ((level == -1) || (scale == -1)) {
         if ((level == -1) || (scale == -1)) {
             LocalReferenceHolder_Cleanup(&refs);
             LocalReferenceHolder_Cleanup(&refs);
             return -1;
             return -1;
@@ -1320,14 +1469,16 @@ void Android_JNI_PollInputDevices(void)
 int Android_JNI_SendMessage(int command, int param)
 int Android_JNI_SendMessage(int command, int param)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
+    jmethodID mid;
+    jboolean success;
     if (!env) {
     if (!env) {
         return -1;
         return -1;
     }
     }
-    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
     if (!mid) {
     if (!mid) {
         return -1;
         return -1;
     }
     }
-    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
+    success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
     return success ? 0 : -1;
     return success ? 0 : -1;
 }
 }
 
 
@@ -1339,11 +1490,12 @@ void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
 void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
 void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
 {
 {
     JNIEnv *env = Android_JNI_GetEnv();
     JNIEnv *env = Android_JNI_GetEnv();
+    jmethodID mid;
     if (!env) {
     if (!env) {
         return;
         return;
     }
     }
 
 
-    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
     if (!mid) {
     if (!mid) {
         return;
         return;
     }
     }

+ 4 - 2
Engine/lib/sdl/src/core/android/SDL_android.h

@@ -40,10 +40,12 @@ extern void Android_JNI_HideTextInput(void);
 extern ANativeWindow* Android_JNI_GetNativeWindow(void);
 extern ANativeWindow* Android_JNI_GetNativeWindow(void);
 
 
 /* Audio support */
 /* Audio support */
-extern int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
+extern int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
 extern void* Android_JNI_GetAudioBuffer(void);
 extern void* Android_JNI_GetAudioBuffer(void);
 extern void Android_JNI_WriteAudioBuffer(void);
 extern void Android_JNI_WriteAudioBuffer(void);
-extern void Android_JNI_CloseAudioDevice(void);
+extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen);
+extern void Android_JNI_FlushCapturedAudio(void);
+extern void Android_JNI_CloseAudioDevice(const int iscapture);
 
 
 #include "SDL_rwops.h"
 #include "SDL_rwops.h"
 
 

+ 1 - 1
Engine/lib/sdl/src/core/linux/SDL_dbus.c

@@ -27,7 +27,7 @@
 static const char *dbus_library = "libdbus-1.so.3";
 static const char *dbus_library = "libdbus-1.so.3";
 static void *dbus_handle = NULL;
 static void *dbus_handle = NULL;
 static unsigned int screensaver_cookie = 0;
 static unsigned int screensaver_cookie = 0;
-static SDL_DBusContext dbus = {0};
+static SDL_DBusContext dbus;
 
 
 static int
 static int
 LoadDBUSSyms(void)
 LoadDBUSSyms(void)

File diff suppressed because it is too large
+ 491 - 435
Engine/lib/sdl/src/core/linux/SDL_evdev.c


+ 0 - 20
Engine/lib/sdl/src/core/linux/SDL_evdev.h

@@ -27,31 +27,11 @@
 #ifdef SDL_INPUT_LINUXEV
 #ifdef SDL_INPUT_LINUXEV
 
 
 #include "SDL_events.h"
 #include "SDL_events.h"
-#include <sys/stat.h>
-
-typedef struct SDL_evdevlist_item
-{
-    char *path;
-    int fd;
-    struct SDL_evdevlist_item *next;
-} SDL_evdevlist_item;
-
-typedef struct SDL_EVDEV_PrivateData
-{
-    SDL_evdevlist_item *first;
-    SDL_evdevlist_item *last;
-    int numdevices;
-    int ref_count;
-    int console_fd;
-    int kb_mode;
-    int tty;
-} SDL_EVDEV_PrivateData;
 
 
 extern int SDL_EVDEV_Init(void);
 extern int SDL_EVDEV_Init(void);
 extern void SDL_EVDEV_Quit(void);
 extern void SDL_EVDEV_Quit(void);
 extern void SDL_EVDEV_Poll(void);
 extern void SDL_EVDEV_Poll(void);
 
 
-
 #endif /* SDL_INPUT_LINUXEV */
 #endif /* SDL_INPUT_LINUXEV */
 
 
 #endif /* _SDL_evdev_h */
 #endif /* _SDL_evdev_h */

+ 553 - 0
Engine/lib/sdl/src/core/linux/SDL_fcitx.c

@@ -0,0 +1,553 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifdef HAVE_FCITX_FRONTEND_H
+
+#include <fcitx/frontend.h>
+#include <unistd.h>
+
+#include "SDL_fcitx.h"
+#include "SDL_keycode.h"
+#include "SDL_keyboard.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "SDL_dbus.h"
+#include "SDL_syswm.h"
+#if SDL_VIDEO_DRIVER_X11
+#  include "../../video/x11/SDL_x11video.h"
+#endif
+#include "SDL_hints.h"
+
+#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
+
+#define FCITX_IM_DBUS_PATH "/inputmethod"
+#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
+
+#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
+#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
+
+#define IC_NAME_MAX 64
+#define DBUS_TIMEOUT 500
+
+typedef struct _FcitxClient
+{
+    SDL_DBusContext *dbus;
+
+    char servicename[IC_NAME_MAX];
+    char icname[IC_NAME_MAX];
+
+    int id;
+
+    SDL_Rect cursor_rect;
+} FcitxClient;
+
+static FcitxClient fcitx_client;
+
+static int
+GetDisplayNumber()
+{
+    const char *display = SDL_getenv("DISPLAY");
+    const char *p = NULL;
+    int number = 0;
+
+    if (display == NULL)
+        return 0;
+
+    display = SDL_strchr(display, ':');
+    if (display == NULL)
+        return 0;
+
+    display++;
+    p = SDL_strchr(display, '.');
+    if (p == NULL && display != NULL) {
+        number = SDL_strtod(display, NULL);
+    } else {
+        char *buffer = SDL_strdup(display);
+        buffer[p - display] = '\0';
+        number = SDL_strtod(buffer, NULL);
+        SDL_free(buffer);
+    }
+
+    return number;
+}
+
+static char*
+GetAppName()
+{
+#if defined(__LINUX__) || defined(__FREEBSD__)
+    char *spot;
+    char procfile[1024];
+    char linkfile[1024];
+    int linksize;
+
+#if defined(__LINUX__)
+    SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid());
+#elif defined(__FREEBSD__)
+    SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid());
+#endif
+    linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
+    if (linksize > 0) {
+        linkfile[linksize] = '\0';
+        spot = SDL_strrchr(linkfile, '/');
+        if (spot) {
+            return SDL_strdup(spot + 1);
+        } else {
+            return SDL_strdup(linkfile);
+        }
+    }
+#endif /* __LINUX__ || __FREEBSD__ */
+
+    return SDL_strdup("SDL_App");
+}
+
+/*
+ * Copied from fcitx source
+ */
+#define CONT(i)   ISUTF8_CB(in[i])
+#define VAL(i, s) ((in[i]&0x3f) << s)
+
+static char *
+_fcitx_utf8_get_char(const char *i, uint32_t *chr)
+{
+    const unsigned char* in = (const unsigned char *)i;
+    if (!(in[0] & 0x80)) {
+        *(chr) = *(in);
+        return (char *)in + 1;
+    }
+
+    /* 2-byte, 0x80-0x7ff */
+    if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
+        *chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
+        return (char *)in + 2;
+    }
+
+    /* 3-byte, 0x800-0xffff */
+    if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
+        *chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
+        return (char *)in + 3;
+    }
+
+    /* 4-byte, 0x10000-0x1FFFFF */
+    if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
+        *chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
+        return (char *)in + 4;
+    }
+
+    /* 5-byte, 0x200000-0x3FFFFFF */
+    if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
+        *chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
+        return (char *)in + 5;
+    }
+
+    /* 6-byte, 0x400000-0x7FFFFFF */
+    if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
+        *chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
+        return (char *)in + 6;
+    }
+
+    *chr = *in;
+
+    return (char *)in + 1;
+}
+
+static size_t
+_fcitx_utf8_strlen(const char *s)
+{
+    unsigned int l = 0;
+
+    while (*s) {
+        uint32_t chr;
+
+        s = _fcitx_utf8_get_char(s, &chr);
+        l++;
+    }
+
+    return l;
+}
+
+static DBusHandlerResult
+DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+    SDL_DBusContext *dbus = (SDL_DBusContext *)data;
+
+    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "CommitString")) {
+        DBusMessageIter iter;
+        const char *text = NULL;
+
+        dbus->message_iter_init(msg, &iter);
+        dbus->message_iter_get_basic(&iter, &text);
+
+        if (text)
+            SDL_SendKeyboardText(text);
+
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+
+    if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
+        DBusMessageIter iter;
+        const char *text;
+
+        dbus->message_iter_init(msg, &iter);
+        dbus->message_iter_get_basic(&iter, &text);
+
+        if (text && *text) {
+            char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+            size_t text_bytes = SDL_strlen(text), i = 0;
+            size_t cursor = 0;
+
+            while (i < text_bytes) {
+                size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
+                size_t chars = _fcitx_utf8_strlen(buf);
+
+                SDL_SendEditingText(buf, cursor, chars);
+
+                i += sz;
+                cursor += chars;
+            }
+        }
+
+        SDL_Fcitx_UpdateTextRect(NULL);
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusMessage*
+FcitxClientICNewMethod(FcitxClient *client,
+        const char *method)
+{
+    SDL_DBusContext *dbus = client->dbus;
+    return dbus->message_new_method_call(
+            client->servicename,
+            client->icname,
+            FCITX_IC_DBUS_INTERFACE,
+            method);
+}
+
+static void
+FcitxClientICCallMethod(FcitxClient *client,
+        const char *method)
+{
+    SDL_DBusContext *dbus = client->dbus;
+    DBusMessage *msg = FcitxClientICNewMethod(client, method);
+
+    if (msg == NULL)
+        return ;
+
+    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
+        dbus->connection_flush(dbus->session_conn);
+    }
+
+    dbus->message_unref(msg);
+}
+
+static void
+Fcitx_SetCapabilities(void *data,
+        const char *name,
+        const char *old_val,
+        const char *internal_editing)
+{
+    FcitxClient *client = (FcitxClient *)data;
+    SDL_DBusContext *dbus = client->dbus;
+    Uint32 caps = CAPACITY_NONE;
+
+    DBusMessage *msg = FcitxClientICNewMethod(client, "SetCapacity");
+    if (msg == NULL)
+        return ;
+
+    if (!(internal_editing && *internal_editing == '1')) {
+        caps |= CAPACITY_PREEDIT;
+    }
+
+    dbus->message_append_args(msg,
+            DBUS_TYPE_UINT32, &caps,
+            DBUS_TYPE_INVALID);
+    if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
+        dbus->connection_flush(dbus->session_conn);
+    }
+
+    dbus->message_unref(msg);
+}
+
+static void
+FcitxClientCreateIC(FcitxClient *client)
+{
+    char *appname = NULL;
+    pid_t pid = 0;
+    int id = 0;
+    SDL_bool enable;
+    Uint32 arg1, arg2, arg3, arg4;
+
+    SDL_DBusContext *dbus = client->dbus;
+    DBusMessage *reply = NULL;
+    DBusMessage *msg = dbus->message_new_method_call(
+            client->servicename,
+            FCITX_IM_DBUS_PATH,
+            FCITX_IM_DBUS_INTERFACE,
+            "CreateICv3"
+            );
+
+    if (msg == NULL)
+        return ;
+
+    appname = GetAppName();
+    pid = getpid();
+    dbus->message_append_args(msg,
+            DBUS_TYPE_STRING, &appname,
+            DBUS_TYPE_INT32, &pid,
+            DBUS_TYPE_INVALID);
+
+    do {
+        reply = dbus->connection_send_with_reply_and_block(
+                dbus->session_conn,
+                msg,
+                DBUS_TIMEOUT,
+                NULL);
+
+        if (!reply)
+            break;
+        if (!dbus->message_get_args(reply, NULL,
+                DBUS_TYPE_INT32, &id,
+                DBUS_TYPE_BOOLEAN, &enable,
+                DBUS_TYPE_UINT32, &arg1,
+                DBUS_TYPE_UINT32, &arg2,
+                DBUS_TYPE_UINT32, &arg3,
+                DBUS_TYPE_UINT32, &arg4,
+                DBUS_TYPE_INVALID))
+            break;
+
+        if (id < 0)
+            break;
+        client->id = id;
+
+        SDL_snprintf(client->icname, IC_NAME_MAX,
+                FCITX_IC_DBUS_PATH, client->id);
+
+        dbus->bus_add_match(dbus->session_conn,
+                "type='signal', interface='org.fcitx.Fcitx.InputContext'",
+                NULL);
+        dbus->connection_add_filter(dbus->session_conn,
+                &DBus_MessageFilter, dbus,
+                NULL);
+        dbus->connection_flush(dbus->session_conn);
+
+        SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &Fcitx_SetCapabilities, client);
+    }
+    while (0);
+
+    if (reply)
+        dbus->message_unref(reply);
+    dbus->message_unref(msg);
+    SDL_free(appname);
+}
+
+static Uint32
+Fcitx_ModState(void)
+{
+    Uint32 fcitx_mods = 0;
+    SDL_Keymod sdl_mods = SDL_GetModState();
+
+    if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
+    if (sdl_mods & KMOD_CAPS)   fcitx_mods |= FcitxKeyState_CapsLock;
+    if (sdl_mods & KMOD_CTRL)  fcitx_mods |= FcitxKeyState_Ctrl;
+    if (sdl_mods & KMOD_ALT)   fcitx_mods |= FcitxKeyState_Alt;
+    if (sdl_mods & KMOD_NUM)    fcitx_mods |= FcitxKeyState_NumLock;
+    if (sdl_mods & KMOD_LGUI)   fcitx_mods |= FcitxKeyState_Super;
+    if (sdl_mods & KMOD_RGUI)   fcitx_mods |= FcitxKeyState_Meta;
+
+    return fcitx_mods;
+}
+
+SDL_bool
+SDL_Fcitx_Init()
+{
+    fcitx_client.dbus = SDL_DBus_GetContext();
+
+    fcitx_client.cursor_rect.x = -1;
+    fcitx_client.cursor_rect.y = -1;
+    fcitx_client.cursor_rect.w = 0;
+    fcitx_client.cursor_rect.h = 0;
+
+    SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
+            "%s-%d",
+            FCITX_DBUS_SERVICE, GetDisplayNumber());
+
+    FcitxClientCreateIC(&fcitx_client);
+
+    return SDL_TRUE;
+}
+
+void
+SDL_Fcitx_Quit()
+{
+    FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
+}
+
+void
+SDL_Fcitx_SetFocus(SDL_bool focused)
+{
+    if (focused) {
+        FcitxClientICCallMethod(&fcitx_client, "FocusIn");
+    } else {
+        FcitxClientICCallMethod(&fcitx_client, "FocusOut");
+    }
+}
+
+void
+SDL_Fcitx_Reset(void)
+{
+    FcitxClientICCallMethod(&fcitx_client, "Reset");
+    FcitxClientICCallMethod(&fcitx_client, "CloseIC");
+}
+
+SDL_bool
+SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+{
+    DBusMessage *msg = NULL;
+    DBusMessage *reply = NULL;
+    SDL_DBusContext *dbus = fcitx_client.dbus;
+
+    Uint32 state = 0;
+    SDL_bool handled = SDL_FALSE;
+    int type = FCITX_PRESS_KEY;
+    Uint32 event_time = 0;
+
+    msg = FcitxClientICNewMethod(&fcitx_client, "ProcessKeyEvent");
+    if (msg == NULL)
+        return SDL_FALSE;
+
+    state = Fcitx_ModState();
+    dbus->message_append_args(msg,
+            DBUS_TYPE_UINT32, &keysym,
+            DBUS_TYPE_UINT32, &keycode,
+            DBUS_TYPE_UINT32, &state,
+            DBUS_TYPE_INT32, &type,
+            DBUS_TYPE_UINT32, &event_time,
+            DBUS_TYPE_INVALID);
+
+    reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
+            msg,
+            -1,
+            NULL);
+
+    if (reply) {
+        dbus->message_get_args(reply,
+                NULL,
+                DBUS_TYPE_INT32, &handled,
+                DBUS_TYPE_INVALID);
+
+        dbus->message_unref(reply);
+    }
+
+    if (handled) {
+        SDL_Fcitx_UpdateTextRect(NULL);
+    }
+
+    return handled;
+}
+
+void
+SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
+{
+    SDL_Window *focused_win = NULL;
+    SDL_SysWMinfo info;
+    int x = 0, y = 0;
+    SDL_Rect *cursor = &fcitx_client.cursor_rect;
+
+    SDL_DBusContext *dbus = fcitx_client.dbus;
+    DBusMessage *msg = NULL;
+    DBusConnection *conn;
+
+    if (rect) {
+        SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
+    }
+
+    focused_win = SDL_GetKeyboardFocus();
+    if (!focused_win) {
+        return ;
+    }
+
+    SDL_VERSION(&info.version);
+    if (!SDL_GetWindowWMInfo(focused_win, &info)) {
+        return;
+    }
+
+    SDL_GetWindowPosition(focused_win, &x, &y);
+
+#if SDL_VIDEO_DRIVER_X11
+    if (info.subsystem == SDL_SYSWM_X11) {
+        SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
+
+        Display *x_disp = info.info.x11.display;
+        Window x_win = info.info.x11.window;
+        int x_screen = displaydata->screen;
+        Window unused;
+        X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
+    }
+#endif
+
+    if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) {
+        // move to bottom left
+        int w = 0, h = 0;
+        SDL_GetWindowSize(focused_win, &w, &h);
+        cursor->x = 0;
+        cursor->y = h;
+    }
+
+    x += cursor->x;
+    y += cursor->y;
+
+    msg = FcitxClientICNewMethod(&fcitx_client, "SetCursorRect");
+    if (msg == NULL)
+        return ;
+
+    dbus->message_append_args(msg,
+            DBUS_TYPE_INT32, &x,
+            DBUS_TYPE_INT32, &y,
+            DBUS_TYPE_INT32, &cursor->w,
+            DBUS_TYPE_INT32, &cursor->h,
+            DBUS_TYPE_INVALID);
+
+    conn = dbus->session_conn;
+    if (dbus->connection_send(conn, msg, NULL))
+        dbus->connection_flush(conn);
+
+    dbus->message_unref(msg);
+}
+
+void
+SDL_Fcitx_PumpEvents()
+{
+    SDL_DBusContext *dbus = fcitx_client.dbus;
+    DBusConnection *conn = dbus->session_conn;
+
+    dbus->connection_read_write(conn, 0);
+
+    while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
+        /* Do nothing, actual work happens in DBus_MessageFilter */
+        usleep(10);
+    }
+}
+
+#endif /* HAVE_FCITX_FRONTEND_H */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 40 - 0
Engine/lib/sdl/src/core/linux/SDL_fcitx.h

@@ -0,0 +1,40 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2016 Sam Lantinga <[email protected]>
+
+  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_fcitx_h
+#define _SDL_fcitx_h
+
+#include "../../SDL_internal.h"
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+
+extern SDL_bool SDL_Fcitx_Init(void);
+extern void SDL_Fcitx_Quit(void);
+extern void SDL_Fcitx_SetFocus(SDL_bool focused);
+extern void SDL_Fcitx_Reset(void);
+extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
+extern void SDL_Fcitx_PumpEvents();
+
+#endif /* _SDL_fcitx_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

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