Merged default into iOS-improvements iOS-improvements
authorAlex Szpakowski <slime73@gmail.com>
Mon, 06 Apr 2015 15:26:37 -0300
branchiOS-improvements
changeset 95363c87b8f9dc58
parent 9535 a66a7f7e8cd8
parent 9459 f5b468964b0b
child 9537 ff30c198864e
Merged default into iOS-improvements
include/SDL_hints.h
include/SDL_syswm.h
src/joystick/iphoneos/SDL_sysjoystick.m
src/video/SDL_video.c
     1.1 --- a/CMakeLists.txt	Sat Jan 24 23:58:07 2015 -0400
     1.2 +++ b/CMakeLists.txt	Mon Apr 06 15:26:37 2015 -0300
     1.3 @@ -118,9 +118,9 @@
     1.4  endif()
     1.5  
     1.6  if (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN) # JavaScript does not yet have threading support, so disable pthreads when building for Emscripten.
     1.7 -  set(PTHREADS_ENABLED_BY_DEFAULT ON)
     1.8 +  set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON)
     1.9  else()
    1.10 -  set(PTHREADS_ENABLED_BY_DEFAULT OFF)
    1.11 +  set(SDL_PTHREADS_ENABLED_BY_DEFAULT OFF)
    1.12  endif()
    1.13  
    1.14  # Default option knobs
    1.15 @@ -202,6 +202,7 @@
    1.16  
    1.17  # All these ENABLED_BY_DEFAULT vars will default to ON if not specified, so
    1.18  #  you only need to have a platform override them if they are disabling.
    1.19 +set(OPT_DEF_ASM TRUE)
    1.20  if(EMSCRIPTEN)
    1.21    # Set up default values for the currently supported set of subsystems:
    1.22    # Emscripten/Javascript does not have assembly support, a dynamic library 
    1.23 @@ -212,12 +213,12 @@
    1.24    set(SDL_THREADS_ENABLED_BY_DEFAULT OFF)
    1.25    set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF)
    1.26    set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF)
    1.27 -  set(DLOPEN_ENABLED_BY_DEFAULT OFF)
    1.28 +  set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF)
    1.29  endif()
    1.30  
    1.31  set(SDL_SUBSYSTEMS
    1.32      Atomic Audio Video Render Events Joystick Haptic Power Threads Timers
    1.33 -    File Loadso CPUinfo Filesystem)
    1.34 +    File Loadso CPUinfo Filesystem Dlopen)
    1.35  foreach(_SUB ${SDL_SUBSYSTEMS})
    1.36    string(TOUPPER ${_SUB} _OPT)
    1.37    if (NOT DEFINED SDL_${_OPT}_ENABLED_BY_DEFAULT)
    1.38 @@ -246,9 +247,9 @@
    1.39  set_option(VIDEO_DUMMY         "Use dummy video driver" ON)
    1.40  set_option(VIDEO_OPENGL        "Include OpenGL support" ON)
    1.41  set_option(VIDEO_OPENGLES      "Include OpenGL ES support" ON)
    1.42 -set_option(PTHREADS            "Use POSIX threads for multi-threading" ${PTHREADS_ENABLED_BY_DEFAULT})
    1.43 +set_option(PTHREADS            "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT})
    1.44  dep_option(PTHREADS_SEM        "Use pthread semaphores" ON "PTHREADS" OFF)
    1.45 -set_option(SDL_DLOPEN          "Use dlopen for shared object loading" ${DLOPEN_ENABLED_BY_DEFAULT})
    1.46 +set_option(SDL_DLOPEN          "Use dlopen for shared object loading" ${SDL_DLOPEN_ENABLED_BY_DEFAULT})
    1.47  set_option(OSS                 "Support the OSS audio API" ${UNIX_SYS})
    1.48  set_option(ALSA                "Support the ALSA audio API" ${UNIX_SYS})
    1.49  dep_option(ALSA_SHARED         "Dynamically load ALSA audio support" ON "ALSA" OFF)
    1.50 @@ -266,7 +267,10 @@
    1.51  set_option(INPUT_TSLIB         "Use the Touchscreen library for input" ${UNIX_SYS})
    1.52  set_option(VIDEO_X11           "Use X11 video driver" ${UNIX_SYS})
    1.53  set_option(VIDEO_WAYLAND       "Use Wayland video driver" ${UNIX_SYS})
    1.54 +dep_option(WAYLAND_SHARED      "Dynamically load Wayland support" ON "VIDEO_WAYLAND" OFF)
    1.55 +dep_option(VIDEO_WAYLAND_QT_TOUCH  "QtWayland server support for Wayland video driver" ON "VIDEO_WAYLAND" OFF)
    1.56  set_option(VIDEO_MIR           "Use Mir video driver" ${UNIX_SYS})
    1.57 +dep_option(MIR_SHARED          "Dynamically load Mir support" ON "VIDEO_MIR" OFF)
    1.58  set_option(VIDEO_RPI           "Use Raspberry Pi video driver" ${UNIX_SYS})
    1.59  dep_option(X11_SHARED          "Dynamically load X11 support" ON "VIDEO_X11" OFF)
    1.60  set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm)
    1.61 @@ -585,7 +589,7 @@
    1.62        set(CMAKE_REQUIRED_LIBRARIES m)
    1.63        foreach(_FN
    1.64                atan atan2 ceil copysign cos cosf fabs floor log pow scalbn sin
    1.65 -              sinf sqrt sqrtf tan tanf)
    1.66 +              sinf sqrt sqrtf tan tanf acos asin)
    1.67          string(TOUPPER ${_FN} _UPPER)
    1.68          set(_HAVEVAR "HAVE_${_UPPER}")
    1.69          check_function_exists("${_FN}" ${_HAVEVAR})
    1.70 @@ -597,6 +601,15 @@
    1.71      check_library_exists(iconv iconv_open "" HAVE_LIBICONV)
    1.72      if(HAVE_LIBICONV)
    1.73        list(APPEND EXTRA_LIBS iconv)
    1.74 +      set(HAVE_ICONV 1)
    1.75 +    endif()
    1.76 +
    1.77 +    if(NOT APPLE)
    1.78 +      check_include_file(alloca.h HAVE_ALLOCA_H)
    1.79 +      check_function_exists(alloca HAVE_ALLOCA)
    1.80 +    else()
    1.81 +      set(HAVE_ALLOCA_H 1)
    1.82 +      set(HAVE_ALLOCA 1)
    1.83      endif()
    1.84  
    1.85      check_struct_has_member("struct sigaction" "sa_sigaction" "signal.h" HAVE_SA_SIGACTION)
    1.86 @@ -1140,10 +1153,6 @@
    1.87        set(SDL_VIDEO_OPENGL 1)
    1.88        set(SDL_VIDEO_OPENGL_CGL 1)
    1.89        set(SDL_VIDEO_RENDER_OGL 1)
    1.90 -      if(DARWIN)
    1.91 -        find_library(OpenGL_LIBRARY OpenGL)
    1.92 -        list(APPEND EXTRA_LIBRARIES ${OpenGL_LIBRARY})
    1.93 -      endif()
    1.94        set(HAVE_VIDEO_OPENGL TRUE)
    1.95      endif()
    1.96    endif()
     2.1 --- a/SDL2.spec.in	Sat Jan 24 23:58:07 2015 -0400
     2.2 +++ b/SDL2.spec.in	Mon Apr 06 15:26:37 2015 -0300
     2.3 @@ -1,7 +1,7 @@
     2.4  Summary: Simple DirectMedia Layer
     2.5  Name: SDL2
     2.6  Version: @SDL_VERSION@
     2.7 -Release: 1
     2.8 +Release: 2
     2.9  Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
    2.10  URL: http://www.libsdl.org/
    2.11  License: zlib
    2.12 @@ -63,12 +63,12 @@
    2.13  
    2.14  %files
    2.15  %{__defattr}
    2.16 -%doc README-SDL.txt COPYING.txt CREDITS.txt BUGS.txt
    2.17 +%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt
    2.18  %{_libdir}/lib*.%{__soext}.*
    2.19  
    2.20  %files devel
    2.21  %{__defattr}
    2.22 -%doc README README-SDL.txt COPYING CREDITS BUGS WhatsNew
    2.23 +%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt WhatsNew.txt
    2.24  %{_bindir}/*-config
    2.25  %{_libdir}/lib*.a
    2.26  %{_libdir}/lib*.la
    2.27 @@ -78,13 +78,16 @@
    2.28  %{_datadir}/aclocal/*
    2.29  
    2.30  %changelog
    2.31 +* Sun Dec 07 2014 Simone Contini <s.contini@oltrelinux.com>
    2.32 +- Fixed changelog date issue and docs filenames
    2.33 +
    2.34  * Sun Jan 22 2012 Sam Lantinga <slouken@libsdl.org>
    2.35  - Updated for SDL 2.0
    2.36  
    2.37  * Tue May 16 2006 Sam Lantinga <slouken@libsdl.org>
    2.38  - Removed support for Darwin, due to build problems on ps2linux
    2.39  
    2.40 -* Mon Jan 03 2004 Anders Bjorklund <afb@algonet.se>
    2.41 +* Sat Jan 03 2004 Anders Bjorklund <afb@algonet.se>
    2.42  - Added support for Darwin, updated spec file
    2.43  
    2.44  * Wed Jan 19 2000 Sam Lantinga <slouken@libsdl.org>
     3.1 --- a/android-project/src/org/libsdl/app/SDLActivity.java	Sat Jan 24 23:58:07 2015 -0400
     3.2 +++ b/android-project/src/org/libsdl/app/SDLActivity.java	Mon Apr 06 15:26:37 2015 -0300
     3.3 @@ -41,6 +41,10 @@
     3.4      /** If shared libraries (e.g. SDL or the native application) could not be loaded. */
     3.5      public static boolean mBrokenLibraries;
     3.6  
     3.7 +    // If we want to separate mouse and touch events.
     3.8 +    //  This is only toggled in native code when a hint is set!
     3.9 +    public static boolean mSeparateMouseAndTouch;
    3.10 +
    3.11      // Main components
    3.12      protected static SDLActivity mSingleton;
    3.13      protected static SDLSurface mSurface;
    3.14 @@ -81,7 +85,6 @@
    3.15      }
    3.16      
    3.17      /**
    3.18 -     * This method is called by SDL using JNI.
    3.19       * This method is called by SDL before starting the native application thread.
    3.20       * It can be overridden to provide the arguments after the application name.
    3.21       * The default implementation returns an empty array. It never returns null.
    3.22 @@ -402,6 +405,7 @@
    3.23      public static native void onNativeKeyDown(int keycode);
    3.24      public static native void onNativeKeyUp(int keycode);
    3.25      public static native void onNativeKeyboardFocusLost();
    3.26 +    public static native void onNativeMouse(int button, int action, float x, float y);
    3.27      public static native void onNativeTouch(int touchDevId, int pointerFingerId,
    3.28                                              int action, float x, 
    3.29                                              float y, float p);
    3.30 @@ -1088,8 +1092,8 @@
    3.31          // Dispatch the different events depending on where they come from
    3.32          // Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
    3.33          // So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD
    3.34 -        
    3.35 -        if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */
    3.36 +
    3.37 +        if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 ||
    3.38                     (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
    3.39              if (event.getAction() == KeyEvent.ACTION_DOWN) {
    3.40                  if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
    3.41 @@ -1126,50 +1130,65 @@
    3.42          final int pointerCount = event.getPointerCount();
    3.43          int action = event.getActionMasked();
    3.44          int pointerFingerId;
    3.45 +        int mouseButton;
    3.46          int i = -1;
    3.47          float x,y,p;
    3.48 -        
    3.49 -        switch(action) {
    3.50 -            case MotionEvent.ACTION_MOVE:
    3.51 -                for (i = 0; i < pointerCount; i++) {
    3.52 +
    3.53 +        // !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
    3.54 +        if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
    3.55 +            if (Build.VERSION.SDK_INT < 14) {
    3.56 +                mouseButton = 1;    // For Android==12 all mouse buttons are the left button
    3.57 +            } else {
    3.58 +                try {
    3.59 +                    mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event);
    3.60 +                } catch(Exception e) {
    3.61 +                    mouseButton = 1;    // oh well.
    3.62 +                }
    3.63 +            }
    3.64 +            SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
    3.65 +        } else {
    3.66 +            switch(action) {
    3.67 +                case MotionEvent.ACTION_MOVE:
    3.68 +                    for (i = 0; i < pointerCount; i++) {
    3.69 +                        pointerFingerId = event.getPointerId(i);
    3.70 +                        x = event.getX(i) / mWidth;
    3.71 +                        y = event.getY(i) / mHeight;
    3.72 +                        p = event.getPressure(i);
    3.73 +                        SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
    3.74 +                    }
    3.75 +                    break;
    3.76 +                
    3.77 +                case MotionEvent.ACTION_UP:
    3.78 +                case MotionEvent.ACTION_DOWN:
    3.79 +                    // Primary pointer up/down, the index is always zero
    3.80 +                    i = 0;
    3.81 +                case MotionEvent.ACTION_POINTER_UP:
    3.82 +                case MotionEvent.ACTION_POINTER_DOWN:
    3.83 +                    // Non primary pointer up/down
    3.84 +                    if (i == -1) {
    3.85 +                        i = event.getActionIndex();
    3.86 +                    }
    3.87 +                    
    3.88                      pointerFingerId = event.getPointerId(i);
    3.89                      x = event.getX(i) / mWidth;
    3.90                      y = event.getY(i) / mHeight;
    3.91                      p = event.getPressure(i);
    3.92                      SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
    3.93 -                }
    3.94 -                break;
    3.95 -            
    3.96 -            case MotionEvent.ACTION_UP:
    3.97 -            case MotionEvent.ACTION_DOWN:
    3.98 -                // Primary pointer up/down, the index is always zero
    3.99 -                i = 0;
   3.100 -            case MotionEvent.ACTION_POINTER_UP:
   3.101 -            case MotionEvent.ACTION_POINTER_DOWN:
   3.102 -                // Non primary pointer up/down
   3.103 -                if (i == -1) {
   3.104 -                    i = event.getActionIndex();
   3.105 -                }
   3.106 +                    break;
   3.107                  
   3.108 -                pointerFingerId = event.getPointerId(i);
   3.109 -                x = event.getX(i) / mWidth;
   3.110 -                y = event.getY(i) / mHeight;
   3.111 -                p = event.getPressure(i);
   3.112 -                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
   3.113 -                break;
   3.114 -            
   3.115 -            case MotionEvent.ACTION_CANCEL:
   3.116 -                for (i = 0; i < pointerCount; i++) {
   3.117 -                    pointerFingerId = event.getPointerId(i);
   3.118 -                    x = event.getX(i) / mWidth;
   3.119 -                    y = event.getY(i) / mHeight;
   3.120 -                    p = event.getPressure(i);
   3.121 -                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
   3.122 -                }
   3.123 -                break;
   3.124 +                case MotionEvent.ACTION_CANCEL:
   3.125 +                    for (i = 0; i < pointerCount; i++) {
   3.126 +                        pointerFingerId = event.getPointerId(i);
   3.127 +                        x = event.getX(i) / mWidth;
   3.128 +                        y = event.getY(i) / mHeight;
   3.129 +                        p = event.getPressure(i);
   3.130 +                        SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
   3.131 +                    }
   3.132 +                    break;
   3.133  
   3.134 -            default:
   3.135 -                break;
   3.136 +                default:
   3.137 +                    break;
   3.138 +            }
   3.139          }
   3.140  
   3.141          return true;
   3.142 @@ -1500,9 +1519,44 @@
   3.143  
   3.144  class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
   3.145      // Generic Motion (mouse hover, joystick...) events go here
   3.146 -    // We only have joysticks yet
   3.147      @Override
   3.148      public boolean onGenericMotion(View v, MotionEvent event) {
   3.149 -        return SDLActivity.handleJoystickMotionEvent(event);
   3.150 +        float x, y;
   3.151 +        int mouseButton;
   3.152 +        int action;
   3.153 +
   3.154 +        switch ( event.getSource() ) {
   3.155 +            case InputDevice.SOURCE_JOYSTICK:
   3.156 +            case InputDevice.SOURCE_GAMEPAD:
   3.157 +            case InputDevice.SOURCE_DPAD:
   3.158 +                SDLActivity.handleJoystickMotionEvent(event);
   3.159 +                return true;
   3.160 +
   3.161 +            case InputDevice.SOURCE_MOUSE:
   3.162 +                action = event.getActionMasked();
   3.163 +                switch(event.getActionMasked()) {
   3.164 +                    case MotionEvent.ACTION_SCROLL:
   3.165 +                        x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
   3.166 +                        y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
   3.167 +                        SDLActivity.onNativeMouse(0, action, x, y);
   3.168 +                        return true;
   3.169 +
   3.170 +                    case MotionEvent.ACTION_HOVER_MOVE:
   3.171 +                        x = event.getX(0);
   3.172 +                        y = event.getY(0);
   3.173 +
   3.174 +                        SDLActivity.onNativeMouse(0, action, x, y);
   3.175 +                        return true;
   3.176 +
   3.177 +                    default:
   3.178 +                        break;
   3.179 +                }
   3.180 +
   3.181 +            default:
   3.182 +                break;
   3.183 +        }
   3.184 +
   3.185 +        // Event was not managed
   3.186 +        return false;
   3.187      }
   3.188  }
     4.1 --- a/cmake/sdlchecks.cmake	Sat Jan 24 23:58:07 2015 -0400
     4.2 +++ b/cmake/sdlchecks.cmake	Mon Apr 06 15:26:37 2015 -0300
     4.3 @@ -505,8 +505,13 @@
     4.4    endif()
     4.5  endmacro()
     4.6  
     4.7 +# Requires:
     4.8 +# - EGL
     4.9 +# - PkgCheckModules
    4.10 +# Optional:
    4.11 +# - MIR_SHARED opt
    4.12 +# - HAVE_DLOPEN opt
    4.13  macro(CheckMir)
    4.14 -# !!! FIXME: hook up dynamic loading here.
    4.15      if(VIDEO_MIR)
    4.16          find_library(MIR_LIB mirclient mircommon egl)
    4.17          pkg_check_modules(MIR_TOOLKIT mirclient mircommon)
    4.18 @@ -522,15 +527,31 @@
    4.19              set(SDL_VIDEO_DRIVER_MIR 1)
    4.20  
    4.21              list(APPEND EXTRA_CFLAGS ${MIR_TOOLKIT_CFLAGS} ${EGL_CLFAGS} ${XKB_CLFLAGS})
    4.22 -            list(APPEND EXTRA_LDFLAGS ${MIR_TOOLKIT_LDFLAGS} ${EGL_LDLAGS} ${XKB_LDLAGS})
    4.23 -        endif (MIR_LIB AND MIR_TOOLKIT_FOUND AND EGL_FOUND AND XKB_FOUND)
    4.24 +
    4.25 +            if(MIR_SHARED)
    4.26 +                if(NOT HAVE_DLOPEN)
    4.27 +                    message_warn("You must have SDL_LoadObject() support for dynamic Mir loading")
    4.28 +                else()
    4.29 +                    FindLibraryAndSONAME(mirclient)
    4.30 +                    FindLibraryAndSONAME(xkbcommon)
    4.31 +                    set(SDL_VIDEO_DRIVER_MIR_DYNAMIC "\"${MIRCLIENT_LIB_SONAME}\"")
    4.32 +                    set(SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"")
    4.33 +                    set(HAVE_MIR_SHARED TRUE)
    4.34 +                endif()
    4.35 +            else()
    4.36 +                set(EXTRA_LIBS ${MIR_TOOLKIT_LIBRARIES} ${EXTRA_LIBS})
    4.37 +            endif()
    4.38 +        endif()
    4.39      endif()
    4.40  endmacro()
    4.41  
    4.42  # Requires:
    4.43  # - EGL
    4.44 +# - PkgCheckModules
    4.45 +# Optional:
    4.46 +# - WAYLAND_SHARED opt
    4.47 +# - HAVE_DLOPEN opt
    4.48  macro(CheckWayland)
    4.49 -# !!! FIXME: hook up dynamic loading here.
    4.50    if(VIDEO_WAYLAND)
    4.51      pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon)
    4.52      if(WAYLAND_FOUND)
    4.53 @@ -540,12 +561,34 @@
    4.54        include_directories(
    4.55            ${WAYLAND_INCLUDE_DIRS}
    4.56        )
    4.57 -      set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
    4.58        set(HAVE_VIDEO_WAYLAND TRUE)
    4.59        set(HAVE_SDL_VIDEO TRUE)
    4.60  
    4.61        file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
    4.62        set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
    4.63 +
    4.64 +      if(VIDEO_WAYLAND_QT_TOUCH)
    4.65 +          set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
    4.66 +      endif()
    4.67 +
    4.68 +      if(WAYLAND_SHARED)
    4.69 +        if(NOT HAVE_DLOPEN)
    4.70 +          message_warn("You must have SDL_LoadObject() support for dynamic Wayland loading")
    4.71 +        else()
    4.72 +          FindLibraryAndSONAME(wayland-client)
    4.73 +          FindLibraryAndSONAME(wayland-egl)
    4.74 +          FindLibraryAndSONAME(wayland-cursor)
    4.75 +          FindLibraryAndSONAME(xkbcommon)
    4.76 +          set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC "\"${WAYLAND_CLIENT_LIB_SONAME}\"")
    4.77 +          set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL "\"${WAYLAND_EGL_LIB_SONAME}\"")
    4.78 +          set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR "\"${WAYLAND_CURSOR_LIB_SONAME}\"")
    4.79 +          set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"")
    4.80 +          set(HAVE_WAYLAND_SHARED TRUE)
    4.81 +        endif()
    4.82 +      else()
    4.83 +        set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS})
    4.84 +      endif()
    4.85 +
    4.86        set(SDL_VIDEO_DRIVER_WAYLAND 1)
    4.87      endif()
    4.88    endif()
    4.89 @@ -682,7 +725,7 @@
    4.90    endif()
    4.91  endmacro()
    4.92  
    4.93 -# Rquires:
    4.94 +# Requires:
    4.95  # - nada
    4.96  # Optional:
    4.97  # - THREADS opt
    4.98 @@ -733,13 +776,17 @@
    4.99  
   4.100      # Run some tests
   4.101      set(CMAKE_REQUIRED_FLAGS "${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
   4.102 -    check_c_source_runs("
   4.103 +    if(CMAKE_CROSSCOMPILING)
   4.104 +      set(HAVE_PTHREADS 1)
   4.105 +    else()
   4.106 +      check_c_source_runs("
   4.107          #include <pthread.h>
   4.108          int main(int argc, char** argv) {
   4.109            pthread_attr_t type;
   4.110            pthread_attr_init(&type);
   4.111            return 0;
   4.112          }" HAVE_PTHREADS)
   4.113 +    endif()
   4.114      if(HAVE_PTHREADS)
   4.115        set(SDL_THREAD_PTHREAD 1)
   4.116        list(APPEND EXTRA_CFLAGS ${PTHREAD_CFLAGS})
   4.117 @@ -788,8 +835,8 @@
   4.118            #include <pthread.h>
   4.119            #include <pthread_np.h>
   4.120            int main(int argc, char** argv) { return 0; }" HAVE_PTHREAD_NP_H)
   4.121 -      check_function_exists(pthread_setname_np HAVE_PTHREAD_setNAME_NP)
   4.122 -      check_function_exists(pthread_set_name_np HAVE_PTHREAD_set_NAME_NP)
   4.123 +      check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
   4.124 +      check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP)
   4.125        set(CMAKE_REQUIRED_FLAGS)
   4.126  
   4.127        set(SOURCE_FILES ${SOURCE_FILES}
     5.1 --- a/configure	Sat Jan 24 23:58:07 2015 -0400
     5.2 +++ b/configure	Mon Apr 06 15:26:37 2015 -0300
     5.3 @@ -21916,6 +21916,7 @@
     5.4                  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     5.5  /* end confdefs.h.  */
     5.6  
     5.7 +                  #define _GNU_SOURCE 1
     5.8                    #include <pthread.h>
     5.9  
    5.10  int
    5.11 @@ -21929,7 +21930,7 @@
    5.12    return 0;
    5.13  }
    5.14  _ACEOF
    5.15 -if ac_fn_c_try_compile "$LINENO"; then :
    5.16 +if ac_fn_c_try_link "$LINENO"; then :
    5.17  
    5.18                  has_recursive_mutexes=yes
    5.19  
    5.20 @@ -21937,12 +21938,14 @@
    5.21  
    5.22  
    5.23  fi
    5.24 -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    5.25 +rm -f core conftest.err conftest.$ac_objext \
    5.26 +    conftest$ac_exeext conftest.$ac_ext
    5.27              fi
    5.28              if test x$has_recursive_mutexes = xno; then
    5.29                  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
    5.30  /* end confdefs.h.  */
    5.31  
    5.32 +                  #define _GNU_SOURCE 1
    5.33                    #include <pthread.h>
    5.34  
    5.35  int
    5.36 @@ -21956,7 +21959,7 @@
    5.37    return 0;
    5.38  }
    5.39  _ACEOF
    5.40 -if ac_fn_c_try_compile "$LINENO"; then :
    5.41 +if ac_fn_c_try_link "$LINENO"; then :
    5.42  
    5.43                  has_recursive_mutexes=yes
    5.44  
    5.45 @@ -21964,7 +21967,8 @@
    5.46  
    5.47  
    5.48  fi
    5.49 -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
    5.50 +rm -f core conftest.err conftest.$ac_objext \
    5.51 +    conftest$ac_exeext conftest.$ac_ext
    5.52              fi
    5.53              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_recursive_mutexes" >&5
    5.54  $as_echo "$has_recursive_mutexes" >&6; }
    5.55 @@ -23091,11 +23095,22 @@
    5.56          fi
    5.57          # Set up files for the filesystem library
    5.58          if test x$enable_filesystem = xyes; then
    5.59 +             case $ARCH in
    5.60 +               android)
    5.61 +
    5.62 +$as_echo "#define SDL_FILESYSTEM_ANDROID 1" >>confdefs.h
    5.63 +
    5.64 +                   SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c"
    5.65 +                   have_filesystem=yes
    5.66 +               ;;
    5.67 +               *)
    5.68  
    5.69  $as_echo "#define SDL_FILESYSTEM_UNIX 1" >>confdefs.h
    5.70  
    5.71 -            SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
    5.72 -            have_filesystem=yes
    5.73 +                   SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
    5.74 +                   have_filesystem=yes
    5.75 +               ;;
    5.76 +             esac
    5.77          fi
    5.78          # Set up files for the timer library
    5.79          if test x$enable_timers = xyes; then
     6.1 --- a/configure.in	Sat Jan 24 23:58:07 2015 -0400
     6.2 +++ b/configure.in	Mon Apr 06 15:26:37 2015 -0300
     6.3 @@ -2424,7 +2424,8 @@
     6.4              AC_MSG_CHECKING(for recursive mutexes)
     6.5              has_recursive_mutexes=no
     6.6              if test x$has_recursive_mutexes = xno; then
     6.7 -                AC_TRY_COMPILE([
     6.8 +                AC_TRY_LINK([
     6.9 +                  #define _GNU_SOURCE 1
    6.10                    #include <pthread.h>
    6.11                  ],[
    6.12                    pthread_mutexattr_t attr;
    6.13 @@ -2435,7 +2436,8 @@
    6.14                  ])
    6.15              fi
    6.16              if test x$has_recursive_mutexes = xno; then
    6.17 -                AC_TRY_COMPILE([
    6.18 +                AC_TRY_LINK([
    6.19 +                  #define _GNU_SOURCE 1
    6.20                    #include <pthread.h>
    6.21                  ],[
    6.22                    pthread_mutexattr_t attr;
    6.23 @@ -2971,9 +2973,18 @@
    6.24          fi
    6.25          # Set up files for the filesystem library
    6.26          if test x$enable_filesystem = xyes; then
    6.27 -            AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ])
    6.28 -            SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
    6.29 -            have_filesystem=yes
    6.30 +             case $ARCH in
    6.31 +               android)
    6.32 +                   AC_DEFINE(SDL_FILESYSTEM_ANDROID, 1, [ ])
    6.33 +                   SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c"
    6.34 +                   have_filesystem=yes
    6.35 +               ;;
    6.36 +               *)
    6.37 +                   AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ])
    6.38 +                   SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c"
    6.39 +                   have_filesystem=yes
    6.40 +               ;;
    6.41 +             esac
    6.42          fi
    6.43          # Set up files for the timer library
    6.44          if test x$enable_timers = xyes; then
     7.1 --- a/docs/README-platforms.md	Sat Jan 24 23:58:07 2015 -0400
     7.2 +++ b/docs/README-platforms.md	Mon Apr 06 15:26:37 2015 -0300
     7.3 @@ -1,34 +1,8 @@
     7.4  Platforms
     7.5  =========
     7.6  
     7.7 -
     7.8 -This is a list of the platforms SDL supports, and who maintains them.
     7.9 -
    7.10 -Officially supported platforms
    7.11 -==============================
    7.12 -(code compiles, and thoroughly tested for release)
    7.13 -==============================
    7.14 -* Windows XP/Vista/7/8
    7.15 -* Mac OS X 10.5+
    7.16 -* Linux 2.6+
    7.17 -* iOS 5.1.1+
    7.18 -* Android 2.3.3+
    7.19 -
    7.20 -Unofficially supported platforms
    7.21 -================================
    7.22 -(code compiles, but not thoroughly tested)
    7.23 -================================
    7.24 -* FreeBSD
    7.25 -* NetBSD
    7.26 -* OpenBSD
    7.27 -* Solaris
    7.28 -
    7.29 -Platforms supported by volunteers
    7.30 -=================================
    7.31 -* Haiku - maintained by Axel Dörfler <axeld@pinc-software.de>
    7.32 -* PSP - maintained by 527721088@qq.com
    7.33 -* Pandora - maintained by Scott Smith <pickle136@sbcglobal.net>
    7.34 -* NaCl - maintained by Gabriel Jacobo <gabomdq@gmail.com>
    7.35 -
    7.36 -Platforms that need maintainers
    7.37 -===============================
    7.38 +We maintain the list of supported platforms on our wiki now, and how to
    7.39 +build and install SDL for those platforms:
    7.40 +
    7.41 +    https://wiki.libsdl.org/Installation
    7.42 +
     8.1 --- a/docs/README-porting.md	Sat Jan 24 23:58:07 2015 -0400
     8.2 +++ b/docs/README-porting.md	Mon Apr 06 15:26:37 2015 -0300
     8.3 @@ -15,7 +15,7 @@
     8.4  
     8.5     If you have a GNUish system, then you might try this.  Edit configure.in,
     8.6     take a look at the large section labelled:
     8.7 -	"Set up the configuration based on the target platform!"
     8.8 +	"Set up the configuration based on the host platform!"
     8.9     Add a section for your platform, and then re-run autogen.sh and build!
    8.10  
    8.11  2. Using an IDE:
     9.1 --- a/docs/README-winrt.md	Sat Jan 24 23:58:07 2015 -0400
     9.2 +++ b/docs/README-winrt.md	Mon Apr 06 15:26:37 2015 -0300
     9.3 @@ -90,10 +90,12 @@
     9.4    * keyboard input.  Most of WinRT's documented virtual keys are supported, as
     9.5      well as many keys with documented hardware scancodes.
     9.6    * OpenGL.  Experimental support for OpenGL ES 2 is available via the ANGLE
     9.7 -    project, using either MS Open Technologies' repository, at 
     9.8 -    https://github.com/msopentech/angle (both the "winrt" and "future-dev"
     9.9 -    branches are supported), or the official ANGLE repository, at
    9.10 -    https://chromium.googlesource.com/angle/angle
    9.11 +    project, using either:
    9.12 +    * MS Open Technologies' "ms-master" repository, at https://github.com/MSOpenTech/angle
    9.13 +      (for use with Windows 8.1+ or Windows Phone 8.1+)
    9.14 +    * MS Open Technologies' "angle-win8.0" repository, at https://github.com/MSOpenTech/angle-win8.0
    9.15 +      (for Windows 8.0 only!)
    9.16 +    * Google's main ANGLE repository, at https://chromium.googlesource.com/angle/angle
    9.17    * SDLmain.  WinRT uses a different signature for each app's main() function.
    9.18      SDL-based apps that use this port must compile in SDL_winrt_main_NonXAML.cpp
    9.19      (in `SDL\src\main\winrt\`) directly in order for their C-style main()
    9.20 @@ -112,6 +114,11 @@
    9.21      supported by WinRT itself.
    9.22    * joysticks and game controllers that aren't supported by Microsoft's XInput
    9.23      API.
    9.24 +  * turning off VSync when rendering on Windows Phone.  Attempts to turn VSync
    9.25 +    off on Windows Phone result either in Direct3D not drawing anything, or it
    9.26 +    forcing VSync back on.  As such, SDL_RENDERER_PRESENTVSYNC will always get
    9.27 +    turned-on on Windows Phone.  This limitation is not present in non-Phone
    9.28 +    WinRT (such as Windows 8.x), where turning off VSync appears to work.
    9.29    * probably anything else that's not listed as supported
    9.30  
    9.31  
    10.1 --- a/include/SDL_assert.h	Sat Jan 24 23:58:07 2015 -0400
    10.2 +++ b/include/SDL_assert.h	Mon Apr 06 15:26:37 2015 -0300
    10.3 @@ -102,9 +102,9 @@
    10.4      SDL_ASSERTION_ABORT,  /**< Terminate the program. */
    10.5      SDL_ASSERTION_IGNORE,  /**< Ignore the assert. */
    10.6      SDL_ASSERTION_ALWAYS_IGNORE  /**< Ignore the assert from now on. */
    10.7 -} SDL_assert_state;
    10.8 +} SDL_AssertState;
    10.9  
   10.10 -typedef struct SDL_assert_data
   10.11 +typedef struct SDL_AssertData
   10.12  {
   10.13      int always_ignore;
   10.14      unsigned int trigger_count;
   10.15 @@ -112,13 +112,13 @@
   10.16      const char *filename;
   10.17      int linenum;
   10.18      const char *function;
   10.19 -    const struct SDL_assert_data *next;
   10.20 -} SDL_assert_data;
   10.21 +    const struct SDL_AssertData *next;
   10.22 +} SDL_AssertData;
   10.23  
   10.24  #if (SDL_ASSERT_LEVEL > 0)
   10.25  
   10.26  /* Never call this directly. Use the SDL_assert* macros. */
   10.27 -extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
   10.28 +extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
   10.29                                                               const char *,
   10.30                                                               const char *, int)
   10.31  #if defined(__clang__)
   10.32 @@ -141,10 +141,10 @@
   10.33  #define SDL_enabled_assert(condition) \
   10.34      do { \
   10.35          while ( !(condition) ) { \
   10.36 -            static struct SDL_assert_data sdl_assert_data = { \
   10.37 +            static struct SDL_AssertData sdl_assert_data = { \
   10.38                  0, 0, #condition, 0, 0, 0, 0 \
   10.39              }; \
   10.40 -            const SDL_assert_state sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
   10.41 +            const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
   10.42              if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
   10.43                  continue; /* go again. */ \
   10.44              } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
   10.45 @@ -181,8 +181,8 @@
   10.46  #define SDL_assert_always(condition) SDL_enabled_assert(condition)
   10.47  
   10.48  
   10.49 -typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
   10.50 -                                 const SDL_assert_data* data, void* userdata);
   10.51 +typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
   10.52 +                                 const SDL_AssertData* data, void* userdata);
   10.53  
   10.54  /**
   10.55   *  \brief Set an application-defined assertion handler.
   10.56 @@ -199,7 +199,7 @@
   10.57   *
   10.58   *  This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
   10.59   *
   10.60 - *  \return SDL_assert_state value of how to handle the assertion failure.
   10.61 + *  \return SDL_AssertState value of how to handle the assertion failure.
   10.62   *
   10.63   *  \param handler Callback function, called when an assertion fails.
   10.64   *  \param userdata A pointer passed to the callback as-is.
   10.65 @@ -246,7 +246,7 @@
   10.66   *  The proper way to examine this data looks something like this:
   10.67   *
   10.68   *  <code>
   10.69 - *  const SDL_assert_data *item = SDL_GetAssertionReport();
   10.70 + *  const SDL_AssertData *item = SDL_GetAssertionReport();
   10.71   *  while (item) {
   10.72   *      printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
   10.73   *             item->condition, item->function, item->filename,
   10.74 @@ -259,7 +259,7 @@
   10.75   *  \return List of all assertions.
   10.76   *  \sa SDL_ResetAssertionReport
   10.77   */
   10.78 -extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void);
   10.79 +extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
   10.80  
   10.81  /**
   10.82   *  \brief Reset the list of all assertion failures.
   10.83 @@ -270,6 +270,12 @@
   10.84   */
   10.85  extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
   10.86  
   10.87 +
   10.88 +/* these had wrong naming conventions until 2.0.4. Please update your app! */
   10.89 +#define SDL_assert_state SDL_AssertState
   10.90 +#define SDL_assert_data SDL_AssertData
   10.91 +
   10.92 +
   10.93  /* Ends C function definitions when using C++ */
   10.94  #ifdef __cplusplus
   10.95  }
    11.1 --- a/include/SDL_config.h.cmake	Sat Jan 24 23:58:07 2015 -0400
    11.2 +++ b/include/SDL_config.h.cmake	Mon Apr 06 15:26:37 2015 -0300
    11.3 @@ -269,14 +269,11 @@
    11.4  #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@
    11.5  #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@
    11.6  
    11.7 -#if 0
    11.8 -/* !!! FIXME: in configure script version, missing here: */
    11.9 -#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
   11.10 -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
   11.11 -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL
   11.12 -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR
   11.13 -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON
   11.14 -#endif
   11.15 +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@
   11.16 +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@
   11.17 +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
   11.18 +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@
   11.19 +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
   11.20  
   11.21  #cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@
   11.22  #cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@
    12.1 --- a/include/SDL_config.h.in	Sat Jan 24 23:58:07 2015 -0400
    12.2 +++ b/include/SDL_config.h.in	Mon Apr 06 15:26:37 2015 -0300
    12.3 @@ -349,6 +349,7 @@
    12.4  #undef SDL_FILESYSTEM_UNIX
    12.5  #undef SDL_FILESYSTEM_WINDOWS
    12.6  #undef SDL_FILESYSTEM_NACL
    12.7 +#undef SDL_FILESYSTEM_ANDROID
    12.8  #undef SDL_FILESYSTEM_EMSCRIPTEN
    12.9  
   12.10  /* Enable assembly routines */
    13.1 --- a/include/SDL_events.h	Sat Jan 24 23:58:07 2015 -0400
    13.2 +++ b/include/SDL_events.h	Mon Apr 06 15:26:37 2015 -0300
    13.3 @@ -134,6 +134,10 @@
    13.4      /* Drag and drop events */
    13.5      SDL_DROPFILE        = 0x1000, /**< The system requests a file open */
    13.6  
    13.7 +    /* Audio hotplug events */
    13.8 +    SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
    13.9 +    SDL_AUDIODEVICEREMOVED,        /**< An audio device has been removed. */
   13.10 +
   13.11      /* Render events */
   13.12      SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
   13.13      SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
   13.14 @@ -382,6 +386,20 @@
   13.15      Sint32 which;       /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
   13.16  } SDL_ControllerDeviceEvent;
   13.17  
   13.18 +/**
   13.19 + *  \brief Audio device event structure (event.adevice.*)
   13.20 + */
   13.21 +typedef struct SDL_AudioDeviceEvent
   13.22 +{
   13.23 +    Uint32 type;        /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
   13.24 +    Uint32 timestamp;
   13.25 +    Uint32 which;       /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
   13.26 +    Uint8 iscapture;    /**< zero if an output device, non-zero if a capture device. */
   13.27 +    Uint8 padding1;
   13.28 +    Uint8 padding2;
   13.29 +    Uint8 padding3;
   13.30 +} SDL_AudioDeviceEvent;
   13.31 +
   13.32  
   13.33  /**
   13.34   *  \brief Touch finger event structure (event.tfinger.*)
   13.35 @@ -422,7 +440,7 @@
   13.36   */
   13.37  typedef struct SDL_DollarGestureEvent
   13.38  {
   13.39 -    Uint32 type;        /**< ::SDL_DOLLARGESTURE */
   13.40 +    Uint32 type;        /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
   13.41      Uint32 timestamp;
   13.42      SDL_TouchID touchId; /**< The touch device id */
   13.43      SDL_GestureID gestureId;
   13.44 @@ -516,6 +534,7 @@
   13.45      SDL_ControllerAxisEvent caxis;      /**< Game Controller axis event data */
   13.46      SDL_ControllerButtonEvent cbutton;  /**< Game Controller button event data */
   13.47      SDL_ControllerDeviceEvent cdevice;  /**< Game Controller device event data */
   13.48 +    SDL_AudioDeviceEvent adevice;   /**< Audio device event data */
   13.49      SDL_QuitEvent quit;             /**< Quit request event data */
   13.50      SDL_UserEvent user;             /**< Custom event data */
   13.51      SDL_SysWMEvent syswm;           /**< System dependent window event data */
    14.1 --- a/include/SDL_gamecontroller.h	Sat Jan 24 23:58:07 2015 -0400
    14.2 +++ b/include/SDL_gamecontroller.h	Mon Apr 06 15:26:37 2015 -0300
    14.3 @@ -241,7 +241,8 @@
    14.4  /**
    14.5   *  Get the current state of an axis control on a game controller.
    14.6   *
    14.7 - *  The state is a value ranging from -32768 to 32767.
    14.8 + *  The state is a value ranging from -32768 to 32767 (except for the triggers,
    14.9 + *  which range from 0 to 32767).
   14.10   *
   14.11   *  The axis indices start at index 0.
   14.12   */
    15.1 --- a/include/SDL_hints.h	Sat Jan 24 23:58:07 2015 -0400
    15.2 +++ b/include/SDL_hints.h	Mon Apr 06 15:26:37 2015 -0300
    15.3 @@ -533,6 +533,18 @@
    15.4   */
    15.5  #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
    15.6  
    15.7 + /**
    15.8 + * \brief A variable to control whether mouse and touch events are to be treated together or separately
    15.9 + *
   15.10 + * The variable can be set to the following values:
   15.11 + *   "0"       - Mouse events will be handled as touch events, and touch will raise fake mouse
   15.12 + *               events. This is the behaviour of SDL <= 2.0.3. (default)
   15.13 + *   "1"       - Mouse events will be handled separately from pure touch events.
   15.14 + *
   15.15 + * The value of this hint is used at runtime, so it can be changed at any time.
   15.16 + */
   15.17 +#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"
   15.18 +
   15.19  /**
   15.20   *  \brief override the binding element for keyboard inputs for Emscripten builds
   15.21   *
   15.22 @@ -548,6 +560,18 @@
   15.23  #define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT   "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
   15.24  
   15.25  /**
   15.26 + *  \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
   15.27 + *
   15.28 + * This hint only applies to Unix-like platforms.
   15.29 + *
   15.30 + * The variable can be set to the following values:
   15.31 + *   "0"       - SDL will install a SIGINT and SIGTERM handler, and when it
   15.32 + *               catches a signal, convert it into an SDL_QUIT event.
   15.33 + *   "1"       - SDL will not install a signal handler at all.
   15.34 + */
   15.35 +#define SDL_HINT_NO_SIGNAL_HANDLERS   "SDL_NO_SIGNAL_HANDLERS"
   15.36 +
   15.37 +/**
   15.38   *  \brief  An enumeration of hint priorities
   15.39   */
   15.40  typedef enum
    16.1 --- a/include/SDL_opengl_glext.h	Sat Jan 24 23:58:07 2015 -0400
    16.2 +++ b/include/SDL_opengl_glext.h	Mon Apr 06 15:26:37 2015 -0300
    16.3 @@ -2988,6 +2988,11 @@
    16.4  #define GL_ARB_framebuffer_sRGB 1
    16.5  #endif /* GL_ARB_framebuffer_sRGB */
    16.6  
    16.7 +#ifndef GL_KHR_context_flush_control
    16.8 +#define GL_CONTEXT_RELEASE_BEHAVIOR       0x82FB
    16.9 +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
   16.10 +#endif /* GL_KHR_context_flush_control */
   16.11 +
   16.12  #ifndef GL_ARB_geometry_shader4
   16.13  #define GL_ARB_geometry_shader4 1
   16.14  #define GL_LINES_ADJACENCY_ARB            0x000A
    17.1 --- a/include/SDL_render.h	Sat Jan 24 23:58:07 2015 -0400
    17.2 +++ b/include/SDL_render.h	Mon Apr 06 15:26:37 2015 -0300
    17.3 @@ -81,8 +81,8 @@
    17.4      Uint32 flags;               /**< Supported ::SDL_RendererFlags */
    17.5      Uint32 num_texture_formats; /**< The number of available texture formats */
    17.6      Uint32 texture_formats[16]; /**< The available texture formats */
    17.7 -    int max_texture_width;      /**< The maximimum texture width */
    17.8 -    int max_texture_height;     /**< The maximimum texture height */
    17.9 +    int max_texture_width;      /**< The maximum texture width */
   17.10 +    int max_texture_height;     /**< The maximum texture height */
   17.11  } SDL_RendererInfo;
   17.12  
   17.13  /**
   17.14 @@ -792,7 +792,7 @@
   17.15   *  \param dstrect   A pointer to the destination rectangle, or NULL for the
   17.16   *                   entire rendering target.
   17.17   *  \param angle    An angle in degrees that indicates the rotation that will be applied to dstrect
   17.18 - *  \param center   A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2)
   17.19 + *  \param center   A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2).
   17.20   *  \param flip     An SDL_RendererFlip value stating which flipping actions should be performed on the texture
   17.21   *
   17.22   *  \return 0 on success, or -1 on error
    18.1 --- a/include/SDL_stdinc.h	Sat Jan 24 23:58:07 2015 -0400
    18.2 +++ b/include/SDL_stdinc.h	Mon Apr 06 15:26:37 2015 -0300
    18.3 @@ -173,6 +173,8 @@
    18.4  #define SDL_PRIs64 PRIs64
    18.5  #elif defined(__WIN32__)
    18.6  #define SDL_PRIs64 "I64d"
    18.7 +#elif defined(__LINUX__) && defined(__LP64__)
    18.8 +#define SDL_PRIs64 "ld"
    18.9  #else
   18.10  #define SDL_PRIs64 "lld"
   18.11  #endif
   18.12 @@ -182,6 +184,8 @@
   18.13  #define SDL_PRIu64 PRIu64
   18.14  #elif defined(__WIN32__)
   18.15  #define SDL_PRIu64 "I64u"
   18.16 +#elif defined(__LINUX__) && defined(__LP64__)
   18.17 +#define SDL_PRIu64 "lu"
   18.18  #else
   18.19  #define SDL_PRIu64 "llu"
   18.20  #endif
   18.21 @@ -191,6 +195,8 @@
   18.22  #define SDL_PRIx64 PRIx64
   18.23  #elif defined(__WIN32__)
   18.24  #define SDL_PRIx64 "I64x"
   18.25 +#elif defined(__LINUX__) && defined(__LP64__)
   18.26 +#define SDL_PRIx64 "lx"
   18.27  #else
   18.28  #define SDL_PRIx64 "llx"
   18.29  #endif
   18.30 @@ -200,6 +206,8 @@
   18.31  #define SDL_PRIX64 PRIX64
   18.32  #elif defined(__WIN32__)
   18.33  #define SDL_PRIX64 "I64X"
   18.34 +#elif defined(__LINUX__) && defined(__LP64__)
   18.35 +#define SDL_PRIX64 "lX"
   18.36  #else
   18.37  #define SDL_PRIX64 "llX"
   18.38  #endif
    19.1 --- a/include/SDL_syswm.h	Sat Jan 24 23:58:07 2015 -0400
    19.2 +++ b/include/SDL_syswm.h	Mon Apr 06 15:26:37 2015 -0300
    19.3 @@ -186,6 +186,7 @@
    19.4          struct
    19.5          {
    19.6              HWND window;                /**< The window handle */
    19.7 +            HDC hdc;                    /**< The window device context */
    19.8          } win;
    19.9  #endif
   19.10  #if defined(SDL_VIDEO_DRIVER_WINRT)
    20.1 --- a/include/SDL_video.h	Sat Jan 24 23:58:07 2015 -0400
    20.2 +++ b/include/SDL_video.h	Mon Apr 06 15:26:37 2015 -0300
    20.3 @@ -189,7 +189,8 @@
    20.4      SDL_GL_CONTEXT_FLAGS,
    20.5      SDL_GL_CONTEXT_PROFILE_MASK,
    20.6      SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
    20.7 -    SDL_GL_FRAMEBUFFER_SRGB_CAPABLE
    20.8 +    SDL_GL_FRAMEBUFFER_SRGB_CAPABLE,
    20.9 +    SDL_GL_CONTEXT_RELEASE_BEHAVIOR
   20.10  } SDL_GLattr;
   20.11  
   20.12  typedef enum
   20.13 @@ -207,6 +208,12 @@
   20.14      SDL_GL_CONTEXT_RESET_ISOLATION_FLAG    = 0x0008
   20.15  } SDL_GLcontextFlag;
   20.16  
   20.17 +typedef enum
   20.18 +{
   20.19 +    SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE   = 0x0000,
   20.20 +    SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH  = 0x0001
   20.21 +} SDL_GLcontextReleaseFlag;
   20.22 +
   20.23  
   20.24  /* Function prototypes */
   20.25  
   20.26 @@ -715,6 +722,9 @@
   20.27   *  \param window The window for which the input grab mode should be set.
   20.28   *  \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input.
   20.29   *
   20.30 + *  If the caller enables a grab while another window is currently grabbed,
   20.31 + *  the other window loses its grab in favor of the caller's window.
   20.32 + *
   20.33   *  \sa SDL_GetWindowGrab()
   20.34   */
   20.35  extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window,
   20.36 @@ -730,6 +740,15 @@
   20.37  extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window);
   20.38  
   20.39  /**
   20.40 + *  \brief Get the window that currently has an input grab enabled.
   20.41 + *
   20.42 + *  \return This returns the window if input is grabbed, and NULL otherwise.
   20.43 + *
   20.44 + *  \sa SDL_SetWindowGrab()
   20.45 + */
   20.46 +extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void);
   20.47 +
   20.48 +/**
   20.49   *  \brief Set the brightness (gamma correction) for a window.
   20.50   *
   20.51   *  \return 0 on success, or -1 if setting the brightness isn't supported.
    21.1 --- a/src/SDL.c	Sat Jan 24 23:58:07 2015 -0400
    21.2 +++ b/src/SDL.c	Mon Apr 06 15:26:37 2015 -0300
    21.3 @@ -405,6 +405,8 @@
    21.4      return "BSDI";
    21.5  #elif __DREAMCAST__
    21.6      return "Dreamcast";
    21.7 +#elif __EMSCRIPTEN__
    21.8 +    return "Emscripten";
    21.9  #elif __FREEBSD__
   21.10      return "FreeBSD";
   21.11  #elif __HAIKU__
    22.1 --- a/src/SDL_error.c	Sat Jan 24 23:58:07 2015 -0400
    22.2 +++ b/src/SDL_error.c	Mon Apr 06 15:26:37 2015 -0300
    22.3 @@ -120,7 +120,7 @@
    22.4     so that it supports internationalization and thread-safe errors.
    22.5  */
    22.6  static char *
    22.7 -SDL_GetErrorMsg(char *errstr, unsigned int maxlen)
    22.8 +SDL_GetErrorMsg(char *errstr, int maxlen)
    22.9  {
   22.10      SDL_error *error;
   22.11  
   22.12 @@ -163,37 +163,55 @@
   22.13                      len =
   22.14                          SDL_snprintf(msg, maxlen, tmp,
   22.15                                       error->args[argi++].value_i);
   22.16 -                    msg += len;
   22.17 -                    maxlen -= len;
   22.18 +                    if (len > 0) {
   22.19 +                        msg += len;
   22.20 +                        maxlen -= len;
   22.21 +                    }
   22.22                      break;
   22.23 +
   22.24                  case 'f':
   22.25                      len =
   22.26                          SDL_snprintf(msg, maxlen, tmp,
   22.27                                       error->args[argi++].value_f);
   22.28 -                    msg += len;
   22.29 -                    maxlen -= len;
   22.30 +                    if (len > 0) {
   22.31 +                        msg += len;
   22.32 +                        maxlen -= len;
   22.33 +                    }
   22.34                      break;
   22.35 +
   22.36                  case 'p':
   22.37                      len =
   22.38                          SDL_snprintf(msg, maxlen, tmp,
   22.39                                       error->args[argi++].value_ptr);
   22.40 -                    msg += len;
   22.41 -                    maxlen -= len;
   22.42 +                    if (len > 0) {
   22.43 +                        msg += len;
   22.44 +                        maxlen -= len;
   22.45 +                    }
   22.46                      break;
   22.47 +
   22.48                  case 's':
   22.49                      len =
   22.50                          SDL_snprintf(msg, maxlen, tmp,
   22.51                                       SDL_LookupString(error->args[argi++].
   22.52                                                        buf));
   22.53 -                    msg += len;
   22.54 -                    maxlen -= len;
   22.55 +                    if (len > 0) {
   22.56 +                        msg += len;
   22.57 +                        maxlen -= len;
   22.58 +                    }
   22.59                      break;
   22.60 +
   22.61                  }
   22.62              } else {
   22.63                  *msg++ = *fmt++;
   22.64                  maxlen -= 1;
   22.65              }
   22.66          }
   22.67 +
   22.68 +        /* slide back if we've overshot the end of our buffer. */
   22.69 +        if (maxlen < 0) {
   22.70 +            msg -= (-maxlen) + 1;
   22.71 +        }
   22.72 +
   22.73          *msg = 0;               /* NULL terminate the string */
   22.74      }
   22.75      return (errstr);
    23.1 --- a/src/audio/SDL_audio.c	Sat Jan 24 23:58:07 2015 -0400
    23.2 +++ b/src/audio/SDL_audio.c	Mon Apr 06 15:26:37 2015 -0300
    23.3 @@ -51,9 +51,7 @@
    23.4  extern AudioBootStrap SUNAUDIO_bootstrap;
    23.5  extern AudioBootStrap ARTS_bootstrap;
    23.6  extern AudioBootStrap ESD_bootstrap;
    23.7 -#if SDL_AUDIO_DRIVER_NACL
    23.8  extern AudioBootStrap NACLAUD_bootstrap;
    23.9 -#endif
   23.10  extern AudioBootStrap NAS_bootstrap;
   23.11  extern AudioBootStrap XAUDIO2_bootstrap;
   23.12  extern AudioBootStrap DSOUND_bootstrap;
   23.13 @@ -163,8 +161,16 @@
   23.14  
   23.15  /* stubs for audio drivers that don't need a specific entry point... */
   23.16  static void
   23.17 -SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
   23.18 -{                               /* no-op. */
   23.19 +SDL_AudioDetectDevices_Default(void)
   23.20 +{
   23.21 +    /* you have to write your own implementation if these assertions fail. */
   23.22 +    SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
   23.23 +    SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
   23.24 +
   23.25 +    SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
   23.26 +    if (current_audio.impl.HasCaptureSupport) {
   23.27 +        SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
   23.28 +    }
   23.29  }
   23.30  
   23.31  static void
   23.32 @@ -209,10 +215,16 @@
   23.33  {                               /* no-op. */
   23.34  }
   23.35  
   23.36 +static void
   23.37 +SDL_AudioFreeDeviceHandle_Default(void *handle)
   23.38 +{                               /* no-op. */
   23.39 +}
   23.40 +
   23.41 +
   23.42  static int
   23.43 -SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
   23.44 +SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
   23.45  {
   23.46 -    return -1;
   23.47 +    return SDL_Unsupported();
   23.48  }
   23.49  
   23.50  static SDL_INLINE SDL_bool
   23.51 @@ -269,71 +281,139 @@
   23.52      FILL_STUB(CloseDevice);
   23.53      FILL_STUB(LockDevice);
   23.54      FILL_STUB(UnlockDevice);
   23.55 +    FILL_STUB(FreeDeviceHandle);
   23.56      FILL_STUB(Deinitialize);
   23.57  #undef FILL_STUB
   23.58  }
   23.59  
   23.60 -#if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   23.61 -/* Streaming functions (for when the input and output buffer sizes are different) */
   23.62 -/* Write [length] bytes from buf into the streamer */
   23.63 +
   23.64 +/* device hotplug support... */
   23.65 +
   23.66 +static int
   23.67 +add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
   23.68 +{
   23.69 +    int retval = -1;
   23.70 +    const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
   23.71 +    SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
   23.72 +    if (item == NULL) {
   23.73 +        return -1;
   23.74 +    }
   23.75 +
   23.76 +    SDL_assert(handle != NULL);  /* we reserve NULL, audio backends can't use it. */
   23.77 +
   23.78 +    item->handle = handle;
   23.79 +    SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
   23.80 +
   23.81 +    SDL_LockMutex(current_audio.detectionLock);
   23.82 +    item->next = *devices;
   23.83 +    *devices = item;
   23.84 +    retval = (*devCount)++;
   23.85 +    SDL_UnlockMutex(current_audio.detectionLock);
   23.86 +
   23.87 +    return retval;
   23.88 +}
   23.89 +
   23.90 +static SDL_INLINE int
   23.91 +add_capture_device(const char *name, void *handle)
   23.92 +{
   23.93 +    /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
   23.94 +    return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
   23.95 +}
   23.96 +
   23.97 +static SDL_INLINE int
   23.98 +add_output_device(const char *name, void *handle)
   23.99 +{
  23.100 +    return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
  23.101 +}
  23.102 +
  23.103  static void
  23.104 -SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
  23.105 +free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
  23.106  {
  23.107 -    int i;
  23.108 +    SDL_AudioDeviceItem *item, *next;
  23.109 +    for (item = *devices; item != NULL; item = next) {
  23.110 +        next = item->next;
  23.111 +        if (item->handle != NULL) {
  23.112 +            current_audio.impl.FreeDeviceHandle(item->handle);
  23.113 +        }
  23.114 +        SDL_free(item);
  23.115 +    }
  23.116 +    *devices = NULL;
  23.117 +    *devCount = 0;
  23.118 +}
  23.119  
  23.120 -    for (i = 0; i < length; ++i) {
  23.121 -        stream->buffer[stream->write_pos] = buf[i];
  23.122 -        ++stream->write_pos;
  23.123 +
  23.124 +/* The audio backends call this when a new device is plugged in. */
  23.125 +void
  23.126 +SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
  23.127 +{
  23.128 +    const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
  23.129 +    if (device_index != -1) {
  23.130 +        /* Post the event, if desired */
  23.131 +        if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
  23.132 +            SDL_Event event;
  23.133 +            SDL_zero(event);
  23.134 +            event.adevice.type = SDL_AUDIODEVICEADDED;
  23.135 +            event.adevice.which = device_index;
  23.136 +            event.adevice.iscapture = iscapture;
  23.137 +            SDL_PushEvent(&event);
  23.138 +        }
  23.139      }
  23.140  }
  23.141  
  23.142 -/* Read [length] bytes out of the streamer into buf */
  23.143 -static void
  23.144 -SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
  23.145 +/* The audio backends call this when a currently-opened device is lost. */
  23.146 +void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
  23.147  {
  23.148 -    int i;
  23.149 +    SDL_assert(get_audio_device(device->id) == device);
  23.150  
  23.151 -    for (i = 0; i < length; ++i) {
  23.152 -        buf[i] = stream->buffer[stream->read_pos];
  23.153 -        ++stream->read_pos;
  23.154 +    if (!device->enabled) {
  23.155 +        return;
  23.156 +    }
  23.157 +
  23.158 +    /* Ends the audio callback and mark the device as STOPPED, but the
  23.159 +       app still needs to close the device to free resources. */
  23.160 +    current_audio.impl.LockDevice(device);
  23.161 +    device->enabled = 0;
  23.162 +    current_audio.impl.UnlockDevice(device);
  23.163 +
  23.164 +    /* Post the event, if desired */
  23.165 +    if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
  23.166 +        SDL_Event event;
  23.167 +        SDL_zero(event);
  23.168 +        event.adevice.type = SDL_AUDIODEVICEREMOVED;
  23.169 +        event.adevice.which = device->id;
  23.170 +        event.adevice.iscapture = device->iscapture ? 1 : 0;
  23.171 +        SDL_PushEvent(&event);
  23.172      }
  23.173  }
  23.174  
  23.175 -static int
  23.176 -SDL_StreamLength(SDL_AudioStreamer * stream)
  23.177 +static void
  23.178 +mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
  23.179  {
  23.180 -    return (stream->write_pos - stream->read_pos) % stream->max_len;
  23.181 +    SDL_AudioDeviceItem *item;
  23.182 +    SDL_assert(handle != NULL);
  23.183 +    for (item = devices; item != NULL; item = item->next) {
  23.184 +        if (item->handle == handle) {
  23.185 +            item->handle = NULL;
  23.186 +            *removedFlag = SDL_TRUE;
  23.187 +            return;
  23.188 +        }
  23.189 +    }
  23.190  }
  23.191  
  23.192 -/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
  23.193 -#if 0
  23.194 -static int
  23.195 -SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
  23.196 +/* The audio backends call this when a device is removed from the system. */
  23.197 +void
  23.198 +SDL_RemoveAudioDevice(const int iscapture, void *handle)
  23.199  {
  23.200 -    /* First try to allocate the buffer */
  23.201 -    stream->buffer = (Uint8 *) SDL_malloc(max_len);
  23.202 -    if (stream->buffer == NULL) {
  23.203 -        return -1;
  23.204 +    SDL_LockMutex(current_audio.detectionLock);
  23.205 +    if (iscapture) {
  23.206 +        mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
  23.207 +    } else {
  23.208 +        mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
  23.209      }
  23.210 +    SDL_UnlockMutex(current_audio.detectionLock);
  23.211 +    current_audio.impl.FreeDeviceHandle(handle);
  23.212 +}
  23.213  
  23.214 -    stream->max_len = max_len;
  23.215 -    stream->read_pos = 0;
  23.216 -    stream->write_pos = 0;
  23.217 -
  23.218 -    /* Zero out the buffer */
  23.219 -    SDL_memset(stream->buffer, silence, max_len);
  23.220 -
  23.221 -    return 0;
  23.222 -}
  23.223 -#endif
  23.224 -
  23.225 -/* Deinitialize the stream simply by freeing the buffer */
  23.226 -static void
  23.227 -SDL_StreamDeinit(SDL_AudioStreamer * stream)
  23.228 -{
  23.229 -    SDL_free(stream->buffer);
  23.230 -}
  23.231 -#endif
  23.232  
  23.233  
  23.234  /* buffer queueing support... */
  23.235 @@ -510,26 +590,17 @@
  23.236  }
  23.237  
  23.238  
  23.239 -#if defined(__ANDROID__)
  23.240 -#include <android/log.h>
  23.241 -#endif
  23.242 -
  23.243  /* The general mixing thread function */
  23.244  int SDLCALL
  23.245  SDL_RunAudio(void *devicep)
  23.246  {
  23.247      SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
  23.248 +    const int silence = (int) device->spec.silence;
  23.249 +    const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
  23.250 +    const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
  23.251      Uint8 *stream;
  23.252 -    int stream_len;
  23.253 -    void *udata;
  23.254 -    void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
  23.255 -    Uint32 delay;
  23.256 -
  23.257 -#if 0  /* !!! FIXME: rewrite/remove this streamer code. */
  23.258 -    /* For streaming when the buffer sizes don't match up */
  23.259 -    Uint8 *istream;
  23.260 -    int istream_len = 0;
  23.261 -#endif
  23.262 +    void *udata = device->spec.userdata;
  23.263 +    void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
  23.264  
  23.265      /* The audio mixing is always a high priority thread */
  23.266      SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
  23.267 @@ -538,197 +609,60 @@
  23.268      device->threadid = SDL_ThreadID();
  23.269      current_audio.impl.ThreadInit(device);
  23.270  
  23.271 -    /* Set up the mixing function */
  23.272 -    fill = device->spec.callback;
  23.273 -    udata = device->spec.userdata;
  23.274 +    /* Loop, filling the audio buffers */
  23.275 +    while (!device->shutdown) {
  23.276 +        /* Fill the current buffer with sound */
  23.277 +        if (device->convert.needed) {
  23.278 +            stream = device->convert.buf;
  23.279 +        } else if (device->enabled) {
  23.280 +            stream = current_audio.impl.GetDeviceBuf(device);
  23.281 +        } else {
  23.282 +            /* if the device isn't enabled, we still write to the
  23.283 +               fake_stream, so the app's callback will fire with
  23.284 +               a regular frequency, in case they depend on that
  23.285 +               for timing or progress. They can use hotplug
  23.286 +               now to know if the device failed. */
  23.287 +            stream = NULL;
  23.288 +        }
  23.289  
  23.290 -    /* By default do not stream */
  23.291 -    device->use_streamer = 0;
  23.292 +        if (stream == NULL) {
  23.293 +            stream = device->fake_stream;
  23.294 +        }
  23.295  
  23.296 -    if (device->convert.needed) {
  23.297 -#if 0                           /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
  23.298 -        /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
  23.299 -        if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
  23.300 -            /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
  23.301 -            stream_max_len = 2 * device->spec.size;
  23.302 -            if (device->convert.len_mult > device->convert.len_div) {
  23.303 -                stream_max_len *= device->convert.len_mult;
  23.304 -                stream_max_len /= device->convert.len_div;
  23.305 -            }
  23.306 -            if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
  23.307 -                0)
  23.308 -                return -1;
  23.309 -            device->use_streamer = 1;
  23.310 +        /* !!! FIXME: this should be LockDevice. */
  23.311 +        SDL_LockMutex(device->mixer_lock);
  23.312 +        if (device->paused) {
  23.313 +            SDL_memset(stream, silence, stream_len);
  23.314 +        } else {
  23.315 +            (*fill) (udata, stream, stream_len);
  23.316 +        }
  23.317 +        SDL_UnlockMutex(device->mixer_lock);
  23.318  
  23.319 -            /* istream_len should be the length of what we grab from the callback and feed to conversion,
  23.320 -               so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
  23.321 -             */
  23.322 -            istream_len =
  23.323 -                device->spec.size * device->convert.len_div /
  23.324 -                device->convert.len_mult;
  23.325 -        }
  23.326 -#endif
  23.327 -        stream_len = device->convert.len;
  23.328 -    } else {
  23.329 -        stream_len = device->spec.size;
  23.330 -    }
  23.331 -
  23.332 -    /* Calculate the delay while paused */
  23.333 -    delay = ((device->spec.samples * 1000) / device->spec.freq);
  23.334 -
  23.335 -    /* Determine if the streamer is necessary here */
  23.336 -#if 0  /* !!! FIXME: rewrite/remove this streamer code. */
  23.337 -    if (device->use_streamer == 1) {
  23.338 -        /* This code is almost the same as the old code. The difference is, instead of reading
  23.339 -           directly from the callback into "stream", then converting and sending the audio off,
  23.340 -           we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
  23.341 -           However, reading and writing with streamer are done separately:
  23.342 -           - We only call the callback and write to the streamer when the streamer does not
  23.343 -           contain enough samples to output to the device.
  23.344 -           - We only read from the streamer and tell the device to play when the streamer
  23.345 -           does have enough samples to output.
  23.346 -           This allows us to perform resampling in the conversion step, where the output of the
  23.347 -           resampling process can be any number. We will have to see what a good size for the
  23.348 -           stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
  23.349 -         */
  23.350 -        while (device->enabled) {
  23.351 -
  23.352 -            if (device->paused) {
  23.353 -                SDL_Delay(delay);
  23.354 -                continue;
  23.355 -            }
  23.356 -
  23.357 -            /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
  23.358 -            if (SDL_StreamLength(&device->streamer) < stream_len) {
  23.359 -                /* Set up istream */
  23.360 -                if (device->convert.needed) {
  23.361 -                    if (device->convert.buf) {
  23.362 -                        istream = device->convert.buf;
  23.363 -                    } else {
  23.364 -                        continue;
  23.365 -                    }
  23.366 -                } else {
  23.367 -/* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
  23.368 - * a device buffer both here and below in the stream output.
  23.369 - */
  23.370 -                    istream = current_audio.impl.GetDeviceBuf(device);
  23.371 -                    if (istream == NULL) {
  23.372 -                        istream = device->fake_stream;
  23.373 -                    }
  23.374 -                }
  23.375 -
  23.376 -                /* Read from the callback into the _input_ stream */
  23.377 -                SDL_LockMutex(device->mixer_lock);
  23.378 -                (*fill) (udata, istream, istream_len);
  23.379 -                SDL_UnlockMutex(device->mixer_lock);
  23.380 -
  23.381 -                /* Convert the audio if necessary and write to the streamer */
  23.382 -                if (device->convert.needed) {
  23.383 -                    SDL_ConvertAudio(&device->convert);
  23.384 -                    if (istream == NULL) {
  23.385 -                        istream = device->fake_stream;
  23.386 -                    }
  23.387 -                    /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
  23.388 -                    SDL_StreamWrite(&device->streamer, device->convert.buf,
  23.389 -                                    device->convert.len_cvt);
  23.390 -                } else {
  23.391 -                    SDL_StreamWrite(&device->streamer, istream, istream_len);
  23.392 -                }
  23.393 -            }
  23.394 -
  23.395 -            /* Only output audio if the streamer has enough to output */
  23.396 -            if (SDL_StreamLength(&device->streamer) >= stream_len) {
  23.397 -                /* Set up the output stream */
  23.398 -                if (device->convert.needed) {
  23.399 -                    if (device->convert.buf) {
  23.400 -                        stream = device->convert.buf;
  23.401 -                    } else {
  23.402 -                        continue;
  23.403 -                    }
  23.404 -                } else {
  23.405 -                    stream = current_audio.impl.GetDeviceBuf(device);
  23.406 -                    if (stream == NULL) {
  23.407 -                        stream = device->fake_stream;
  23.408 -                    }
  23.409 -                }
  23.410 -
  23.411 -                /* Now read from the streamer */
  23.412 -                SDL_StreamRead(&device->streamer, stream, stream_len);
  23.413 -
  23.414 -                /* Ready current buffer for play and change current buffer */
  23.415 -                if (stream != device->fake_stream) {
  23.416 -                    current_audio.impl.PlayDevice(device);
  23.417 -                    /* Wait for an audio buffer to become available */
  23.418 -                    current_audio.impl.WaitDevice(device);
  23.419 -                } else {
  23.420 -                    SDL_Delay(delay);
  23.421 -                }
  23.422 -            }
  23.423 -
  23.424 -        }
  23.425 -    } else
  23.426 -#endif
  23.427 -    {
  23.428 -        /* Otherwise, do not use the streamer. This is the old code. */
  23.429 -        const int silence = (int) device->spec.silence;
  23.430 -
  23.431 -        /* Loop, filling the audio buffers */
  23.432 -        while (device->enabled) {
  23.433 -
  23.434 -            /* Fill the current buffer with sound */
  23.435 -            if (device->convert.needed) {
  23.436 -                if (device->convert.buf) {
  23.437 -                    stream = device->convert.buf;
  23.438 -                } else {
  23.439 -                    continue;
  23.440 -                }
  23.441 +        /* Convert the audio if necessary */
  23.442 +        if (device->enabled && device->convert.needed) {
  23.443 +            SDL_ConvertAudio(&device->convert);
  23.444 +            stream = current_audio.impl.GetDeviceBuf(device);
  23.445 +            if (stream == NULL) {
  23.446 +                stream = device->fake_stream;
  23.447              } else {
  23.448 -                stream = current_audio.impl.GetDeviceBuf(device);
  23.449 -                if (stream == NULL) {
  23.450 -                    stream = device->fake_stream;
  23.451 -                }
  23.452 -            }
  23.453 -
  23.454 -            SDL_LockMutex(device->mixer_lock);
  23.455 -            if (device->paused) {
  23.456 -                SDL_memset(stream, silence, stream_len);
  23.457 -            } else {
  23.458 -                (*fill) (udata, stream, stream_len);
  23.459 -            }
  23.460 -            SDL_UnlockMutex(device->mixer_lock);
  23.461 -
  23.462 -            /* Convert the audio if necessary */
  23.463 -            if (device->convert.needed) {
  23.464 -                SDL_ConvertAudio(&device->convert);
  23.465 -                stream = current_audio.impl.GetDeviceBuf(device);
  23.466 -                if (stream == NULL) {
  23.467 -                    stream = device->fake_stream;
  23.468 -                }
  23.469                  SDL_memcpy(stream, device->convert.buf,
  23.470                             device->convert.len_cvt);
  23.471              }
  23.472 +        }
  23.473  
  23.474 -            /* Ready current buffer for play and change current buffer */
  23.475 -            if (stream != device->fake_stream) {
  23.476 -                current_audio.impl.PlayDevice(device);
  23.477 -                /* Wait for an audio buffer to become available */
  23.478 -                current_audio.impl.WaitDevice(device);
  23.479 -            } else {
  23.480 -                SDL_Delay(delay);
  23.481 -            }
  23.482 +        /* Ready current buffer for play and change current buffer */
  23.483 +        if (stream == device->fake_stream) {
  23.484 +            SDL_Delay(delay);
  23.485 +        } else {
  23.486 +            current_audio.impl.PlayDevice(device);
  23.487 +            current_audio.impl.WaitDevice(device);
  23.488          }
  23.489      }
  23.490  
  23.491 -    /* Wait for the audio to drain.. */
  23.492 +    /* Wait for the audio to drain. */
  23.493      current_audio.impl.WaitDone(device);
  23.494  
  23.495 -    /* If necessary, deinit the streamer */
  23.496 -#if 0  /* !!! FIXME: rewrite/remove this streamer code. */
  23.497 -    if (device->use_streamer == 1)
  23.498 -        SDL_StreamDeinit(&device->streamer);
  23.499 -#endif
  23.500 -
  23.501 -    return (0);
  23.502 +    return 0;
  23.503  }
  23.504  
  23.505  
  23.506 @@ -761,16 +695,16 @@
  23.507  int
  23.508  SDL_GetNumAudioDrivers(void)
  23.509  {
  23.510 -    return (SDL_arraysize(bootstrap) - 1);
  23.511 +    return SDL_arraysize(bootstrap) - 1;
  23.512  }
  23.513  
  23.514  const char *
  23.515  SDL_GetAudioDriver(int index)
  23.516  {
  23.517      if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
  23.518 -        return (bootstrap[index]->name);
  23.519 +        return bootstrap[index]->name;
  23.520      }
  23.521 -    return (NULL);
  23.522 +    return NULL;
  23.523  }
  23.524  
  23.525  int
  23.526 @@ -784,8 +718,8 @@
  23.527          SDL_AudioQuit();        /* shutdown driver if already running. */
  23.528      }
  23.529  
  23.530 -    SDL_memset(&current_audio, '\0', sizeof(current_audio));
  23.531 -    SDL_memset(open_devices, '\0', sizeof(open_devices));
  23.532 +    SDL_zero(current_audio);
  23.533 +    SDL_zero(open_devices);
  23.534  
  23.535      /* Select the proper audio driver */
  23.536      if (driver_name == NULL) {
  23.537 @@ -801,7 +735,7 @@
  23.538          }
  23.539  
  23.540          tried_to_init = 1;
  23.541 -        SDL_memset(&current_audio, 0, sizeof(current_audio));
  23.542 +        SDL_zero(current_audio);
  23.543          current_audio.name = backend->name;
  23.544          current_audio.desc = backend->desc;
  23.545          initialized = backend->init(&current_audio.impl);
  23.546 @@ -817,13 +751,18 @@
  23.547              }
  23.548          }
  23.549  
  23.550 -        SDL_memset(&current_audio, 0, sizeof(current_audio));
  23.551 -        return (-1);            /* No driver was available, so fail. */
  23.552 +        SDL_zero(current_audio);
  23.553 +        return -1;            /* No driver was available, so fail. */
  23.554      }
  23.555  
  23.556 +    current_audio.detectionLock = SDL_CreateMutex();
  23.557 +
  23.558      finalize_audio_entry_points();
  23.559  
  23.560 -    return (0);
  23.561 +    /* Make sure we have a list of devices available at startup. */
  23.562 +    current_audio.impl.DetectDevices();
  23.563 +
  23.564 +    return 0;
  23.565  }
  23.566  
  23.567  /*
  23.568 @@ -835,50 +774,32 @@
  23.569      return current_audio.name;
  23.570  }
  23.571  
  23.572 +/* Clean out devices that we've removed but had to keep around for stability. */
  23.573  static void
  23.574 -free_device_list(char ***devices, int *devCount)
  23.575 +clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
  23.576  {
  23.577 -    int i = *devCount;
  23.578 -    if ((i > 0) && (*devices != NULL)) {
  23.579 -        while (i--) {
  23.580 -            SDL_free((*devices)[i]);
  23.581 +    SDL_AudioDeviceItem *item = *devices;
  23.582 +    SDL_AudioDeviceItem *prev = NULL;
  23.583 +    int total = 0;
  23.584 +
  23.585 +    while (item) {
  23.586 +        SDL_AudioDeviceItem *next = item->next;
  23.587 +        if (item->handle != NULL) {
  23.588 +            total++;
  23.589 +            prev = item;
  23.590 +        } else {
  23.591 +            if (prev) {
  23.592 +                prev->next = next;
  23.593 +            } else {
  23.594 +                *devices = next;
  23.595 +            }
  23.596 +            SDL_free(item);
  23.597          }
  23.598 +        item = next;
  23.599      }
  23.600  
  23.601 -    SDL_free(*devices);
  23.602 -
  23.603 -    *devices = NULL;
  23.604 -    *devCount = 0;
  23.605 -}
  23.606 -
  23.607 -static
  23.608 -void SDL_AddCaptureAudioDevice(const char *_name)
  23.609 -{
  23.610 -    char *name = NULL;
  23.611 -    void *ptr = SDL_realloc(current_audio.inputDevices,
  23.612 -                          (current_audio.inputDeviceCount+1) * sizeof(char*));
  23.613 -    if (ptr == NULL) {
  23.614 -        return;  /* oh well. */
  23.615 -    }
  23.616 -
  23.617 -    current_audio.inputDevices = (char **) ptr;
  23.618 -    name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
  23.619 -    current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
  23.620 -}
  23.621 -
  23.622 -static
  23.623 -void SDL_AddOutputAudioDevice(const char *_name)
  23.624 -{
  23.625 -    char *name = NULL;
  23.626 -    void *ptr = SDL_realloc(current_audio.outputDevices,
  23.627 -                          (current_audio.outputDeviceCount+1) * sizeof(char*));
  23.628 -    if (ptr == NULL) {
  23.629 -        return;  /* oh well. */
  23.630 -    }
  23.631 -
  23.632 -    current_audio.outputDevices = (char **) ptr;
  23.633 -    name = SDL_strdup(_name);  /* if this returns NULL, that's okay. */
  23.634 -    current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
  23.635 +    *devCount = total;
  23.636 +    *removedFlag = SDL_FALSE;
  23.637  }
  23.638  
  23.639  
  23.640 @@ -891,29 +812,18 @@
  23.641          return -1;
  23.642      }
  23.643  
  23.644 -    if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
  23.645 -        return 0;
  23.646 +    SDL_LockMutex(current_audio.detectionLock);
  23.647 +    if (iscapture && current_audio.captureDevicesRemoved) {
  23.648 +        clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
  23.649      }
  23.650  
  23.651 -    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  23.652 -        return 1;
  23.653 +    if (!iscapture && current_audio.outputDevicesRemoved) {
  23.654 +        clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
  23.655 +        current_audio.outputDevicesRemoved = SDL_FALSE;
  23.656      }
  23.657  
  23.658 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  23.659 -        return 1;
  23.660 -    }
  23.661 -
  23.662 -    if (iscapture) {
  23.663 -        free_device_list(&current_audio.inputDevices,
  23.664 -                         &current_audio.inputDeviceCount);
  23.665 -        current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
  23.666 -        retval = current_audio.inputDeviceCount;
  23.667 -    } else {
  23.668 -        free_device_list(&current_audio.outputDevices,
  23.669 -                         &current_audio.outputDeviceCount);
  23.670 -        current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
  23.671 -        retval = current_audio.outputDeviceCount;
  23.672 -    }
  23.673 +    retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
  23.674 +    SDL_UnlockMutex(current_audio.detectionLock);
  23.675  
  23.676      return retval;
  23.677  }
  23.678 @@ -922,6 +832,8 @@
  23.679  const char *
  23.680  SDL_GetAudioDeviceName(int index, int iscapture)
  23.681  {
  23.682 +    const char *retval = NULL;
  23.683 +
  23.684      if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  23.685          SDL_SetError("Audio subsystem is not initialized");
  23.686          return NULL;
  23.687 @@ -932,39 +844,28 @@
  23.688          return NULL;
  23.689      }
  23.690  
  23.691 -    if (index < 0) {
  23.692 -        goto no_such_device;
  23.693 +    if (index >= 0) {
  23.694 +        SDL_AudioDeviceItem *item;
  23.695 +        int i;
  23.696 +
  23.697 +        SDL_LockMutex(current_audio.detectionLock);
  23.698 +        item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
  23.699 +        i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
  23.700 +        if (index < i) {
  23.701 +            for (i--; i > index; i--, item = item->next) {
  23.702 +                SDL_assert(item != NULL);
  23.703 +            }
  23.704 +            SDL_assert(item != NULL);
  23.705 +            retval = item->name;
  23.706 +        }
  23.707 +        SDL_UnlockMutex(current_audio.detectionLock);
  23.708      }
  23.709  
  23.710 -    if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  23.711 -        if (index > 0) {
  23.712 -            goto no_such_device;
  23.713 -        }
  23.714 -        return DEFAULT_INPUT_DEVNAME;
  23.715 +    if (retval == NULL) {
  23.716 +        SDL_SetError("No such device");
  23.717      }
  23.718  
  23.719 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  23.720 -        if (index > 0) {
  23.721 -            goto no_such_device;
  23.722 -        }
  23.723 -        return DEFAULT_OUTPUT_DEVNAME;
  23.724 -    }
  23.725 -
  23.726 -    if (iscapture) {
  23.727 -        if (index >= current_audio.inputDeviceCount) {
  23.728 -            goto no_such_device;
  23.729 -        }
  23.730 -        return current_audio.inputDevices[index];
  23.731 -    } else {
  23.732 -        if (index >= current_audio.outputDeviceCount) {
  23.733 -            goto no_such_device;
  23.734 -        }
  23.735 -        return current_audio.outputDevices[index];
  23.736 -    }
  23.737 -
  23.738 -no_such_device:
  23.739 -    SDL_SetError("No such device");
  23.740 -    return NULL;
  23.741 +    return retval;
  23.742  }
  23.743  
  23.744  
  23.745 @@ -972,6 +873,7 @@
  23.746  close_audio_device(SDL_AudioDevice * device)
  23.747  {
  23.748      device->enabled = 0;
  23.749 +    device->shutdown = 1;
  23.750      if (device->thread != NULL) {
  23.751          SDL_WaitThread(device->thread, NULL);
  23.752      }
  23.753 @@ -1065,6 +967,8 @@
  23.754      SDL_AudioSpec _obtained;
  23.755      SDL_AudioDevice *device;
  23.756      SDL_bool build_cvt;
  23.757 +    void *handle = NULL;
  23.758 +    Uint32 stream_len;
  23.759      int i = 0;
  23.760  
  23.761      if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  23.762 @@ -1077,6 +981,18 @@
  23.763          return 0;
  23.764      }
  23.765  
  23.766 +    /* Find an available device ID... */
  23.767 +    for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  23.768 +        if (open_devices[id] == NULL) {
  23.769 +            break;
  23.770 +        }
  23.771 +    }
  23.772 +
  23.773 +    if (id == SDL_arraysize(open_devices)) {
  23.774 +        SDL_SetError("Too many open audio devices");
  23.775 +        return 0;
  23.776 +    }
  23.777 +
  23.778      if (!obtained) {
  23.779          obtained = &_obtained;
  23.780      }
  23.781 @@ -1112,9 +1028,7 @@
  23.782                  return 0;
  23.783              }
  23.784          }
  23.785 -    }
  23.786 -
  23.787 -    if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  23.788 +    } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  23.789          if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
  23.790              SDL_SetError("No such device");
  23.791              return 0;
  23.792 @@ -1127,6 +1041,30 @@
  23.793                  return 0;
  23.794              }
  23.795          }
  23.796 +    } else if (devname != NULL) {
  23.797 +        /* if the app specifies an exact string, we can pass the backend
  23.798 +           an actual device handle thingey, which saves them the effort of
  23.799 +           figuring out what device this was (such as, reenumerating
  23.800 +           everything again to find the matching human-readable name).
  23.801 +           It might still need to open a device based on the string for,
  23.802 +           say, a network audio server, but this optimizes some cases. */
  23.803 +        SDL_AudioDeviceItem *item;
  23.804 +        SDL_LockMutex(current_audio.detectionLock);
  23.805 +        for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
  23.806 +            if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
  23.807 +                handle = item->handle;
  23.808 +                break;
  23.809 +            }
  23.810 +        }
  23.811 +        SDL_UnlockMutex(current_audio.detectionLock);
  23.812 +    }
  23.813 +
  23.814 +    if (!current_audio.impl.AllowsArbitraryDeviceNames) {
  23.815 +        /* has to be in our device list, or the default device. */
  23.816 +        if ((handle == NULL) && (devname != NULL)) {
  23.817 +            SDL_SetError("No such device.");
  23.818 +            return 0;
  23.819 +        }
  23.820      }
  23.821  
  23.822      device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
  23.823 @@ -1135,12 +1073,13 @@
  23.824          return 0;
  23.825      }
  23.826      SDL_zerop(device);
  23.827 +    device->id = id + 1;
  23.828      device->spec = *obtained;
  23.829      device->enabled = 1;
  23.830      device->paused = 1;
  23.831      device->iscapture = iscapture;
  23.832  
  23.833 -    /* Create a semaphore for locking the sound buffers */
  23.834 +    /* Create a mutex for locking the sound buffers */
  23.835      if (!current_audio.impl.SkipMixerLock) {
  23.836          device->mixer_lock = SDL_CreateMutex();
  23.837          if (device->mixer_lock == NULL) {
  23.838 @@ -1150,26 +1089,12 @@
  23.839          }
  23.840      }
  23.841  
  23.842 -    /* force a device detection if we haven't done one yet. */
  23.843 -    if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
  23.844 -         ((!iscapture) && (current_audio.outputDevices == NULL)) ) {
  23.845 -        SDL_GetNumAudioDevices(iscapture);
  23.846 -    }
  23.847 -
  23.848 -    if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
  23.849 +    if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
  23.850          close_audio_device(device);
  23.851          return 0;
  23.852      }
  23.853      device->opened = 1;
  23.854  
  23.855 -    /* Allocate a fake audio memory buffer */
  23.856 -    device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
  23.857 -    if (device->fake_stream == NULL) {
  23.858 -        close_audio_device(device);
  23.859 -        SDL_OutOfMemory();
  23.860 -        return 0;
  23.861 -    }
  23.862 -
  23.863      /* See if we need to do any conversion */
  23.864      build_cvt = SDL_FALSE;
  23.865      if (obtained->freq != device->spec.freq) {
  23.866 @@ -1228,6 +1153,19 @@
  23.867          }
  23.868      }
  23.869  
  23.870 +    /* Allocate a fake audio memory buffer */
  23.871 +    stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
  23.872 +    if (device->spec.size > stream_len) {
  23.873 +        stream_len = device->spec.size;
  23.874 +    }
  23.875 +    SDL_assert(stream_len > 0);
  23.876 +    device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
  23.877 +    if (device->fake_stream == NULL) {
  23.878 +        close_audio_device(device);
  23.879 +        SDL_OutOfMemory();
  23.880 +        return 0;
  23.881 +    }
  23.882 +
  23.883      if (device->spec.callback == NULL) {  /* use buffer queueing? */
  23.884          /* pool a few packets to start. Enough for two callbacks. */
  23.885          const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
  23.886 @@ -1247,25 +1185,14 @@
  23.887          device->spec.userdata = device;
  23.888      }
  23.889  
  23.890 -    /* Find an available device ID and store the structure... */
  23.891 -    for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  23.892 -        if (open_devices[id] == NULL) {
  23.893 -            open_devices[id] = device;
  23.894 -            break;
  23.895 -        }
  23.896 -    }
  23.897 -
  23.898 -    if (id == SDL_arraysize(open_devices)) {
  23.899 -        SDL_SetError("Too many open audio devices");
  23.900 -        close_audio_device(device);
  23.901 -        return 0;
  23.902 -    }
  23.903 +    /* add it to our list of open devices. */
  23.904 +    open_devices[id] = device;
  23.905  
  23.906      /* Start the audio thread if necessary */
  23.907      if (!current_audio.impl.ProvidesOwnCallbackThread) {
  23.908          /* Start the audio thread */
  23.909          char name[64];
  23.910 -        SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
  23.911 +        SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
  23.912  /* !!! FIXME: this is nasty. */
  23.913  #if defined(__WIN32__) && !defined(HAVE_LIBC)
  23.914  #undef SDL_CreateThread
  23.915 @@ -1278,13 +1205,13 @@
  23.916          device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  23.917  #endif
  23.918          if (device->thread == NULL) {
  23.919 -            SDL_CloseAudioDevice(id + 1);
  23.920 +            SDL_CloseAudioDevice(device->id);
  23.921              SDL_SetError("Couldn't create audio thread");
  23.922              return 0;
  23.923          }
  23.924      }
  23.925  
  23.926 -    return id + 1;
  23.927 +    return device->id;
  23.928  }
  23.929  
  23.930  
  23.931 @@ -1296,14 +1223,14 @@
  23.932      /* Start up the audio driver, if necessary. This is legacy behaviour! */
  23.933      if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  23.934          if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  23.935 -            return (-1);
  23.936 +            return -1;
  23.937          }
  23.938      }
  23.939  
  23.940      /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  23.941      if (open_devices[0] != NULL) {
  23.942          SDL_SetError("Audio device is already opened");
  23.943 -        return (-1);
  23.944 +        return -1;
  23.945      }
  23.946  
  23.947      if (obtained) {
  23.948 @@ -1314,7 +1241,7 @@
  23.949      }
  23.950  
  23.951      SDL_assert((id == 0) || (id == 1));
  23.952 -    return ((id == 0) ? -1 : 0);
  23.953 +    return (id == 0) ? -1 : 0;
  23.954  }
  23.955  
  23.956  SDL_AudioDeviceID
  23.957 @@ -1338,7 +1265,7 @@
  23.958              status = SDL_AUDIO_PLAYING;
  23.959          }
  23.960      }
  23.961 -    return (status);
  23.962 +    return status;
  23.963  }
  23.964  
  23.965  
  23.966 @@ -1429,14 +1356,16 @@
  23.967          }
  23.968      }
  23.969  
  23.970 +    free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
  23.971 +    free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
  23.972 +
  23.973      /* Free the driver data */
  23.974      current_audio.impl.Deinitialize();
  23.975 -    free_device_list(&current_audio.outputDevices,
  23.976 -                     &current_audio.outputDeviceCount);
  23.977 -    free_device_list(&current_audio.inputDevices,
  23.978 -                     &current_audio.inputDeviceCount);
  23.979 -    SDL_memset(&current_audio, '\0', sizeof(current_audio));
  23.980 -    SDL_memset(open_devices, '\0', sizeof(open_devices));
  23.981 +
  23.982 +    SDL_DestroyMutex(current_audio.detectionLock);
  23.983 +
  23.984 +    SDL_zero(current_audio);
  23.985 +    SDL_zero(open_devices);
  23.986  }
  23.987  
  23.988  #define NUM_FORMATS 10
  23.989 @@ -1474,16 +1403,16 @@
  23.990          }
  23.991      }
  23.992      format_idx_sub = 0;
  23.993 -    return (SDL_NextAudioFormat());
  23.994 +    return SDL_NextAudioFormat();
  23.995  }
  23.996  
  23.997  SDL_AudioFormat
  23.998  SDL_NextAudioFormat(void)
  23.999  {
 23.1000      if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
 23.1001 -        return (0);
 23.1002 +        return 0;
 23.1003      }
 23.1004 -    return (format_list[format_idx][format_idx_sub++]);
 23.1005 +    return format_list[format_idx][format_idx_sub++];
 23.1006  }
 23.1007  
 23.1008  void
    24.1 --- a/src/audio/SDL_audiodev.c	Sat Jan 24 23:58:07 2015 -0400
    24.2 +++ b/src/audio/SDL_audiodev.c	Mon Apr 06 15:26:37 2015 -0300
    24.3 @@ -46,18 +46,21 @@
    24.4  #define _PATH_DEV_AUDIO "/dev/audio"
    24.5  #endif
    24.6  
    24.7 -static SDL_INLINE void
    24.8 -test_device(const char *fname, int flags, int (*test) (int fd),
    24.9 -            SDL_AddAudioDevice addfn)
   24.10 +static void
   24.11 +test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd))
   24.12  {
   24.13      struct stat sb;
   24.14      if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
   24.15          const int audio_fd = open(fname, flags, 0);
   24.16          if (audio_fd >= 0) {
   24.17 -            if (test(audio_fd)) {
   24.18 -                addfn(fname);
   24.19 +            const int okay = test(audio_fd);
   24.20 +            close(audio_fd);
   24.21 +            if (okay) {
   24.22 +                static size_t dummyhandle = 0;
   24.23 +                dummyhandle++;
   24.24 +                SDL_assert(dummyhandle != 0);
   24.25 +                SDL_AddAudioDevice(iscapture, fname, (void *) dummyhandle);
   24.26              }
   24.27 -            close(audio_fd);
   24.28          }
   24.29      }
   24.30  }
   24.31 @@ -68,11 +71,10 @@
   24.32      return 1;
   24.33  }
   24.34  
   24.35 -void
   24.36 -SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd),
   24.37 -                         SDL_AddAudioDevice addfn)
   24.38 +static void
   24.39 +SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int))
   24.40  {
   24.41 -    const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   24.42 +    const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
   24.43      const char *audiodev;
   24.44      char audiopath[1024];
   24.45  
   24.46 @@ -97,17 +99,25 @@
   24.47              }
   24.48          }
   24.49      }
   24.50 -    test_device(audiodev, flags, test, addfn);
   24.51 +    test_device(iscapture, audiodev, flags, test);
   24.52  
   24.53      if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) {
   24.54          int instance = 0;
   24.55          while (instance++ <= 64) {
   24.56              SDL_snprintf(audiopath, SDL_arraysize(audiopath),
   24.57                           "%s%d", audiodev, instance);
   24.58 -            test_device(audiopath, flags, test, addfn);
   24.59 +            test_device(iscapture, audiopath, flags, test);
   24.60          }
   24.61      }
   24.62  }
   24.63  
   24.64 +void
   24.65 +SDL_EnumUnixAudioDevices(const int classic, int (*test)(int))
   24.66 +{
   24.67 +    SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test);
   24.68 +    SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test);
   24.69 +}
   24.70 +
   24.71  #endif /* Audio driver selection */
   24.72 +
   24.73  /* vi: set ts=4 sw=4 expandtab: */
    25.1 --- a/src/audio/SDL_audiodev_c.h	Sat Jan 24 23:58:07 2015 -0400
    25.2 +++ b/src/audio/SDL_audiodev_c.h	Mon Apr 06 15:26:37 2015 -0300
    25.3 @@ -33,7 +33,6 @@
    25.4  #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK)
    25.5  #endif
    25.6  
    25.7 -void SDL_EnumUnixAudioDevices(int iscapture, int classic,
    25.8 -                              int (*test) (int fd), SDL_AddAudioDevice addfn);
    25.9 +extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int));
   25.10  
   25.11  /* vi: set ts=4 sw=4 expandtab: */
    26.1 --- a/src/audio/SDL_sysaudio.h	Sat Jan 24 23:58:07 2015 -0400
    26.2 +++ b/src/audio/SDL_sysaudio.h	Mon Apr 06 15:26:37 2015 -0300
    26.3 @@ -30,8 +30,21 @@
    26.4  typedef struct SDL_AudioDevice SDL_AudioDevice;
    26.5  #define _THIS   SDL_AudioDevice *_this
    26.6  
    26.7 -/* Used by audio targets during DetectDevices() */
    26.8 -typedef void (*SDL_AddAudioDevice)(const char *name);
    26.9 +/* Audio targets should call this as devices are added to the system (such as
   26.10 +   a USB headset being plugged in), and should also be called for
   26.11 +   for every device found during DetectDevices(). */
   26.12 +extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle);
   26.13 +
   26.14 +/* Audio targets should call this as devices are removed, so SDL can update
   26.15 +   its list of available devices. */
   26.16 +extern void SDL_RemoveAudioDevice(const int iscapture, void *handle);
   26.17 +
   26.18 +/* Audio targets should call this if an opened audio device is lost while
   26.19 +   being used. This can happen due to i/o errors, or a device being unplugged,
   26.20 +   etc. If the device is totally gone, please also call SDL_RemoveAudioDevice()
   26.21 +   as appropriate so SDL's list of devices is accurate. */
   26.22 +extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device);
   26.23 +
   26.24  
   26.25  /* This is the size of a packet when using SDL_QueueAudio(). We allocate
   26.26     these as necessary and pool them, under the assumption that we'll
   26.27 @@ -55,8 +68,8 @@
   26.28  
   26.29  typedef struct SDL_AudioDriverImpl
   26.30  {
   26.31 -    void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn);
   26.32 -    int (*OpenDevice) (_THIS, const char *devname, int iscapture);
   26.33 +    void (*DetectDevices) (void);
   26.34 +    int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture);
   26.35      void (*ThreadInit) (_THIS); /* Called by audio thread at start */
   26.36      void (*WaitDevice) (_THIS);
   26.37      void (*PlayDevice) (_THIS);
   26.38 @@ -66,19 +79,34 @@
   26.39      void (*CloseDevice) (_THIS);
   26.40      void (*LockDevice) (_THIS);
   26.41      void (*UnlockDevice) (_THIS);
   26.42 +    void (*FreeDeviceHandle) (void *handle);  /**< SDL is done with handle from SDL_AddAudioDevice() */
   26.43      void (*Deinitialize) (void);
   26.44  
   26.45      /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */
   26.46  
   26.47      /* Some flags to push duplicate code into the core and reduce #ifdefs. */
   26.48 +    /* !!! FIXME: these should be SDL_bool */
   26.49      int ProvidesOwnCallbackThread;
   26.50      int SkipMixerLock;  /* !!! FIXME: do we need this anymore? */
   26.51      int HasCaptureSupport;
   26.52      int OnlyHasDefaultOutputDevice;
   26.53      int OnlyHasDefaultInputDevice;
   26.54 +    int AllowsArbitraryDeviceNames;
   26.55  } SDL_AudioDriverImpl;
   26.56  
   26.57  
   26.58 +typedef struct SDL_AudioDeviceItem
   26.59 +{
   26.60 +    void *handle;
   26.61 +    struct SDL_AudioDeviceItem *next;
   26.62 +    #if (defined(__GNUC__) && (__GNUC__ <= 2))
   26.63 +    char name[1];  /* actually variable length. */
   26.64 +    #else
   26.65 +    char name[];
   26.66 +    #endif
   26.67 +} SDL_AudioDeviceItem;
   26.68 +
   26.69 +
   26.70  typedef struct SDL_AudioDriver
   26.71  {
   26.72      /* * * */
   26.73 @@ -91,11 +119,14 @@
   26.74  
   26.75      SDL_AudioDriverImpl impl;
   26.76  
   26.77 -    char **outputDevices;
   26.78 +    /* A mutex for device detection */
   26.79 +    SDL_mutex *detectionLock;
   26.80 +    SDL_bool captureDevicesRemoved;
   26.81 +    SDL_bool outputDevicesRemoved;
   26.82      int outputDeviceCount;
   26.83 -
   26.84 -    char **inputDevices;
   26.85      int inputDeviceCount;
   26.86 +    SDL_AudioDeviceItem *outputDevices;
   26.87 +    SDL_AudioDeviceItem *inputDevices;
   26.88  } SDL_AudioDriver;
   26.89  
   26.90  
   26.91 @@ -113,6 +144,7 @@
   26.92  {
   26.93      /* * * */
   26.94      /* Data common to all devices */
   26.95 +    SDL_AudioDeviceID id;
   26.96  
   26.97      /* The current audio specification (shared with audio thread) */
   26.98      SDL_AudioSpec spec;
   26.99 @@ -125,15 +157,17 @@
  26.100      SDL_AudioStreamer streamer;
  26.101  
  26.102      /* Current state flags */
  26.103 +    /* !!! FIXME: should be SDL_bool */
  26.104      int iscapture;
  26.105 -    int enabled;
  26.106 +    int enabled;  /* true if device is functioning and connected. */
  26.107 +    int shutdown; /* true if we are signaling the play thread to end. */
  26.108      int paused;
  26.109      int opened;
  26.110  
  26.111      /* Fake audio buffer for when the audio hardware is busy */
  26.112      Uint8 *fake_stream;
  26.113  
  26.114 -    /* A semaphore for locking the mixing buffers */
  26.115 +    /* A mutex for locking the mixing buffers */
  26.116      SDL_mutex *mixer_lock;
  26.117  
  26.118      /* A thread to feed the audio device */
    27.1 --- a/src/audio/alsa/SDL_alsa_audio.c	Sat Jan 24 23:58:07 2015 -0400
    27.2 +++ b/src/audio/alsa/SDL_alsa_audio.c	Mon Apr 06 15:26:37 2015 -0300
    27.3 @@ -320,7 +320,7 @@
    27.4                  /* Hmm, not much we can do - abort */
    27.5                  fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
    27.6                          ALSA_snd_strerror(status));
    27.7 -                this->enabled = 0;
    27.8 +                SDL_OpenedAudioDeviceDisconnected(this);
    27.9                  return;
   27.10              }
   27.11              continue;
   27.12 @@ -465,7 +465,7 @@
   27.13  }
   27.14  
   27.15  static int
   27.16 -ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
   27.17 +ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   27.18  {
   27.19      int status = 0;
   27.20      snd_pcm_t *pcm_handle = NULL;
    28.1 --- a/src/audio/android/SDL_androidaudio.c	Sat Jan 24 23:58:07 2015 -0400
    28.2 +++ b/src/audio/android/SDL_androidaudio.c	Mon Apr 06 15:26:37 2015 -0300
    28.3 @@ -35,7 +35,7 @@
    28.4  static SDL_AudioDevice* audioDevice = NULL;
    28.5  
    28.6  static int
    28.7 -AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
    28.8 +AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    28.9  {
   28.10      SDL_AudioFormat test_format;
   28.11  
    29.1 --- a/src/audio/arts/SDL_artsaudio.c	Sat Jan 24 23:58:07 2015 -0400
    29.2 +++ b/src/audio/arts/SDL_artsaudio.c	Mon Apr 06 15:26:37 2015 -0300
    29.3 @@ -151,7 +151,7 @@
    29.4          /* Check every 10 loops */
    29.5          if (this->hidden->parent && (((++cnt) % 10) == 0)) {
    29.6              if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
    29.7 -                this->enabled = 0;
    29.8 +                SDL_OpenedAudioDeviceDisconnected(this);
    29.9              }
   29.10          }
   29.11      }
   29.12 @@ -179,7 +179,7 @@
   29.13  
   29.14      /* If we couldn't write, assume fatal error for now */
   29.15      if (written < 0) {
   29.16 -        this->enabled = 0;
   29.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   29.18      }
   29.19  #ifdef DEBUG_AUDIO
   29.20      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   29.21 @@ -229,7 +229,7 @@
   29.22  }
   29.23  
   29.24  static int
   29.25 -ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
   29.26 +ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   29.27  {
   29.28      int rc = 0;
   29.29      int bits = 0, frag_spec = 0;
    30.1 --- a/src/audio/bsd/SDL_bsdaudio.c	Sat Jan 24 23:58:07 2015 -0400
    30.2 +++ b/src/audio/bsd/SDL_bsdaudio.c	Mon Apr 06 15:26:37 2015 -0300
    30.3 @@ -51,9 +51,9 @@
    30.4  
    30.5  
    30.6  static void
    30.7 -BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    30.8 +BSDAUDIO_DetectDevices(void)
    30.9  {
   30.10 -    SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
   30.11 +    SDL_EnumUnixAudioDevices(0, NULL);
   30.12  }
   30.13  
   30.14  
   30.15 @@ -150,7 +150,7 @@
   30.16                 the user know what happened.
   30.17               */
   30.18              fprintf(stderr, "SDL: %s\n", message);
   30.19 -            this->enabled = 0;
   30.20 +            SDL_OpenedAudioDeviceDisconnected(this);
   30.21              /* Don't try to close - may hang */
   30.22              this->hidden->audio_fd = -1;
   30.23  #ifdef DEBUG_AUDIO
   30.24 @@ -195,7 +195,7 @@
   30.25  
   30.26      /* If we couldn't write, assume fatal error for now */
   30.27      if (written < 0) {
   30.28 -        this->enabled = 0;
   30.29 +        SDL_OpenedAudioDeviceDisconnected(this);
   30.30      }
   30.31  #ifdef DEBUG_AUDIO
   30.32      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   30.33 @@ -224,7 +224,7 @@
   30.34  }
   30.35  
   30.36  static int
   30.37 -BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   30.38 +BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   30.39  {
   30.40      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   30.41      SDL_AudioFormat format = 0;
   30.42 @@ -348,6 +348,8 @@
   30.43      impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
   30.44      impl->CloseDevice = BSDAUDIO_CloseDevice;
   30.45  
   30.46 +    impl->AllowsArbitraryDeviceNames = 1;
   30.47 +
   30.48      return 1;   /* this audio target is available. */
   30.49  }
   30.50  
    31.1 --- a/src/audio/coreaudio/SDL_coreaudio.c	Sat Jan 24 23:58:07 2015 -0400
    31.2 +++ b/src/audio/coreaudio/SDL_coreaudio.c	Mon Apr 06 15:26:37 2015 -0300
    31.3 @@ -19,6 +19,9 @@
    31.4    3. This notice may not be removed or altered from any source distribution.
    31.5  */
    31.6  #include "../../SDL_internal.h"
    31.7 +
    31.8 +#if SDL_AUDIO_DRIVER_COREAUDIO
    31.9 +
   31.10  #include "SDL_audio.h"
   31.11  #include "../SDL_audio_c.h"
   31.12  #include "../SDL_sysaudio.h"
   31.13 @@ -37,31 +40,48 @@
   31.14      }
   31.15  
   31.16  #if MACOSX_COREAUDIO
   31.17 -typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data);
   31.18 +static const AudioObjectPropertyAddress devlist_address = {
   31.19 +    kAudioHardwarePropertyDevices,
   31.20 +    kAudioObjectPropertyScopeGlobal,
   31.21 +    kAudioObjectPropertyElementMaster
   31.22 +};
   31.23 +
   31.24 +typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data);
   31.25 +
   31.26 +typedef struct AudioDeviceList
   31.27 +{
   31.28 +    AudioDeviceID devid;
   31.29 +    SDL_bool alive;
   31.30 +    struct AudioDeviceList *next;
   31.31 +} AudioDeviceList;
   31.32 +
   31.33 +static AudioDeviceList *output_devs = NULL;
   31.34 +static AudioDeviceList *capture_devs = NULL;
   31.35 +
   31.36 +static SDL_bool
   31.37 +add_to_internal_dev_list(const int iscapture, AudioDeviceID devId)
   31.38 +{
   31.39 +    AudioDeviceList *item = (AudioDeviceList *) SDL_malloc(sizeof (AudioDeviceList));
   31.40 +    if (item == NULL) {
   31.41 +        return SDL_FALSE;
   31.42 +    }
   31.43 +    item->devid = devId;
   31.44 +    item->alive = SDL_TRUE;
   31.45 +    item->next = iscapture ? capture_devs : output_devs;
   31.46 +    if (iscapture) {
   31.47 +        capture_devs = item;
   31.48 +    } else {
   31.49 +        output_devs = item;
   31.50 +    }
   31.51 +
   31.52 +    return SDL_TRUE;
   31.53 +}
   31.54  
   31.55  static void
   31.56 -addToDevList(const char *name, AudioDeviceID devId, void *data)
   31.57 +addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
   31.58  {
   31.59 -    SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
   31.60 -    addfn(name);
   31.61 -}
   31.62 -
   31.63 -typedef struct
   31.64 -{
   31.65 -    const char *findname;
   31.66 -    AudioDeviceID devId;
   31.67 -    int found;
   31.68 -} FindDevIdData;
   31.69 -
   31.70 -static void
   31.71 -findDevId(const char *name, AudioDeviceID devId, void *_data)
   31.72 -{
   31.73 -    FindDevIdData *data = (FindDevIdData *) _data;
   31.74 -    if (!data->found) {
   31.75 -        if (SDL_strcmp(name, data->findname) == 0) {
   31.76 -            data->found = 1;
   31.77 -            data->devId = devId;
   31.78 -        }
   31.79 +    if (add_to_internal_dev_list(iscapture, devId)) {
   31.80 +        SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
   31.81      }
   31.82  }
   31.83  
   31.84 @@ -74,14 +94,8 @@
   31.85      UInt32 i = 0;
   31.86      UInt32 max = 0;
   31.87  
   31.88 -    AudioObjectPropertyAddress addr = {
   31.89 -        kAudioHardwarePropertyDevices,
   31.90 -        kAudioObjectPropertyScopeGlobal,
   31.91 -        kAudioObjectPropertyElementMaster
   31.92 -    };
   31.93 -
   31.94 -    result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr,
   31.95 -                                            0, NULL, &size);
   31.96 +    result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
   31.97 +                                            &devlist_address, 0, NULL, &size);
   31.98      if (result != kAudioHardwareNoError)
   31.99          return;
  31.100  
  31.101 @@ -89,8 +103,8 @@
  31.102      if (devs == NULL)
  31.103          return;
  31.104  
  31.105 -    result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
  31.106 -                                        0, NULL, &size, devs);
  31.107 +    result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
  31.108 +                                        &devlist_address, 0, NULL, &size, devs);
  31.109      if (result != kAudioHardwareNoError)
  31.110          return;
  31.111  
  31.112 @@ -102,10 +116,17 @@
  31.113          AudioBufferList *buflist = NULL;
  31.114          int usable = 0;
  31.115          CFIndex len = 0;
  31.116 +        const AudioObjectPropertyAddress addr = {
  31.117 +            kAudioDevicePropertyStreamConfiguration,
  31.118 +            iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
  31.119 +            kAudioObjectPropertyElementMaster
  31.120 +        };
  31.121  
  31.122 -        addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
  31.123 -                        kAudioDevicePropertyScopeOutput;
  31.124 -        addr.mSelector = kAudioDevicePropertyStreamConfiguration;
  31.125 +        const AudioObjectPropertyAddress nameaddr = {
  31.126 +            kAudioObjectPropertyName,
  31.127 +            iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
  31.128 +            kAudioObjectPropertyElementMaster
  31.129 +        };
  31.130  
  31.131          result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size);
  31.132          if (result != noErr)
  31.133 @@ -133,9 +154,9 @@
  31.134          if (!usable)
  31.135              continue;
  31.136  
  31.137 -        addr.mSelector = kAudioObjectPropertyName;
  31.138 +
  31.139          size = sizeof (CFStringRef);
  31.140 -        result = AudioObjectGetPropertyData(dev, &addr, 0, NULL, &size, &cfstr);
  31.141 +        result = AudioObjectGetPropertyData(dev, &nameaddr, 0, NULL, &size, &cfstr);
  31.142          if (result != kAudioHardwareNoError)
  31.143              continue;
  31.144  
  31.145 @@ -166,79 +187,84 @@
  31.146                     ((iscapture) ? "capture" : "output"),
  31.147                     (int) *devCount, ptr, (int) dev);
  31.148  #endif
  31.149 -            addfn(ptr, dev, addfndata);
  31.150 +            addfn(ptr, iscapture, dev, addfndata);
  31.151          }
  31.152          SDL_free(ptr);  /* addfn() would have copied the string. */
  31.153      }
  31.154  }
  31.155  
  31.156  static void
  31.157 -COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
  31.158 +free_audio_device_list(AudioDeviceList **list)
  31.159  {
  31.160 -    build_device_list(iscapture, addToDevList, addfn);
  31.161 +    AudioDeviceList *item = *list;
  31.162 +    while (item) {
  31.163 +        AudioDeviceList *next = item->next;
  31.164 +        SDL_free(item);
  31.165 +        item = next;
  31.166 +    }
  31.167 +    *list = NULL;
  31.168  }
  31.169  
  31.170 -static int
  31.171 -find_device_by_name(_THIS, const char *devname, int iscapture)
  31.172 +static void
  31.173 +COREAUDIO_DetectDevices(void)
  31.174  {
  31.175 -    AudioDeviceID devid = 0;
  31.176 -    OSStatus result = noErr;
  31.177 -    UInt32 size = 0;
  31.178 -    UInt32 alive = 0;
  31.179 -    pid_t pid = 0;
  31.180 +    build_device_list(SDL_TRUE, addToDevList, NULL);
  31.181 +    build_device_list(SDL_FALSE, addToDevList, NULL);
  31.182 +}
  31.183  
  31.184 -    AudioObjectPropertyAddress addr = {
  31.185 -        0,
  31.186 -        kAudioObjectPropertyScopeGlobal,
  31.187 -        kAudioObjectPropertyElementMaster
  31.188 -    };
  31.189 -
  31.190 -    if (devname == NULL) {
  31.191 -        size = sizeof (AudioDeviceID);
  31.192 -        addr.mSelector =
  31.193 -            ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
  31.194 -            kAudioHardwarePropertyDefaultOutputDevice);
  31.195 -        result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
  31.196 -                                            0, NULL, &size, &devid);
  31.197 -        CHECK_RESULT("AudioHardwareGetProperty (default device)");
  31.198 -    } else {
  31.199 -        FindDevIdData data;
  31.200 -        SDL_zero(data);
  31.201 -        data.findname = devname;
  31.202 -        build_device_list(iscapture, findDevId, &data);
  31.203 -        if (!data.found) {
  31.204 -            SDL_SetError("CoreAudio: No such audio device.");
  31.205 -            return 0;
  31.206 +static void
  31.207 +build_device_change_list(const char *name, const int iscapture, AudioDeviceID devId, void *data)
  31.208 +{
  31.209 +    AudioDeviceList **list = (AudioDeviceList **) data;
  31.210 +    AudioDeviceList *item;
  31.211 +    for (item = *list; item != NULL; item = item->next) {
  31.212 +        if (item->devid == devId) {
  31.213 +            item->alive = SDL_TRUE;
  31.214 +            return;
  31.215          }
  31.216 -        devid = data.devId;
  31.217      }
  31.218  
  31.219 -    addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
  31.220 -    addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
  31.221 -                    kAudioDevicePropertyScopeOutput;
  31.222 +    add_to_internal_dev_list(iscapture, devId);  /* new device, add it. */
  31.223 +    SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
  31.224 +}
  31.225  
  31.226 -    size = sizeof (alive);
  31.227 -    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
  31.228 -    CHECK_RESULT
  31.229 -        ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
  31.230 -
  31.231 -    if (!alive) {
  31.232 -        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
  31.233 -        return 0;
  31.234 +static void
  31.235 +reprocess_device_list(const int iscapture, AudioDeviceList **list)
  31.236 +{
  31.237 +    AudioDeviceList *item;
  31.238 +    AudioDeviceList *prev = NULL;
  31.239 +    for (item = *list; item != NULL; item = item->next) {
  31.240 +        item->alive = SDL_FALSE;
  31.241      }
  31.242  
  31.243 -    addr.mSelector = kAudioDevicePropertyHogMode;
  31.244 -    size = sizeof (pid);
  31.245 -    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
  31.246 +    build_device_list(iscapture, build_device_change_list, list);
  31.247  
  31.248 -    /* some devices don't support this property, so errors are fine here. */
  31.249 -    if ((result == noErr) && (pid != -1)) {
  31.250 -        SDL_SetError("CoreAudio: requested device is being hogged.");
  31.251 -        return 0;
  31.252 +    /* free items in the list that aren't still alive. */
  31.253 +    item = *list;
  31.254 +    while (item != NULL) {
  31.255 +        AudioDeviceList *next = item->next;
  31.256 +        if (item->alive) {
  31.257 +            prev = item;
  31.258 +        } else {
  31.259 +            SDL_RemoveAudioDevice(iscapture, (void *) ((size_t) item->devid));
  31.260 +            if (prev) {
  31.261 +                prev->next = item->next;
  31.262 +            } else {
  31.263 +                *list = item->next;
  31.264 +            }
  31.265 +            SDL_free(item);
  31.266 +        }
  31.267 +        item = next;
  31.268      }
  31.269 +}
  31.270  
  31.271 -    this->hidden->deviceID = devid;
  31.272 -    return 1;
  31.273 +/* this is called when the system's list of available audio devices changes. */
  31.274 +static OSStatus
  31.275 +device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
  31.276 +{
  31.277 +    reprocess_device_list(SDL_TRUE, &capture_devs);
  31.278 +    reprocess_device_list(SDL_FALSE, &output_devs);
  31.279 +    return 0;
  31.280  }
  31.281  #endif
  31.282  
  31.283 @@ -314,11 +340,54 @@
  31.284  }
  31.285  
  31.286  
  31.287 +#if MACOSX_COREAUDIO
  31.288 +static const AudioObjectPropertyAddress alive_address =
  31.289 +{
  31.290 +    kAudioDevicePropertyDeviceIsAlive,
  31.291 +    kAudioObjectPropertyScopeGlobal,
  31.292 +    kAudioObjectPropertyElementMaster
  31.293 +};
  31.294 +
  31.295 +static OSStatus
  31.296 +device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
  31.297 +{
  31.298 +    SDL_AudioDevice *this = (SDL_AudioDevice *) data;
  31.299 +    SDL_bool dead = SDL_FALSE;
  31.300 +    UInt32 isAlive = 1;
  31.301 +    UInt32 size = sizeof (isAlive);
  31.302 +    OSStatus error;
  31.303 +
  31.304 +    if (!this->enabled) {
  31.305 +        return 0;  /* already known to be dead. */
  31.306 +    }
  31.307 +
  31.308 +    error = AudioObjectGetPropertyData(this->hidden->deviceID, &alive_address,
  31.309 +                                       0, NULL, &size, &isAlive);
  31.310 +
  31.311 +    if (error == kAudioHardwareBadDeviceError) {
  31.312 +        dead = SDL_TRUE;  /* device was unplugged. */
  31.313 +    } else if ((error == kAudioHardwareNoError) && (!isAlive)) {
  31.314 +        dead = SDL_TRUE;  /* device died in some other way. */
  31.315 +    }
  31.316 +
  31.317 +    if (dead) {
  31.318 +        SDL_OpenedAudioDeviceDisconnected(this);
  31.319 +    }
  31.320 +
  31.321 +    return 0;
  31.322 +}
  31.323 +#endif
  31.324 +
  31.325  static void
  31.326  COREAUDIO_CloseDevice(_THIS)
  31.327  {
  31.328      if (this->hidden != NULL) {
  31.329          if (this->hidden->audioUnitOpened) {
  31.330 +            #if MACOSX_COREAUDIO
  31.331 +            /* Unregister our disconnect callback. */
  31.332 +            AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
  31.333 +            #endif
  31.334 +
  31.335              AURenderCallbackStruct callback;
  31.336              const AudioUnitElement output_bus = 0;
  31.337              const AudioUnitElement input_bus = 1;
  31.338 @@ -352,9 +421,63 @@
  31.339      }
  31.340  }
  31.341  
  31.342 +#if MACOSX_COREAUDIO
  31.343 +static int
  31.344 +prepare_device(_THIS, void *handle, int iscapture)
  31.345 +{
  31.346 +    AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
  31.347 +    OSStatus result = noErr;
  31.348 +    UInt32 size = 0;
  31.349 +    UInt32 alive = 0;
  31.350 +    pid_t pid = 0;
  31.351 +
  31.352 +    AudioObjectPropertyAddress addr = {
  31.353 +        0,
  31.354 +        kAudioObjectPropertyScopeGlobal,
  31.355 +        kAudioObjectPropertyElementMaster
  31.356 +    };
  31.357 +
  31.358 +    if (handle == NULL) {
  31.359 +        size = sizeof (AudioDeviceID);
  31.360 +        addr.mSelector =
  31.361 +            ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
  31.362 +            kAudioHardwarePropertyDefaultOutputDevice);
  31.363 +        result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
  31.364 +                                            0, NULL, &size, &devid);
  31.365 +        CHECK_RESULT("AudioHardwareGetProperty (default device)");
  31.366 +    }
  31.367 +
  31.368 +    addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
  31.369 +    addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
  31.370 +                    kAudioDevicePropertyScopeOutput;
  31.371 +
  31.372 +    size = sizeof (alive);
  31.373 +    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
  31.374 +    CHECK_RESULT
  31.375 +        ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
  31.376 +
  31.377 +    if (!alive) {
  31.378 +        SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
  31.379 +        return 0;
  31.380 +    }
  31.381 +
  31.382 +    addr.mSelector = kAudioDevicePropertyHogMode;
  31.383 +    size = sizeof (pid);
  31.384 +    result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
  31.385 +
  31.386 +    /* some devices don't support this property, so errors are fine here. */
  31.387 +    if ((result == noErr) && (pid != -1)) {
  31.388 +        SDL_SetError("CoreAudio: requested device is being hogged.");
  31.389 +        return 0;
  31.390 +    }
  31.391 +
  31.392 +    this->hidden->deviceID = devid;
  31.393 +    return 1;
  31.394 +}
  31.395 +#endif
  31.396  
  31.397  static int
  31.398 -prepare_audiounit(_THIS, const char *devname, int iscapture,
  31.399 +prepare_audiounit(_THIS, void *handle, int iscapture,
  31.400                    const AudioStreamBasicDescription * strdesc)
  31.401  {
  31.402      OSStatus result = noErr;
  31.403 @@ -373,8 +496,7 @@
  31.404                                    kAudioUnitScope_Input);
  31.405  
  31.406  #if MACOSX_COREAUDIO
  31.407 -    if (!find_device_by_name(this, devname, iscapture)) {
  31.408 -        SDL_SetError("Couldn't find requested CoreAudio device");
  31.409 +    if (!prepare_device(this, handle, iscapture)) {
  31.410          return 0;
  31.411      }
  31.412  #endif
  31.413 @@ -451,13 +573,18 @@
  31.414      result = AudioOutputUnitStart(this->hidden->audioUnit);
  31.415      CHECK_RESULT("AudioOutputUnitStart");
  31.416  
  31.417 +#if MACOSX_COREAUDIO
  31.418 +    /* Fire a callback if the device stops being "alive" (disconnected, etc). */
  31.419 +    AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
  31.420 +#endif
  31.421 +
  31.422      /* We're running! */
  31.423      return 1;
  31.424  }
  31.425  
  31.426  
  31.427  static int
  31.428 -COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
  31.429 +COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
  31.430  {
  31.431      AudioStreamBasicDescription strdesc;
  31.432      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
  31.433 @@ -516,7 +643,7 @@
  31.434      strdesc.mBytesPerPacket =
  31.435          strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
  31.436  
  31.437 -    if (!prepare_audiounit(this, devname, iscapture, &strdesc)) {
  31.438 +    if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
  31.439          COREAUDIO_CloseDevice(this);
  31.440          return -1;      /* prepare_audiounit() will call SDL_SetError()... */
  31.441      }
  31.442 @@ -524,15 +651,27 @@
  31.443      return 0;   /* good to go. */
  31.444  }
  31.445  
  31.446 +static void
  31.447 +COREAUDIO_Deinitialize(void)
  31.448 +{
  31.449 +#if MACOSX_COREAUDIO
  31.450 +    AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
  31.451 +    free_audio_device_list(&capture_devs);
  31.452 +    free_audio_device_list(&output_devs);
  31.453 +#endif
  31.454 +}
  31.455 +
  31.456  static int
  31.457  COREAUDIO_Init(SDL_AudioDriverImpl * impl)
  31.458  {
  31.459      /* Set the function pointers */
  31.460      impl->OpenDevice = COREAUDIO_OpenDevice;
  31.461      impl->CloseDevice = COREAUDIO_CloseDevice;
  31.462 +    impl->Deinitialize = COREAUDIO_Deinitialize;
  31.463  
  31.464  #if MACOSX_COREAUDIO
  31.465      impl->DetectDevices = COREAUDIO_DetectDevices;
  31.466 +    AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
  31.467  #else
  31.468      impl->OnlyHasDefaultOutputDevice = 1;
  31.469  
  31.470 @@ -554,4 +693,6 @@
  31.471      "coreaudio", "CoreAudio", COREAUDIO_Init, 0
  31.472  };
  31.473  
  31.474 +#endif /* SDL_AUDIO_DRIVER_COREAUDIO */
  31.475 +
  31.476  /* vi: set ts=4 sw=4 expandtab: */
    32.1 --- a/src/audio/directsound/SDL_directsound.c	Sat Jan 24 23:58:07 2015 -0400
    32.2 +++ b/src/audio/directsound/SDL_directsound.c	Mon Apr 06 15:26:37 2015 -0300
    32.3 @@ -144,15 +144,22 @@
    32.4      return SDL_SetError("%s", errbuf);
    32.5  }
    32.6  
    32.7 +static void
    32.8 +DSOUND_FreeDeviceHandle(void *handle)
    32.9 +{
   32.10 +    SDL_free(handle);
   32.11 +}
   32.12  
   32.13  static BOOL CALLBACK
   32.14  FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
   32.15  {
   32.16 -    SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
   32.17 +    const int iscapture = (int) ((size_t) data);
   32.18      if (guid != NULL) {  /* skip default device */
   32.19          char *str = WIN_StringToUTF8(desc);
   32.20          if (str != NULL) {
   32.21 -            addfn(str);
   32.22 +            LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
   32.23 +            SDL_memcpy(cpyguid, guid, sizeof (GUID));
   32.24 +            SDL_AddAudioDevice(iscapture, str, cpyguid);
   32.25              SDL_free(str);  /* addfn() makes a copy of this string. */
   32.26          }
   32.27      }
   32.28 @@ -160,13 +167,10 @@
   32.29  }
   32.30  
   32.31  static void
   32.32 -DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
   32.33 +DSOUND_DetectDevices(void)
   32.34  {
   32.35 -    if (iscapture) {
   32.36 -        pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
   32.37 -    } else {
   32.38 -        pDirectSoundEnumerateW(FindAllDevs, addfn);
   32.39 -    }
   32.40 +    pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1));
   32.41 +    pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0));
   32.42  }
   32.43  
   32.44  
   32.45 @@ -419,53 +423,14 @@
   32.46      return (numchunks);
   32.47  }
   32.48  
   32.49 -typedef struct FindDevGUIDData
   32.50 -{
   32.51 -    const char *devname;
   32.52 -    GUID guid;
   32.53 -    int found;
   32.54 -} FindDevGUIDData;
   32.55 -
   32.56 -static BOOL CALLBACK
   32.57 -FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
   32.58 -{
   32.59 -    if (guid != NULL) {  /* skip the default device. */
   32.60 -        FindDevGUIDData *data = (FindDevGUIDData *) _data;
   32.61 -        char *str = WIN_StringToUTF8(desc);
   32.62 -        const int match = (SDL_strcmp(str, data->devname) == 0);
   32.63 -        SDL_free(str);
   32.64 -        if (match) {
   32.65 -            data->found = 1;
   32.66 -            SDL_memcpy(&data->guid, guid, sizeof (data->guid));
   32.67 -            return FALSE;  /* found it! stop enumerating. */
   32.68 -        }
   32.69 -    }
   32.70 -    return TRUE;  /* keep enumerating. */
   32.71 -}
   32.72 -
   32.73  static int
   32.74 -DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
   32.75 +DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   32.76  {
   32.77      HRESULT result;
   32.78      SDL_bool valid_format = SDL_FALSE;
   32.79      SDL_bool tried_format = SDL_FALSE;
   32.80      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   32.81 -    FindDevGUIDData devguid;
   32.82 -    LPGUID guid = NULL;
   32.83 -
   32.84 -    if (devname != NULL) {
   32.85 -        devguid.found = 0;
   32.86 -        devguid.devname = devname;
   32.87 -        if (iscapture)
   32.88 -            pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
   32.89 -        else
   32.90 -            pDirectSoundEnumerateW(FindDevGUID, &devguid);
   32.91 -
   32.92 -        if (!devguid.found) {
   32.93 -            return SDL_SetError("DirectSound: Requested device not found");
   32.94 -        }
   32.95 -        guid = &devguid.guid;
   32.96 -    }
   32.97 +    LPGUID guid = (LPGUID) handle;
   32.98  
   32.99      /* Initialize all variables that we clean on shutdown */
  32.100      this->hidden = (struct SDL_PrivateAudioData *)
  32.101 @@ -536,6 +501,8 @@
  32.102      impl->WaitDone = DSOUND_WaitDone;
  32.103      impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
  32.104      impl->CloseDevice = DSOUND_CloseDevice;
  32.105 +    impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
  32.106 +
  32.107      impl->Deinitialize = DSOUND_Deinitialize;
  32.108  
  32.109      return 1;   /* this audio target is available. */
    33.1 --- a/src/audio/disk/SDL_diskaudio.c	Sat Jan 24 23:58:07 2015 -0400
    33.2 +++ b/src/audio/disk/SDL_diskaudio.c	Mon Apr 06 15:26:37 2015 -0300
    33.3 @@ -71,7 +71,7 @@
    33.4  
    33.5      /* If we couldn't write, assume fatal error for now */
    33.6      if (written != this->hidden->mixlen) {
    33.7 -        this->enabled = 0;
    33.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    33.9      }
   33.10  #ifdef DEBUG_AUDIO
   33.11      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   33.12 @@ -100,7 +100,7 @@
   33.13  }
   33.14  
   33.15  static int
   33.16 -DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture)
   33.17 +DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   33.18  {
   33.19      const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
   33.20      const char *fname = DISKAUD_GetOutputFilename(devname);
   33.21 @@ -151,6 +151,8 @@
   33.22      impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
   33.23      impl->CloseDevice = DISKAUD_CloseDevice;
   33.24  
   33.25 +    impl->AllowsArbitraryDeviceNames = 1;
   33.26 +
   33.27      return 1;   /* this audio target is available. */
   33.28  }
   33.29  
    34.1 --- a/src/audio/dsp/SDL_dspaudio.c	Sat Jan 24 23:58:07 2015 -0400
    34.2 +++ b/src/audio/dsp/SDL_dspaudio.c	Mon Apr 06 15:26:37 2015 -0300
    34.3 @@ -51,9 +51,9 @@
    34.4  
    34.5  
    34.6  static void
    34.7 -DSP_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    34.8 +DSP_DetectDevices(void)
    34.9  {
   34.10 -    SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn);
   34.11 +    SDL_EnumUnixAudioDevices(0, NULL);
   34.12  }
   34.13  
   34.14  
   34.15 @@ -74,7 +74,7 @@
   34.16  
   34.17  
   34.18  static int
   34.19 -DSP_OpenDevice(_THIS, const char *devname, int iscapture)
   34.20 +DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   34.21  {
   34.22      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   34.23      int format;
   34.24 @@ -270,7 +270,7 @@
   34.25      const int mixlen = this->hidden->mixlen;
   34.26      if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
   34.27          perror("Audio write");
   34.28 -        this->enabled = 0;
   34.29 +        SDL_OpenedAudioDeviceDisconnected(this);
   34.30      }
   34.31  #ifdef DEBUG_AUDIO
   34.32      fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
   34.33 @@ -293,6 +293,8 @@
   34.34      impl->GetDeviceBuf = DSP_GetDeviceBuf;
   34.35      impl->CloseDevice = DSP_CloseDevice;
   34.36  
   34.37 +    impl->AllowsArbitraryDeviceNames = 1;
   34.38 +
   34.39      return 1;   /* this audio target is available. */
   34.40  }
   34.41  
    35.1 --- a/src/audio/dummy/SDL_dummyaudio.c	Sat Jan 24 23:58:07 2015 -0400
    35.2 +++ b/src/audio/dummy/SDL_dummyaudio.c	Mon Apr 06 15:26:37 2015 -0300
    35.3 @@ -27,7 +27,7 @@
    35.4  #include "SDL_dummyaudio.h"
    35.5  
    35.6  static int
    35.7 -DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture)
    35.8 +DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    35.9  {
   35.10      return 0;                   /* always succeeds. */
   35.11  }
    36.1 --- a/src/audio/emscripten/SDL_emscriptenaudio.c	Sat Jan 24 23:58:07 2015 -0400
    36.2 +++ b/src/audio/emscripten/SDL_emscriptenaudio.c	Mon Apr 06 15:26:37 2015 -0300
    36.3 @@ -151,12 +151,13 @@
    36.4  }
    36.5  
    36.6  static int
    36.7 -Emscripten_OpenDevice(_THIS, const char *devname, int iscapture)
    36.8 +Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    36.9  {
   36.10      SDL_bool valid_format = SDL_FALSE;
   36.11      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   36.12      int i;
   36.13      float f;
   36.14 +    int result;
   36.15  
   36.16      while ((!valid_format) && (test_format)) {
   36.17          switch (test_format) {
   36.18 @@ -185,7 +186,7 @@
   36.19      /* based on parts of library_sdl.js */
   36.20  
   36.21      /* create context (TODO: this puts stuff in the global namespace...)*/
   36.22 -    EM_ASM({
   36.23 +    result = EM_ASM_INT_V({
   36.24          if(typeof(SDL2) === 'undefined')
   36.25              SDL2 = {};
   36.26  
   36.27 @@ -198,10 +199,14 @@
   36.28              } else if (typeof(webkitAudioContext) !== 'undefined') {
   36.29                  SDL2.audioContext = new webkitAudioContext();
   36.30              } else {
   36.31 -                throw 'Web Audio API is not available!';
   36.32 +                return -1;
   36.33              }
   36.34          }
   36.35 +        return 0;
   36.36      });
   36.37 +    if (result < 0) {
   36.38 +        return SDL_SetError("Web Audio API is not available!");
   36.39 +    }
   36.40  
   36.41      /* limit to native freq */
   36.42      int sampleRate = EM_ASM_INT_V({
    37.1 --- a/src/audio/esd/SDL_esdaudio.c	Sat Jan 24 23:58:07 2015 -0400
    37.2 +++ b/src/audio/esd/SDL_esdaudio.c	Mon Apr 06 15:26:37 2015 -0300
    37.3 @@ -129,7 +129,7 @@
    37.4          /* Check every 10 loops */
    37.5          if (this->hidden->parent && (((++cnt) % 10) == 0)) {
    37.6              if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
    37.7 -                this->enabled = 0;
    37.8 +                SDL_OpenedAudioDeviceDisconnected(this);
    37.9              }
   37.10          }
   37.11      }
   37.12 @@ -161,7 +161,7 @@
   37.13  
   37.14      /* If we couldn't write, assume fatal error for now */
   37.15      if (written < 0) {
   37.16 -        this->enabled = 0;
   37.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   37.18      }
   37.19  }
   37.20  
   37.21 @@ -215,7 +215,7 @@
   37.22  
   37.23  
   37.24  static int
   37.25 -ESD_OpenDevice(_THIS, const char *devname, int iscapture)
   37.26 +ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   37.27  {
   37.28      esd_format_t format = (ESD_STREAM | ESD_PLAY);
   37.29      SDL_AudioFormat test_format = 0;
    38.1 --- a/src/audio/fusionsound/SDL_fsaudio.c	Sat Jan 24 23:58:07 2015 -0400
    38.2 +++ b/src/audio/fusionsound/SDL_fsaudio.c	Mon Apr 06 15:26:37 2015 -0300
    38.3 @@ -143,7 +143,7 @@
    38.4                                        this->hidden->mixsamples);
    38.5      /* If we couldn't write, assume fatal error for now */
    38.6      if (ret) {
    38.7 -        this->enabled = 0;
    38.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    38.9      }
   38.10  #ifdef DEBUG_AUDIO
   38.11      fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
   38.12 @@ -186,7 +186,7 @@
   38.13  
   38.14  
   38.15  static int
   38.16 -SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
   38.17 +SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   38.18  {
   38.19      int bytes;
   38.20      SDL_AudioFormat test_format = 0, format = 0;
    39.1 --- a/src/audio/haiku/SDL_haikuaudio.cc	Sat Jan 24 23:58:07 2015 -0400
    39.2 +++ b/src/audio/haiku/SDL_haikuaudio.cc	Mon Apr 06 15:26:37 2015 -0300
    39.3 @@ -111,7 +111,7 @@
    39.4  
    39.5  
    39.6  static int
    39.7 -HAIKUAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
    39.8 +HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    39.9  {
   39.10      int valid_datatype = 0;
   39.11      media_raw_audio_format format;
    40.1 --- a/src/audio/nacl/SDL_naclaudio.c	Sat Jan 24 23:58:07 2015 -0400
    40.2 +++ b/src/audio/nacl/SDL_naclaudio.c	Mon Apr 06 15:26:37 2015 -0300
    40.3 @@ -20,6 +20,9 @@
    40.4  */
    40.5  
    40.6  #include "../../SDL_internal.h"
    40.7 +
    40.8 +#if SDL_AUDIO_DRIVER_NACL
    40.9 +
   40.10  #include "SDL_naclaudio.h"
   40.11  
   40.12  #include "SDL_audio.h"
   40.13 @@ -40,7 +43,7 @@
   40.14  #define SAMPLE_FRAME_COUNT 4096
   40.15  
   40.16  /* Audio driver functions */
   40.17 -static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture);
   40.18 +static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
   40.19  static void NACLAUD_CloseDevice(_THIS);
   40.20  static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
   40.21  
   40.22 @@ -82,7 +85,7 @@
   40.23  }
   40.24  
   40.25  static int
   40.26 -NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) {
   40.27 +NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
   40.28      PP_Instance instance = PSGetInstanceId();
   40.29      const PPB_Audio *ppb_audio = PSInterfaceAudio();
   40.30      const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
   40.31 @@ -127,9 +130,7 @@
   40.32      /* Set the function pointers */
   40.33      impl->OpenDevice = NACLAUD_OpenDevice;
   40.34      impl->CloseDevice = NACLAUD_CloseDevice;
   40.35 -    impl->HasCaptureSupport = 0;
   40.36      impl->OnlyHasDefaultOutputDevice = 1;
   40.37 -    impl->OnlyHasDefaultInputDevice = 1;
   40.38      impl->ProvidesOwnCallbackThread = 1;
   40.39      /*
   40.40       *    impl->WaitDevice = NACLAUD_WaitDevice;
   40.41 @@ -145,3 +146,7 @@
   40.42      NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
   40.43      NACLAUD_Init, 0
   40.44  };
   40.45 +
   40.46 +#endif /* SDL_AUDIO_DRIVER_NACL */
   40.47 +
   40.48 +/* vi: set ts=4 sw=4 expandtab: */
    41.1 --- a/src/audio/nas/SDL_nasaudio.c	Sat Jan 24 23:58:07 2015 -0400
    41.2 +++ b/src/audio/nas/SDL_nasaudio.c	Mon Apr 06 15:26:37 2015 -0300
    41.3 @@ -276,7 +276,7 @@
    41.4  }
    41.5  
    41.6  static int
    41.7 -NAS_OpenDevice(_THIS, const char *devname, int iscapture)
    41.8 +NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
    41.9  {
   41.10      AuElement elms[3];
   41.11      int buffer_size;
    42.1 --- a/src/audio/paudio/SDL_paudio.c	Sat Jan 24 23:58:07 2015 -0400
    42.2 +++ b/src/audio/paudio/SDL_paudio.c	Mon Apr 06 15:26:37 2015 -0300
    42.3 @@ -176,7 +176,7 @@
    42.4               * the user know what happened.
    42.5               */
    42.6              fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message);
    42.7 -            this->enabled = 0;
    42.8 +            SDL_OpenedAudioDeviceDisconnected(this);
    42.9              /* Don't try to close - may hang */
   42.10              this->hidden->audio_fd = -1;
   42.11  #ifdef DEBUG_AUDIO
   42.12 @@ -212,7 +212,7 @@
   42.13  
   42.14      /* If we couldn't write, assume fatal error for now */
   42.15      if (written < 0) {
   42.16 -        this->enabled = 0;
   42.17 +        SDL_OpenedAudioDeviceDisconnected(this);
   42.18      }
   42.19  #ifdef DEBUG_AUDIO
   42.20      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   42.21 @@ -241,7 +241,7 @@
   42.22  }
   42.23  
   42.24  static int
   42.25 -PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   42.26 +PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   42.27  {
   42.28      const char *workaround = SDL_getenv("SDL_DSP_NOSELECT");
   42.29      char audiodev[1024];
    43.1 --- a/src/audio/psp/SDL_pspaudio.c	Sat Jan 24 23:58:07 2015 -0400
    43.2 +++ b/src/audio/psp/SDL_pspaudio.c	Mon Apr 06 15:26:37 2015 -0300
    43.3 @@ -18,6 +18,9 @@
    43.4       misrepresented as being the original software.
    43.5    3. This notice may not be removed or altered from any source distribution.
    43.6  */
    43.7 +#include "../../SDL_internal.h"
    43.8 +
    43.9 +#if SDL_AUDIO_DRIVER_PSP
   43.10  
   43.11  #include <stdio.h>
   43.12  #include <string.h>
   43.13 @@ -40,7 +43,7 @@
   43.14  #define PSPAUD_DRIVER_NAME         "psp"
   43.15  
   43.16  static int
   43.17 -PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
   43.18 +PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   43.19  {
   43.20      int format, mixlen, i;
   43.21      this->hidden = (struct SDL_PrivateAudioData *)
   43.22 @@ -191,5 +194,6 @@
   43.23  
   43.24   /* SDL_AUDI */
   43.25  
   43.26 +#endif /* SDL_AUDIO_DRIVER_PSP */
   43.27  
   43.28 -
   43.29 +/* vi: set ts=4 sw=4 expandtab: */
    44.1 --- a/src/audio/psp/SDL_pspaudio.h	Sat Jan 24 23:58:07 2015 -0400
    44.2 +++ b/src/audio/psp/SDL_pspaudio.h	Mon Apr 06 15:26:37 2015 -0300
    44.3 @@ -24,7 +24,7 @@
    44.4  
    44.5  #include "../SDL_sysaudio.h"
    44.6  
    44.7 -/* Hidden "this" pointer for the video functions */
    44.8 +/* Hidden "this" pointer for the audio functions */
    44.9  #define _THIS   SDL_AudioDevice *this
   44.10  
   44.11  #define NUM_BUFFERS 2
    45.1 --- a/src/audio/pulseaudio/SDL_pulseaudio.c	Sat Jan 24 23:58:07 2015 -0400
    45.2 +++ b/src/audio/pulseaudio/SDL_pulseaudio.c	Mon Apr 06 15:26:37 2015 -0300
    45.3 @@ -26,6 +26,7 @@
    45.4     Stéphan Kochen: stephan .a.t. kochen.nl
    45.5  */
    45.6  #include "../../SDL_internal.h"
    45.7 +#include "SDL_assert.h"
    45.8  
    45.9  #if SDL_AUDIO_DRIVER_PULSEAUDIO
   45.10  
   45.11 @@ -38,7 +39,6 @@
   45.12  #include <sys/types.h>
   45.13  #include <errno.h>
   45.14  #include <pulse/pulseaudio.h>
   45.15 -#include <pulse/simple.h>
   45.16  
   45.17  #include "SDL_timer.h"
   45.18  #include "SDL_audio.h"
   45.19 @@ -66,16 +66,14 @@
   45.20  
   45.21  
   45.22  static const char *(*PULSEAUDIO_pa_get_library_version) (void);
   45.23 -static pa_simple *(*PULSEAUDIO_pa_simple_new) (const char *, const char *,
   45.24 -    pa_stream_direction_t, const char *, const char *, const pa_sample_spec *,
   45.25 -    const pa_channel_map *, const pa_buffer_attr *, int *);
   45.26 -static void (*PULSEAUDIO_pa_simple_free) (pa_simple *);
   45.27  static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto) (
   45.28      pa_channel_map *, unsigned, pa_channel_map_def_t);
   45.29  static const char * (*PULSEAUDIO_pa_strerror) (int);
   45.30  static pa_mainloop * (*PULSEAUDIO_pa_mainloop_new) (void);
   45.31  static pa_mainloop_api * (*PULSEAUDIO_pa_mainloop_get_api) (pa_mainloop *);
   45.32  static int (*PULSEAUDIO_pa_mainloop_iterate) (pa_mainloop *, int, int *);
   45.33 +static int (*PULSEAUDIO_pa_mainloop_run) (pa_mainloop *, int *);
   45.34 +static void (*PULSEAUDIO_pa_mainloop_quit) (pa_mainloop *, int);
   45.35  static void (*PULSEAUDIO_pa_mainloop_free) (pa_mainloop *);
   45.36  
   45.37  static pa_operation_state_t (*PULSEAUDIO_pa_operation_get_state) (
   45.38 @@ -87,7 +85,13 @@
   45.39      const char *);
   45.40  static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *,
   45.41      pa_context_flags_t, const pa_spawn_api *);
   45.42 +static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list) (pa_context *, pa_sink_info_cb_t, void *);
   45.43 +static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list) (pa_context *, pa_source_info_cb_t, void *);
   45.44 +static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_by_index) (pa_context *, uint32_t, pa_sink_info_cb_t, void *);
   45.45 +static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_by_index) (pa_context *, uint32_t, pa_source_info_cb_t, void *);
   45.46  static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *);
   45.47 +static pa_operation * (*PULSEAUDIO_pa_context_subscribe) (pa_context *, pa_subscription_mask_t, pa_context_success_cb_t, void *);
   45.48 +static void (*PULSEAUDIO_pa_context_set_subscribe_callback) (pa_context *, pa_context_subscribe_cb_t, void *);
   45.49  static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *);
   45.50  static void (*PULSEAUDIO_pa_context_unref) (pa_context *);
   45.51  
   45.52 @@ -179,18 +183,24 @@
   45.53  load_pulseaudio_syms(void)
   45.54  {
   45.55      SDL_PULSEAUDIO_SYM(pa_get_library_version);
   45.56 -    SDL_PULSEAUDIO_SYM(pa_simple_new);
   45.57 -    SDL_PULSEAUDIO_SYM(pa_simple_free);
   45.58      SDL_PULSEAUDIO_SYM(pa_mainloop_new);
   45.59      SDL_PULSEAUDIO_SYM(pa_mainloop_get_api);
   45.60      SDL_PULSEAUDIO_SYM(pa_mainloop_iterate);
   45.61 +    SDL_PULSEAUDIO_SYM(pa_mainloop_run);
   45.62 +    SDL_PULSEAUDIO_SYM(pa_mainloop_quit);
   45.63      SDL_PULSEAUDIO_SYM(pa_mainloop_free);
   45.64      SDL_PULSEAUDIO_SYM(pa_operation_get_state);
   45.65      SDL_PULSEAUDIO_SYM(pa_operation_cancel);
   45.66      SDL_PULSEAUDIO_SYM(pa_operation_unref);
   45.67      SDL_PULSEAUDIO_SYM(pa_context_new);
   45.68      SDL_PULSEAUDIO_SYM(pa_context_connect);
   45.69 +    SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list);
   45.70 +    SDL_PULSEAUDIO_SYM(pa_context_get_source_info_list);
   45.71 +    SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_by_index);
   45.72 +    SDL_PULSEAUDIO_SYM(pa_context_get_source_info_by_index);
   45.73      SDL_PULSEAUDIO_SYM(pa_context_get_state);
   45.74 +    SDL_PULSEAUDIO_SYM(pa_context_subscribe);
   45.75 +    SDL_PULSEAUDIO_SYM(pa_context_set_subscribe_callback);
   45.76      SDL_PULSEAUDIO_SYM(pa_context_disconnect);
   45.77      SDL_PULSEAUDIO_SYM(pa_context_unref);
   45.78      SDL_PULSEAUDIO_SYM(pa_stream_new);
   45.79 @@ -206,122 +216,6 @@
   45.80      return 0;
   45.81  }
   45.82  
   45.83 -
   45.84 -/* Check to see if we can connect to PulseAudio */
   45.85 -static SDL_bool
   45.86 -CheckPulseAudioAvailable()
   45.87 -{
   45.88 -    pa_simple *s;
   45.89 -    pa_sample_spec ss;
   45.90 -
   45.91 -    ss.format = PA_SAMPLE_S16NE;
   45.92 -    ss.channels = 1;
   45.93 -    ss.rate = 22050;
   45.94 -
   45.95 -    s = PULSEAUDIO_pa_simple_new(NULL, "SDL", PA_STREAM_PLAYBACK, NULL,
   45.96 -                                 "Test", &ss, NULL, NULL, NULL);
   45.97 -    if (s) {
   45.98 -        PULSEAUDIO_pa_simple_free(s);
   45.99 -        return SDL_TRUE;
  45.100 -    } else {
  45.101 -        return SDL_FALSE;
  45.102 -    }
  45.103 -}
  45.104 -
  45.105 -/* This function waits until it is possible to write a full sound buffer */
  45.106 -static void
  45.107 -PULSEAUDIO_WaitDevice(_THIS)
  45.108 -{
  45.109 -    struct SDL_PrivateAudioData *h = this->hidden;
  45.110 -
  45.111 -    while(1) {
  45.112 -        if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
  45.113 -            PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
  45.114 -            PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
  45.115 -            this->enabled = 0;
  45.116 -            return;
  45.117 -        }
  45.118 -        if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
  45.119 -            return;
  45.120 -        }
  45.121 -    }
  45.122 -}
  45.123 -
  45.124 -static void
  45.125 -PULSEAUDIO_PlayDevice(_THIS)
  45.126 -{
  45.127 -    /* Write the audio data */
  45.128 -    struct SDL_PrivateAudioData *h = this->hidden;
  45.129 -    if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL,
  45.130 -                                   PA_SEEK_RELATIVE) < 0) {
  45.131 -        this->enabled = 0;
  45.132 -    }
  45.133 -}
  45.134 -
  45.135 -static void
  45.136 -stream_drain_complete(pa_stream *s, int success, void *userdata)
  45.137 -{
  45.138 -    /* no-op for pa_stream_drain() to use for callback. */
  45.139 -}
  45.140 -
  45.141 -static void
  45.142 -PULSEAUDIO_WaitDone(_THIS)
  45.143 -{
  45.144 -    struct SDL_PrivateAudioData *h = this->hidden;
  45.145 -    pa_operation *o;
  45.146 -
  45.147 -    o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
  45.148 -    if (!o) {
  45.149 -        return;
  45.150 -    }
  45.151 -
  45.152 -    while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
  45.153 -        if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
  45.154 -            PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
  45.155 -            PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
  45.156 -            PULSEAUDIO_pa_operation_cancel(o);
  45.157 -            break;
  45.158 -        }
  45.159 -    }
  45.160 -
  45.161 -    PULSEAUDIO_pa_operation_unref(o);
  45.162 -}
  45.163 -
  45.164 -
  45.165 -
  45.166 -static Uint8 *
  45.167 -PULSEAUDIO_GetDeviceBuf(_THIS)
  45.168 -{
  45.169 -    return (this->hidden->mixbuf);
  45.170 -}
  45.171 -
  45.172 -
  45.173 -static void
  45.174 -PULSEAUDIO_CloseDevice(_THIS)
  45.175 -{
  45.176 -    if (this->hidden != NULL) {
  45.177 -        SDL_FreeAudioMem(this->hidden->mixbuf);
  45.178 -        this->hidden->mixbuf = NULL;
  45.179 -        if (this->hidden->stream) {
  45.180 -            PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
  45.181 -            PULSEAUDIO_pa_stream_unref(this->hidden->stream);
  45.182 -            this->hidden->stream = NULL;
  45.183 -        }
  45.184 -        if (this->hidden->context != NULL) {
  45.185 -            PULSEAUDIO_pa_context_disconnect(this->hidden->context);
  45.186 -            PULSEAUDIO_pa_context_unref(this->hidden->context);
  45.187 -            this->hidden->context = NULL;
  45.188 -        }
  45.189 -        if (this->hidden->mainloop != NULL) {
  45.190 -            PULSEAUDIO_pa_mainloop_free(this->hidden->mainloop);
  45.191 -            this->hidden->mainloop = NULL;
  45.192 -        }
  45.193 -        SDL_free(this->hidden);
  45.194 -        this->hidden = NULL;
  45.195 -    }
  45.196 -}
  45.197 -
  45.198 -
  45.199  static SDL_INLINE int
  45.200  squashVersion(const int major, const int minor, const int patch)
  45.201  {
  45.202 @@ -344,8 +238,193 @@
  45.203      return "SDL Application";  /* oh well. */
  45.204  }
  45.205  
  45.206 +static void
  45.207 +WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
  45.208 +{
  45.209 +    /* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */
  45.210 +    if (mainloop && o) {
  45.211 +        SDL_bool okay = SDL_TRUE;
  45.212 +        while (okay && (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING)) {
  45.213 +            okay = (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) >= 0);
  45.214 +        }
  45.215 +        PULSEAUDIO_pa_operation_unref(o);
  45.216 +    }
  45.217 +}
  45.218 +
  45.219 +static void
  45.220 +DisconnectFromPulseServer(pa_mainloop *mainloop, pa_context *context)
  45.221 +{
  45.222 +    if (context) {
  45.223 +        PULSEAUDIO_pa_context_disconnect(context);
  45.224 +        PULSEAUDIO_pa_context_unref(context);
  45.225 +    }
  45.226 +    if (mainloop != NULL) {
  45.227 +        PULSEAUDIO_pa_mainloop_free(mainloop);
  45.228 +    }
  45.229 +}
  45.230 +
  45.231  static int
  45.232 -PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
  45.233 +ConnectToPulseServer_Internal(pa_mainloop **_mainloop, pa_context **_context)
  45.234 +{
  45.235 +    pa_mainloop *mainloop = NULL;
  45.236 +    pa_context *context = NULL;
  45.237 +    pa_mainloop_api *mainloop_api = NULL;
  45.238 +    int state = 0;
  45.239 +
  45.240 +    *_mainloop = NULL;
  45.241 +    *_context = NULL;
  45.242 +
  45.243 +    /* Set up a new main loop */
  45.244 +    if (!(mainloop = PULSEAUDIO_pa_mainloop_new())) {
  45.245 +        return SDL_SetError("pa_mainloop_new() failed");
  45.246 +    }
  45.247 +
  45.248 +    *_mainloop = mainloop;
  45.249 +
  45.250 +    mainloop_api = PULSEAUDIO_pa_mainloop_get_api(mainloop);
  45.251 +    SDL_assert(mainloop_api);  /* this never fails, right? */
  45.252 +
  45.253 +    context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName());
  45.254 +    if (!context) {
  45.255 +        return SDL_SetError("pa_context_new() failed");
  45.256 +    }
  45.257 +    *_context = context;
  45.258 +
  45.259 +    /* Connect to the PulseAudio server */
  45.260 +    if (PULSEAUDIO_pa_context_connect(context, NULL, 0, NULL) < 0) {
  45.261 +        return SDL_SetError("Could not setup connection to PulseAudio");
  45.262 +    }
  45.263 +
  45.264 +    do {
  45.265 +        if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) {
  45.266 +            return SDL_SetError("pa_mainloop_iterate() failed");
  45.267 +        }
  45.268 +        state = PULSEAUDIO_pa_context_get_state(context);
  45.269 +        if (!PA_CONTEXT_IS_GOOD(state)) {
  45.270 +            return SDL_SetError("Could not connect to PulseAudio");
  45.271 +        }
  45.272 +    } while (state != PA_CONTEXT_READY);
  45.273 +
  45.274 +    return 0;  /* connected and ready! */
  45.275 +}
  45.276 +
  45.277 +static int
  45.278 +ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context)
  45.279 +{
  45.280 +    const int retval = ConnectToPulseServer_Internal(_mainloop, _context);
  45.281 +    if (retval < 0) {
  45.282 +        DisconnectFromPulseServer(*_mainloop, *_context);
  45.283 +    }
  45.284 +    return retval;
  45.285 +}
  45.286 +
  45.287 +
  45.288 +/* This function waits until it is possible to write a full sound buffer */
  45.289 +static void
  45.290 +PULSEAUDIO_WaitDevice(_THIS)
  45.291 +{
  45.292 +    struct SDL_PrivateAudioData *h = this->hidden;
  45.293 +
  45.294 +    while (this->enabled) {
  45.295 +        if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
  45.296 +            PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
  45.297 +            PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
  45.298 +            SDL_OpenedAudioDeviceDisconnected(this);
  45.299 +            return;
  45.300 +        }
  45.301 +        if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) {
  45.302 +            return;
  45.303 +        }
  45.304 +    }
  45.305 +}
  45.306 +
  45.307 +static void
  45.308 +PULSEAUDIO_PlayDevice(_THIS)
  45.309 +{
  45.310 +    /* Write the audio data */
  45.311 +    struct SDL_PrivateAudioData *h = this->hidden;
  45.312 +    if (this->enabled) {
  45.313 +        if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
  45.314 +            SDL_OpenedAudioDeviceDisconnected(this);
  45.315 +        }
  45.316 +    }
  45.317 +}
  45.318 +
  45.319 +static void
  45.320 +stream_drain_complete(pa_stream *s, int success, void *userdata)
  45.321 +{
  45.322 +    /* no-op for pa_stream_drain() to use for callback. */
  45.323 +}
  45.324 +
  45.325 +static void
  45.326 +PULSEAUDIO_WaitDone(_THIS)
  45.327 +{
  45.328 +    if (this->enabled) {
  45.329 +        struct SDL_PrivateAudioData *h = this->hidden;
  45.330 +        pa_operation *o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
  45.331 +        if (o) {
  45.332 +            while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
  45.333 +                if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
  45.334 +                    PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
  45.335 +                    PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
  45.336 +                    PULSEAUDIO_pa_operation_cancel(o);
  45.337 +                    break;
  45.338 +                }
  45.339 +            }
  45.340 +            PULSEAUDIO_pa_operation_unref(o);
  45.341 +        }
  45.342 +    }
  45.343 +}
  45.344 +
  45.345 +
  45.346 +
  45.347 +static Uint8 *
  45.348 +PULSEAUDIO_GetDeviceBuf(_THIS)
  45.349 +{
  45.350 +    return (this->hidden->mixbuf);
  45.351 +}
  45.352 +
  45.353 +
  45.354 +static void
  45.355 +PULSEAUDIO_CloseDevice(_THIS)
  45.356 +{
  45.357 +    if (this->hidden != NULL) {
  45.358 +        SDL_FreeAudioMem(this->hidden->mixbuf);
  45.359 +        SDL_free(this->hidden->device_name);
  45.360 +        if (this->hidden->stream) {
  45.361 +            PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
  45.362 +            PULSEAUDIO_pa_stream_unref(this->hidden->stream);
  45.363 +        }
  45.364 +        DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
  45.365 +        SDL_free(this->hidden);
  45.366 +        this->hidden = NULL;
  45.367 +    }
  45.368 +}
  45.369 +
  45.370 +static void
  45.371 +DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
  45.372 +{
  45.373 +    if (i) {
  45.374 +        char **devname = (char **) data;
  45.375 +        *devname = SDL_strdup(i->name);
  45.376 +    }
  45.377 +}
  45.378 +
  45.379 +static SDL_bool
  45.380 +FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
  45.381 +{
  45.382 +    const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
  45.383 +
  45.384 +    if (handle == NULL) {  /* NULL == default device. */
  45.385 +        return SDL_TRUE;
  45.386 +    }
  45.387 +
  45.388 +    WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name));
  45.389 +    return (h->device_name != NULL);
  45.390 +}
  45.391 +
  45.392 +static int
  45.393 +PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
  45.394  {
  45.395      struct SDL_PrivateAudioData *h = NULL;
  45.396      Uint16 test_format = 0;
  45.397 @@ -442,42 +521,21 @@
  45.398      paattr.minreq = h->mixlen;
  45.399  #endif
  45.400  
  45.401 +    if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
  45.402 +        PULSEAUDIO_CloseDevice(this);
  45.403 +        return SDL_SetError("Could not connect to PulseAudio server");
  45.404 +    }
  45.405 +
  45.406 +    if (!FindDeviceName(h, handle)) {
  45.407 +        PULSEAUDIO_CloseDevice(this);
  45.408 +        return SDL_SetError("Requested PulseAudio sink missing?");
  45.409 +    }
  45.410 +
  45.411      /* The SDL ALSA output hints us that we use Windows' channel mapping */
  45.412      /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */
  45.413      PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels,
  45.414                                          PA_CHANNEL_MAP_WAVEEX);
  45.415  
  45.416 -    /* Set up a new main loop */
  45.417 -    if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) {
  45.418 -        PULSEAUDIO_CloseDevice(this);
  45.419 -        return SDL_SetError("pa_mainloop_new() failed");
  45.420 -    }
  45.421 -
  45.422 -    h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop);
  45.423 -    h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName());
  45.424 -    if (!h->context) {
  45.425 -        PULSEAUDIO_CloseDevice(this);
  45.426 -        return SDL_SetError("pa_context_new() failed");
  45.427 -    }
  45.428 -
  45.429 -    /* Connect to the PulseAudio server */
  45.430 -    if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) {
  45.431 -        PULSEAUDIO_CloseDevice(this);
  45.432 -        return SDL_SetError("Could not setup connection to PulseAudio");
  45.433 -    }
  45.434 -
  45.435 -    do {
  45.436 -        if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
  45.437 -            PULSEAUDIO_CloseDevice(this);
  45.438 -            return SDL_SetError("pa_mainloop_iterate() failed");
  45.439 -        }
  45.440 -        state = PULSEAUDIO_pa_context_get_state(h->context);
  45.441 -        if (!PA_CONTEXT_IS_GOOD(state)) {
  45.442 -            PULSEAUDIO_CloseDevice(this);
  45.443 -            return SDL_SetError("Could not connect to PulseAudio");
  45.444 -        }
  45.445 -    } while (state != PA_CONTEXT_READY);
  45.446 -
  45.447      h->stream = PULSEAUDIO_pa_stream_new(
  45.448          h->context,
  45.449          "Simple DirectMedia Layer", /* stream description */
  45.450 @@ -490,7 +548,13 @@
  45.451          return SDL_SetError("Could not set up PulseAudio stream");
  45.452      }
  45.453  
  45.454 -    if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags,
  45.455 +    /* now that we have multi-device support, don't move a stream from
  45.456 +        a device that was unplugged to something else, unless we're default. */
  45.457 +    if (h->device_name != NULL) {
  45.458 +        flags |= PA_STREAM_DONT_MOVE;
  45.459 +    }
  45.460 +
  45.461 +    if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags,
  45.462              NULL, NULL) < 0) {
  45.463          PULSEAUDIO_CloseDevice(this);
  45.464          return SDL_SetError("Could not connect PulseAudio stream");
  45.465 @@ -504,7 +568,7 @@
  45.466          state = PULSEAUDIO_pa_stream_get_state(h->stream);
  45.467          if (!PA_STREAM_IS_GOOD(state)) {
  45.468              PULSEAUDIO_CloseDevice(this);
  45.469 -            return SDL_SetError("Could not create to PulseAudio stream");
  45.470 +            return SDL_SetError("Could not connect PulseAudio stream");
  45.471          }
  45.472      } while (state != PA_STREAM_READY);
  45.473  
  45.474 @@ -512,10 +576,92 @@
  45.475      return 0;
  45.476  }
  45.477  
  45.478 +static pa_mainloop *hotplug_mainloop = NULL;
  45.479 +static pa_context *hotplug_context = NULL;
  45.480 +static SDL_Thread *hotplug_thread = NULL;
  45.481 +
  45.482 +/* device handles are device index + 1, cast to void*, so we never pass a NULL. */
  45.483 +
  45.484 +/* This is called when PulseAudio adds an output ("sink") device. */
  45.485 +static void
  45.486 +SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
  45.487 +{
  45.488 +    if (i) {
  45.489 +        SDL_AddAudioDevice(SDL_FALSE, i->description, (void *) ((size_t) i->index+1));
  45.490 +    }
  45.491 +}
  45.492 +
  45.493 +/* This is called when PulseAudio adds a capture ("source") device. */
  45.494 +static void
  45.495 +SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
  45.496 +{
  45.497 +    if (i) {
  45.498 +        /* Skip "monitor" sources. These are just output from other sinks. */
  45.499 +        if (i->monitor_of_sink == PA_INVALID_INDEX) {
  45.500 +            SDL_AddAudioDevice(SDL_TRUE, i->description, (void *) ((size_t) i->index+1));
  45.501 +        }
  45.502 +    }
  45.503 +}
  45.504 +
  45.505 +/* This is called when PulseAudio has a device connected/removed/changed. */
  45.506 +static void
  45.507 +HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data)
  45.508 +{
  45.509 +    const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW);
  45.510 +    const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE);
  45.511 +
  45.512 +    if (added || removed) {  /* we only care about add/remove events. */
  45.513 +        const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK);
  45.514 +        const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE);
  45.515 +
  45.516 +        /* adds need sink details from the PulseAudio server. Another callback... */
  45.517 +        if (added && sink) {
  45.518 +            PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, NULL);
  45.519 +        } else if (added && source) {
  45.520 +            PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, NULL);
  45.521 +        } else if (removed && (sink || source)) {
  45.522 +            /* removes we can handle just with the device index. */
  45.523 +            SDL_RemoveAudioDevice(source != 0, (void *) ((size_t) idx+1));
  45.524 +        }
  45.525 +    }
  45.526 +}
  45.527 +
  45.528 +/* this runs as a thread while the Pulse target is initialized to catch hotplug events. */
  45.529 +static int SDLCALL
  45.530 +HotplugThread(void *data)
  45.531 +{
  45.532 +    pa_operation *o;
  45.533 +    SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
  45.534 +    PULSEAUDIO_pa_context_set_subscribe_callback(hotplug_context, HotplugCallback, NULL);
  45.535 +    o = PULSEAUDIO_pa_context_subscribe(hotplug_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, NULL, NULL);
  45.536 +    PULSEAUDIO_pa_operation_unref(o);  /* don't wait for it, just do our thing. */
  45.537 +    PULSEAUDIO_pa_mainloop_run(hotplug_mainloop, NULL);
  45.538 +    return 0;
  45.539 +}
  45.540 +
  45.541 +static void
  45.542 +PULSEAUDIO_DetectDevices()
  45.543 +{
  45.544 +    WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, NULL));
  45.545 +    WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL));
  45.546 +
  45.547 +    /* ok, we have a sane list, let's set up hotplug notifications now... */
  45.548 +    hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL);
  45.549 +}
  45.550  
  45.551  static void
  45.552  PULSEAUDIO_Deinitialize(void)
  45.553  {
  45.554 +    if (hotplug_thread) {
  45.555 +        PULSEAUDIO_pa_mainloop_quit(hotplug_mainloop, 0);
  45.556 +        SDL_WaitThread(hotplug_thread, NULL);
  45.557 +        hotplug_thread = NULL;
  45.558 +    }
  45.559 +
  45.560 +    DisconnectFromPulseServer(hotplug_mainloop, hotplug_context);
  45.561 +    hotplug_mainloop = NULL;
  45.562 +    hotplug_context = NULL;
  45.563 +
  45.564      UnloadPulseAudioLibrary();
  45.565  }
  45.566  
  45.567 @@ -526,12 +672,13 @@
  45.568          return 0;
  45.569      }
  45.570  
  45.571 -    if (!CheckPulseAudioAvailable()) {
  45.572 +    if (ConnectToPulseServer(&hotplug_mainloop, &hotplug_context) < 0) {
  45.573          UnloadPulseAudioLibrary();
  45.574          return 0;
  45.575      }
  45.576  
  45.577      /* Set the function pointers */
  45.578 +    impl->DetectDevices = PULSEAUDIO_DetectDevices;
  45.579      impl->OpenDevice = PULSEAUDIO_OpenDevice;
  45.580      impl->PlayDevice = PULSEAUDIO_PlayDevice;
  45.581      impl->WaitDevice = PULSEAUDIO_WaitDevice;
  45.582 @@ -539,12 +686,10 @@
  45.583      impl->CloseDevice = PULSEAUDIO_CloseDevice;
  45.584      impl->WaitDone = PULSEAUDIO_WaitDone;
  45.585      impl->Deinitialize = PULSEAUDIO_Deinitialize;
  45.586 -    impl->OnlyHasDefaultOutputDevice = 1;
  45.587  
  45.588      return 1;   /* this audio target is available. */
  45.589  }
  45.590  
  45.591 -
  45.592  AudioBootStrap PULSEAUDIO_bootstrap = {
  45.593      "pulseaudio", "PulseAudio", PULSEAUDIO_Init, 0
  45.594  };
    46.1 --- a/src/audio/pulseaudio/SDL_pulseaudio.h	Sat Jan 24 23:58:07 2015 -0400
    46.2 +++ b/src/audio/pulseaudio/SDL_pulseaudio.h	Mon Apr 06 15:26:37 2015 -0300
    46.3 @@ -32,9 +32,10 @@
    46.4  
    46.5  struct SDL_PrivateAudioData
    46.6  {
    46.7 +    char *device_name;
    46.8 +
    46.9      /* pulseaudio structures */
   46.10      pa_mainloop *mainloop;
   46.11 -    pa_mainloop_api *mainloop_api;
   46.12      pa_context *context;
   46.13      pa_stream *stream;
   46.14  
    47.1 --- a/src/audio/qsa/SDL_qsa_audio.c	Sat Jan 24 23:58:07 2015 -0400
    47.2 +++ b/src/audio/qsa/SDL_qsa_audio.c	Mon Apr 06 15:26:37 2015 -0300
    47.3 @@ -19,6 +19,15 @@
    47.4    3. This notice may not be removed or altered from any source distribution.
    47.5  */
    47.6  
    47.7 +/*
    47.8 + * !!! FIXME: streamline this a little by removing all the
    47.9 + * !!! FIXME:  if (capture) {} else {} sections that are identical
   47.10 + * !!! FIXME:  except for one flag.
   47.11 + */
   47.12 +
   47.13 +/* !!! FIXME: can this target support hotplugging? */
   47.14 +/* !!! FIXME: ...does SDL2 even support QNX? */
   47.15 +
   47.16  #include "../../SDL_internal.h"
   47.17  
   47.18  #if SDL_AUDIO_DRIVER_QSA
   47.19 @@ -300,7 +309,7 @@
   47.20  
   47.21      /* If we couldn't write, assume fatal error for now */
   47.22      if (towrite != 0) {
   47.23 -        this->enabled = 0;
   47.24 +        SDL_OpenedAudioDeviceDisconnected(this);
   47.25      }
   47.26  }
   47.27  
   47.28 @@ -337,8 +346,9 @@
   47.29  }
   47.30  
   47.31  static int
   47.32 -QSA_OpenDevice(_THIS, const char *devname, int iscapture)
   47.33 +QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   47.34  {
   47.35 +    const QSA_Device *device = (const QSA_Device *) handle;
   47.36      int status = 0;
   47.37      int format = 0;
   47.38      SDL_AudioFormat test_format = 0;
   47.39 @@ -363,80 +373,19 @@
   47.40      /* Initialize channel direction: capture or playback */
   47.41      this->hidden->iscapture = iscapture;
   47.42  
   47.43 -    /* Find deviceid and cardid by device name for playback */
   47.44 -    if ((!this->hidden->iscapture) && (devname != NULL)) {
   47.45 -        uint32_t device;
   47.46 -        int32_t status;
   47.47 -
   47.48 -        /* Search in the playback devices */
   47.49 -        device = 0;
   47.50 -        do {
   47.51 -            status = SDL_strcmp(qsa_playback_device[device].name, devname);
   47.52 -            if (status == 0) {
   47.53 -                /* Found requested device */
   47.54 -                this->hidden->deviceno = qsa_playback_device[device].deviceno;
   47.55 -                this->hidden->cardno = qsa_playback_device[device].cardno;
   47.56 -                break;
   47.57 -            }
   47.58 -            device++;
   47.59 -            if (device >= qsa_playback_devices) {
   47.60 -                QSA_CloseDevice(this);
   47.61 -                return SDL_SetError("No such playback device");
   47.62 -            }
   47.63 -        } while (1);
   47.64 -    }
   47.65 -
   47.66 -    /* Find deviceid and cardid by device name for capture */
   47.67 -    if ((this->hidden->iscapture) && (devname != NULL)) {
   47.68 -        /* Search in the capture devices */
   47.69 -        uint32_t device;
   47.70 -        int32_t status;
   47.71 -
   47.72 -        /* Searching in the playback devices */
   47.73 -        device = 0;
   47.74 -        do {
   47.75 -            status = SDL_strcmp(qsa_capture_device[device].name, devname);
   47.76 -            if (status == 0) {
   47.77 -                /* Found requested device */
   47.78 -                this->hidden->deviceno = qsa_capture_device[device].deviceno;
   47.79 -                this->hidden->cardno = qsa_capture_device[device].cardno;
   47.80 -                break;
   47.81 -            }
   47.82 -            device++;
   47.83 -            if (device >= qsa_capture_devices) {
   47.84 -                QSA_CloseDevice(this);
   47.85 -                return SDL_SetError("No such capture device");
   47.86 -            }
   47.87 -        } while (1);
   47.88 -    }
   47.89 -
   47.90 -    /* Check if SDL requested default audio device */
   47.91 -    if (devname == NULL) {
   47.92 +    if (device != NULL) {
   47.93 +        /* Open requested audio device */
   47.94 +        this->hidden->deviceno = device->deviceno;
   47.95 +        this->hidden->cardno = device->cardno;
   47.96 +        status = snd_pcm_open(&this->hidden->audio_handle,
   47.97 +                              device->cardno, device->deviceno,
   47.98 +                              iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
   47.99 +    } else {
  47.100          /* Open system default audio device */
  47.101 -        if (!this->hidden->iscapture) {
  47.102 -            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  47.103 -                                            &this->hidden->cardno,
  47.104 -                                            &this->hidden->deviceno,
  47.105 -                                            SND_PCM_OPEN_PLAYBACK);
  47.106 -        } else {
  47.107 -            status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  47.108 -                                            &this->hidden->cardno,
  47.109 -                                            &this->hidden->deviceno,
  47.110 -                                            SND_PCM_OPEN_CAPTURE);
  47.111 -        }
  47.112 -    } else {
  47.113 -        /* Open requested audio device */
  47.114 -        if (!this->hidden->iscapture) {
  47.115 -            status =
  47.116 -                snd_pcm_open(&this->hidden->audio_handle,
  47.117 -                             this->hidden->cardno, this->hidden->deviceno,
  47.118 -                             SND_PCM_OPEN_PLAYBACK);
  47.119 -        } else {
  47.120 -            status =
  47.121 -                snd_pcm_open(&this->hidden->audio_handle,
  47.122 -                             this->hidden->cardno, this->hidden->deviceno,
  47.123 -                             SND_PCM_OPEN_CAPTURE);
  47.124 -        }
  47.125 +        status = snd_pcm_open_preferred(&this->hidden->audio_handle,
  47.126 +                                        &this->hidden->cardno,
  47.127 +                                        &this->hidden->deviceno,
  47.128 +                                        iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
  47.129      }
  47.130  
  47.131      /* Check if requested device is opened */
  47.132 @@ -638,7 +587,7 @@
  47.133  }
  47.134  
  47.135  static void
  47.136 -QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
  47.137 +QSA_DetectDevices(void)
  47.138  {
  47.139      uint32_t it;
  47.140      uint32_t cards;
  47.141 @@ -656,8 +605,9 @@
  47.142          return;
  47.143      }
  47.144  
  47.145 +    /* !!! FIXME: code duplication */
  47.146      /* Find requested devices by type */
  47.147 -    if (!iscapture) {
  47.148 +    {  /* output devices */
  47.149          /* Playback devices enumeration requested */
  47.150          for (it = 0; it < cards; it++) {
  47.151              devices = 0;
  47.152 @@ -688,7 +638,7 @@
  47.153                              devices;
  47.154                          status = snd_pcm_close(handle);
  47.155                          if (status == EOK) {
  47.156 -                            addfn(qsa_playback_device[qsa_playback_devices].name);
  47.157 +                            SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]);
  47.158                              qsa_playback_devices++;
  47.159                          }
  47.160                      } else {
  47.161 @@ -713,7 +663,9 @@
  47.162                  break;
  47.163              }
  47.164          }
  47.165 -    } else {
  47.166 +    }
  47.167 +
  47.168 +    {  /* capture devices */
  47.169          /* Capture devices enumeration requested */
  47.170          for (it = 0; it < cards; it++) {
  47.171              devices = 0;
  47.172 @@ -744,7 +696,7 @@
  47.173                              devices;
  47.174                          status = snd_pcm_close(handle);
  47.175                          if (status == EOK) {
  47.176 -                            addfn(qsa_capture_device[qsa_capture_devices].name);
  47.177 +                            SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]);
  47.178                              qsa_capture_devices++;
  47.179                          }
  47.180                      } else {
    48.1 --- a/src/audio/sndio/SDL_sndioaudio.c	Sat Jan 24 23:58:07 2015 -0400
    48.2 +++ b/src/audio/sndio/SDL_sndioaudio.c	Mon Apr 06 15:26:37 2015 -0300
    48.3 @@ -158,7 +158,7 @@
    48.4  
    48.5      /* If we couldn't write, assume fatal error for now */
    48.6      if ( written == 0 ) {
    48.7 -        this->enabled = 0;
    48.8 +        SDL_OpenedAudioDeviceDisconnected(this);
    48.9      }
   48.10  #ifdef DEBUG_AUDIO
   48.11      fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   48.12 @@ -193,7 +193,7 @@
   48.13  }
   48.14  
   48.15  static int
   48.16 -SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   48.17 +SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   48.18  {
   48.19      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   48.20      struct sio_par par;
    49.1 --- a/src/audio/sun/SDL_sunaudio.c	Sat Jan 24 23:58:07 2015 -0400
    49.2 +++ b/src/audio/sun/SDL_sunaudio.c	Mon Apr 06 15:26:37 2015 -0300
    49.3 @@ -56,9 +56,9 @@
    49.4  
    49.5  /* Audio driver bootstrap functions */
    49.6  static void
    49.7 -SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    49.8 +SUNAUDIO_DetectDevices(void)
    49.9  {
   49.10 -    SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn);
   49.11 +    SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL);
   49.12  }
   49.13  
   49.14  #ifdef DEBUG_AUDIO
   49.15 @@ -158,7 +158,7 @@
   49.16          if (write(this->hidden->audio_fd, this->hidden->ulaw_buf,
   49.17              this->hidden->fragsize) < 0) {
   49.18              /* Assume fatal error, for now */
   49.19 -            this->enabled = 0;
   49.20 +            SDL_OpenedAudioDeviceDisconnected(this);
   49.21          }
   49.22          this->hidden->written += this->hidden->fragsize;
   49.23      } else {
   49.24 @@ -168,7 +168,7 @@
   49.25          if (write(this->hidden->audio_fd, this->hidden->mixbuf,
   49.26              this->spec.size) < 0) {
   49.27              /* Assume fatal error, for now */
   49.28 -            this->enabled = 0;
   49.29 +            SDL_OpenedAudioDeviceDisconnected(this);
   49.30          }
   49.31          this->hidden->written += this->hidden->fragsize;
   49.32      }
   49.33 @@ -198,7 +198,7 @@
   49.34  }
   49.35  
   49.36  static int
   49.37 -SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture)
   49.38 +SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   49.39  {
   49.40      const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
   49.41      SDL_AudioFormat format = 0;
   49.42 @@ -414,6 +414,8 @@
   49.43      impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf;
   49.44      impl->CloseDevice = SUNAUDIO_CloseDevice;
   49.45  
   49.46 +    impl->AllowsArbitraryDeviceNames = 1;
   49.47 +
   49.48      return 1; /* this audio target is available. */
   49.49  }
   49.50  
    50.1 --- a/src/audio/winmm/SDL_winmm.c	Sat Jan 24 23:58:07 2015 -0400
    50.2 +++ b/src/audio/winmm/SDL_winmm.c	Mon Apr 06 15:26:37 2015 -0300
    50.3 @@ -36,8 +36,9 @@
    50.4  #define WAVE_FORMAT_IEEE_FLOAT 0x0003
    50.5  #endif
    50.6  
    50.7 -#define DETECT_DEV_IMPL(typ, capstyp) \
    50.8 -static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \
    50.9 +#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
   50.10 +static void DetectWave##typ##Devs(void) { \
   50.11 +    const UINT iscapture = iscap ? 1 : 0; \
   50.12      const UINT devcount = wave##typ##GetNumDevs(); \
   50.13      capstyp caps; \
   50.14      UINT i; \
   50.15 @@ -45,24 +46,21 @@
   50.16          if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
   50.17              char *name = WIN_StringToUTF8(caps.szPname); \
   50.18              if (name != NULL) { \
   50.19 -                addfn(name); \
   50.20 +                SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
   50.21                  SDL_free(name); \
   50.22              } \
   50.23          } \
   50.24      } \
   50.25  }
   50.26  
   50.27 -DETECT_DEV_IMPL(Out, WAVEOUTCAPS)
   50.28 -DETECT_DEV_IMPL(In, WAVEINCAPS)
   50.29 +DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
   50.30 +DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
   50.31  
   50.32  static void
   50.33 -WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
   50.34 +WINMM_DetectDevices(void)
   50.35  {
   50.36 -    if (iscapture) {
   50.37 -        DetectWaveInDevs(addfn);
   50.38 -    } else {
   50.39 -        DetectWaveOutDevs(addfn);
   50.40 -    }
   50.41 +    DetectWaveInDevs();
   50.42 +    DetectWaveOutDevs();
   50.43  }
   50.44  
   50.45  static void CALLBACK
   50.46 @@ -220,48 +218,19 @@
   50.47  }
   50.48  
   50.49  static int
   50.50 -WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
   50.51 +WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   50.52  {
   50.53      SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   50.54      int valid_datatype = 0;
   50.55      MMRESULT result;
   50.56      WAVEFORMATEX waveformat;
   50.57      UINT devId = WAVE_MAPPER;  /* WAVE_MAPPER == choose system's default */
   50.58 -    char *utf8 = NULL;
   50.59      UINT i;
   50.60  
   50.61 -    if (devname != NULL) {  /* specific device requested? */
   50.62 -        if (iscapture) {
   50.63 -            const UINT devcount = waveInGetNumDevs();
   50.64 -            WAVEINCAPS caps;
   50.65 -            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
   50.66 -                result = waveInGetDevCaps(i, &caps, sizeof (caps));
   50.67 -                if (result != MMSYSERR_NOERROR)
   50.68 -                    continue;
   50.69 -                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
   50.70 -                    continue;
   50.71 -                else if (SDL_strcmp(devname, utf8) == 0)
   50.72 -                    devId = i;
   50.73 -                SDL_free(utf8);
   50.74 -            }
   50.75 -        } else {
   50.76 -            const UINT devcount = waveOutGetNumDevs();
   50.77 -            WAVEOUTCAPS caps;
   50.78 -            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
   50.79 -                result = waveOutGetDevCaps(i, &caps, sizeof (caps));
   50.80 -                if (result != MMSYSERR_NOERROR)
   50.81 -                    continue;
   50.82 -                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
   50.83 -                    continue;
   50.84 -                else if (SDL_strcmp(devname, utf8) == 0)
   50.85 -                    devId = i;
   50.86 -                SDL_free(utf8);
   50.87 -            }
   50.88 -        }
   50.89 -
   50.90 -        if (devId == WAVE_MAPPER) {
   50.91 -            return SDL_SetError("Requested device not found");
   50.92 -        }
   50.93 +    if (handle != NULL) {  /* specific device requested? */
   50.94 +        /* -1 because we increment the original value to avoid NULL. */
   50.95 +        const size_t val = ((size_t) handle) - 1;
   50.96 +        devId = (UINT) val;
   50.97      }
   50.98  
   50.99      /* Initialize all variables that we clean on shutdown */
  50.100 @@ -279,10 +248,6 @@
  50.101      if (this->spec.channels > 2)
  50.102          this->spec.channels = 2;        /* !!! FIXME: is this right? */
  50.103  
  50.104 -    /* Check the buffer size -- minimum of 1/4 second (word aligned) */
  50.105 -    if (this->spec.samples < (this->spec.freq / 4))
  50.106 -        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
  50.107 -
  50.108      while ((!valid_datatype) && (test_format)) {
  50.109          switch (test_format) {
  50.110          case AUDIO_U8:
    51.1 --- a/src/audio/xaudio2/SDL_xaudio2.c	Sat Jan 24 23:58:07 2015 -0400
    51.2 +++ b/src/audio/xaudio2/SDL_xaudio2.c	Mon Apr 06 15:26:37 2015 -0300
    51.3 @@ -126,16 +126,13 @@
    51.4  
    51.5  
    51.6  static void
    51.7 -XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
    51.8 +XAUDIO2_DetectDevices(void)
    51.9  {
   51.10      IXAudio2 *ixa2 = NULL;
   51.11      UINT32 devcount = 0;
   51.12      UINT32 i = 0;
   51.13  
   51.14 -    if (iscapture) {
   51.15 -        SDL_SetError("XAudio2: capture devices unsupported.");
   51.16 -        return;
   51.17 -    } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   51.18 +    if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   51.19          SDL_SetError("XAudio2: XAudio2Create() failed at detection.");
   51.20          return;
   51.21      } else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
   51.22 @@ -149,8 +146,8 @@
   51.23          if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
   51.24              char *str = WIN_StringToUTF8(details.DisplayName);
   51.25              if (str != NULL) {
   51.26 -                addfn(str);
   51.27 -                SDL_free(str);  /* addfn() made a copy of the string. */
   51.28 +                SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i+1));
   51.29 +                SDL_free(str);  /* SDL_AddAudioDevice made a copy of the string. */
   51.30              }
   51.31          }
   51.32      }
   51.33 @@ -169,8 +166,8 @@
   51.34  static void STDMETHODCALLTYPE
   51.35  VoiceCBOnVoiceError(THIS_ void *data, HRESULT Error)
   51.36  {
   51.37 -    /* !!! FIXME: attempt to recover, or mark device disconnected. */
   51.38 -    SDL_assert(0 && "write me!");
   51.39 +    SDL_AudioDevice *this = (SDL_AudioDevice *) data;
   51.40 +    SDL_OpenedAudioDeviceDisconnected(this);
   51.41  }
   51.42  
   51.43  /* no-op callbacks... */
   51.44 @@ -221,7 +218,7 @@
   51.45  
   51.46      if (result != S_OK) {  /* uhoh, panic! */
   51.47          IXAudio2SourceVoice_FlushSourceBuffers(source);
   51.48 -        this->enabled = 0;
   51.49 +        SDL_OpenedAudioDeviceDisconnected(this);
   51.50      }
   51.51  }
   51.52  
   51.53 @@ -289,7 +286,7 @@
   51.54  }
   51.55  
   51.56  static int
   51.57 -XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
   51.58 +XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   51.59  {
   51.60      HRESULT result = S_OK;
   51.61      WAVEFORMATEX waveformat;
   51.62 @@ -315,9 +312,17 @@
   51.63  
   51.64      static IXAudio2VoiceCallback callbacks = { &callbacks_vtable };
   51.65  
   51.66 -    if (iscapture) {
   51.67 -        return SDL_SetError("XAudio2: capture devices unsupported.");
   51.68 -    } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   51.69 +#if defined(SDL_XAUDIO2_WIN8)
   51.70 +    /* !!! FIXME: hook up hotplugging. */
   51.71 +#else
   51.72 +    if (handle != NULL) {  /* specific device requested? */
   51.73 +        /* -1 because we increment the original value to avoid NULL. */
   51.74 +        const size_t val = ((size_t) handle) - 1;
   51.75 +        devId = (UINT32) val;
   51.76 +    }
   51.77 +#endif
   51.78 +
   51.79 +    if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) {
   51.80          return SDL_SetError("XAudio2: XAudio2Create() failed at open.");
   51.81      }
   51.82  
   51.83 @@ -332,37 +337,6 @@
   51.84      ixa2->SetDebugConfiguration(&debugConfig);
   51.85      */
   51.86  
   51.87 -#if ! defined(__WINRT__)
   51.88 -    if (devname != NULL) {
   51.89 -        UINT32 devcount = 0;
   51.90 -        UINT32 i = 0;
   51.91 -
   51.92 -        if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) {
   51.93 -            IXAudio2_Release(ixa2);
   51.94 -            return SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed.");
   51.95 -        }
   51.96 -        for (i = 0; i < devcount; i++) {
   51.97 -            XAUDIO2_DEVICE_DETAILS details;
   51.98 -            if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
   51.99 -                char *str = WIN_StringToUTF8(details.DisplayName);
  51.100 -                if (str != NULL) {
  51.101 -                    const int match = (SDL_strcmp(str, devname) == 0);
  51.102 -                    SDL_free(str);
  51.103 -                    if (match) {
  51.104 -                        devId = i;
  51.105 -                        break;
  51.106 -                    }
  51.107 -                }
  51.108 -            }
  51.109 -        }
  51.110 -
  51.111 -        if (i == devcount) {
  51.112 -            IXAudio2_Release(ixa2);
  51.113 -            return SDL_SetError("XAudio2: Requested device not found.");
  51.114 -        }
  51.115 -    }
  51.116 -#endif
  51.117 -
  51.118      /* Initialize all variables that we clean on shutdown */
  51.119      this->hidden = (struct SDL_PrivateAudioData *)
  51.120          SDL_malloc((sizeof *this->hidden));
  51.121 @@ -529,6 +503,16 @@
  51.122      impl->CloseDevice = XAUDIO2_CloseDevice;
  51.123      impl->Deinitialize = XAUDIO2_Deinitialize;
  51.124  
  51.125 +    /* !!! FIXME: We can apparently use a C++ interface on Windows 8
  51.126 +     * !!! FIXME: (Windows::Devices::Enumeration::DeviceInformation) for device
  51.127 +     * !!! FIXME: detection, but it's not implemented here yet.
  51.128 +     * !!! FIXME:  see http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx
  51.129 +     * !!! FIXME:  for now, force the default device.
  51.130 +     */
  51.131 +#if defined(SDL_XAUDIO2_WIN8) || defined(__WINRT__)
  51.132 +    impl->OnlyHasDefaultOutputDevice = 1;
  51.133 +#endif
  51.134 +
  51.135      return 1;   /* this audio target is available. */
  51.136  #endif
  51.137  }
    52.1 --- a/src/core/android/SDL_android.c	Sat Jan 24 23:58:07 2015 -0400
    52.2 +++ b/src/core/android/SDL_android.c	Mon Apr 06 15:26:37 2015 -0300
    52.3 @@ -32,6 +32,7 @@
    52.4  
    52.5  #include "../../events/SDL_events_c.h"
    52.6  #include "../../video/android/SDL_androidkeyboard.h"
    52.7 +#include "../../video/android/SDL_androidmouse.h"
    52.8  #include "../../video/android/SDL_androidtouch.h"
    52.9  #include "../../video/android/SDL_androidvideo.h"
   52.10  #include "../../video/android/SDL_androidwindow.h"
   52.11 @@ -293,6 +294,14 @@
   52.12      Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
   52.13  }
   52.14  
   52.15 +/* Mouse */
   52.16 +JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse(
   52.17 +                                    JNIEnv* env, jclass jcls,
   52.18 +                                    jint button, jint action, jfloat x, jfloat y)
   52.19 +{
   52.20 +    Android_OnMouse(button, action, x, y);
   52.21 +}
   52.22 +
   52.23  /* Accelerometer */
   52.24  JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel(
   52.25                                      JNIEnv* env, jclass jcls,
   52.26 @@ -548,12 +557,12 @@
   52.27   * Audio support
   52.28   */
   52.29  static jboolean audioBuffer16Bit = JNI_FALSE;
   52.30 -static jboolean audioBufferStereo = JNI_FALSE;
   52.31  static jobject audioBuffer = NULL;
   52.32  static void* audioBufferPinned = NULL;
   52.33  
   52.34  int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
   52.35  {
   52.36 +    jboolean audioBufferStereo;
   52.37      int audioBufferFrames;
   52.38  
   52.39      JNIEnv *env = Android_JNI_GetEnv();
   52.40 @@ -1601,6 +1610,11 @@
   52.41      return s_AndroidExternalFilesPath;
   52.42  }
   52.43  
   52.44 +jclass Android_JNI_GetActivityClass(void)
   52.45 +{
   52.46 +    return mActivityClass;
   52.47 +}
   52.48 +
   52.49  #endif /* __ANDROID__ */
   52.50  
   52.51  /* vi: set ts=4 sw=4 expandtab: */
    53.1 --- a/src/core/android/SDL_android.h	Sat Jan 24 23:58:07 2015 -0400
    53.2 +++ b/src/core/android/SDL_android.h	Mon Apr 06 15:26:37 2015 -0300
    53.3 @@ -78,6 +78,7 @@
    53.4  #include <jni.h>
    53.5  JNIEnv *Android_JNI_GetEnv(void);
    53.6  int Android_JNI_SetupThread(void);
    53.7 +jclass Android_JNI_GetActivityClass(void);
    53.8  
    53.9  /* Generic messages */
   53.10  int Android_JNI_SendMessage(int command, int param);
    54.1 --- a/src/core/linux/SDL_ibus.c	Sat Jan 24 23:58:07 2015 -0400
    54.2 +++ b/src/core/linux/SDL_ibus.c	Mon Apr 06 15:26:37 2015 -0300
    54.3 @@ -462,6 +462,9 @@
    54.4          ibus_addr_file = SDL_strdup(addr_file);
    54.5          
    54.6          addr = IBus_ReadAddressFromFile(addr_file);
    54.7 +        if (!addr) {
    54.8 +            return SDL_FALSE;
    54.9 +        }
   54.10          
   54.11          if (inotify_fd < 0) {
   54.12              inotify_fd = inotify_init();
    55.1 --- a/src/core/linux/SDL_udev.c	Sat Jan 24 23:58:07 2015 -0400
    55.2 +++ b/src/core/linux/SDL_udev.c	Mon Apr 06 15:26:37 2015 -0300
    55.3 @@ -350,17 +350,19 @@
    55.4              devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
    55.5          } else if (test_bit(BTN_TOUCH, bitmask_key)) {
    55.6              ; /* ID_INPUT_TOUCHSCREEN */
    55.7 -        } else if (test_bit(BTN_TRIGGER, bitmask_key) ||
    55.8 -                 test_bit(BTN_A, bitmask_key) ||
    55.9 -                 test_bit(BTN_1, bitmask_key) ||
   55.10 -                 test_bit(ABS_RX, bitmask_abs) ||
   55.11 -                 test_bit(ABS_RY, bitmask_abs) ||
   55.12 -                 test_bit(ABS_RZ, bitmask_abs) ||
   55.13 -                 test_bit(ABS_THROTTLE, bitmask_abs) ||
   55.14 -                 test_bit(ABS_RUDDER, bitmask_abs) ||
   55.15 -                 test_bit(ABS_WHEEL, bitmask_abs) ||
   55.16 -                 test_bit(ABS_GAS, bitmask_abs) ||
   55.17 -                 test_bit(ABS_BRAKE, bitmask_abs)) {
   55.18 +        }
   55.19 +
   55.20 +        if (test_bit(BTN_TRIGGER, bitmask_key) ||
   55.21 +            test_bit(BTN_A, bitmask_key) ||
   55.22 +            test_bit(BTN_1, bitmask_key) ||
   55.23 +            test_bit(ABS_RX, bitmask_abs) ||
   55.24 +            test_bit(ABS_RY, bitmask_abs) ||
   55.25 +            test_bit(ABS_RZ, bitmask_abs) ||
   55.26 +            test_bit(ABS_THROTTLE, bitmask_abs) ||
   55.27 +            test_bit(ABS_RUDDER, bitmask_abs) ||
   55.28 +            test_bit(ABS_WHEEL, bitmask_abs) ||
   55.29 +            test_bit(ABS_GAS, bitmask_abs) ||
   55.30 +            test_bit(ABS_BRAKE, bitmask_abs)) {
   55.31              devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */
   55.32          }
   55.33      }
    56.1 --- a/src/dynapi/SDL_dynapi.h	Sat Jan 24 23:58:07 2015 -0400
    56.2 +++ b/src/dynapi/SDL_dynapi.h	Mon Apr 06 15:26:37 2015 -0300
    56.3 @@ -49,7 +49,10 @@
    56.4  #define SDL_DYNAMIC_API 0
    56.5  #elif defined(__clang_analyzer__)
    56.6  #define SDL_DYNAMIC_API 0  /* Turn off for static analysis, so reports are more clear. */
    56.7 -#else   /* everyone else. */
    56.8 +#endif
    56.9 +
   56.10 +/* everyone else. This is where we turn on the API if nothing forced it off. */
   56.11 +#ifndef SDL_DYNAMIC_API
   56.12  #define SDL_DYNAMIC_API 1
   56.13  #endif
   56.14  
    57.1 --- a/src/dynapi/SDL_dynapi_overrides.h	Sat Jan 24 23:58:07 2015 -0400
    57.2 +++ b/src/dynapi/SDL_dynapi_overrides.h	Mon Apr 06 15:26:37 2015 -0300
    57.3 @@ -591,3 +591,4 @@
    57.4  #define SDL_QueueAudio SDL_QueueAudio_REAL
    57.5  #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL
    57.6  #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL
    57.7 +#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL
    58.1 --- a/src/dynapi/SDL_dynapi_procs.h	Sat Jan 24 23:58:07 2015 -0400
    58.2 +++ b/src/dynapi/SDL_dynapi_procs.h	Mon Apr 06 15:26:37 2015 -0300
    58.3 @@ -623,3 +623,4 @@
    58.4  SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return)
    58.5  SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return)
    58.6  SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),)
    58.7 +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return)
    59.1 --- a/src/events/SDL_events.c	Sat Jan 24 23:58:07 2015 -0400
    59.2 +++ b/src/events/SDL_events.c	Mon Apr 06 15:26:37 2015 -0300
    59.3 @@ -75,12 +75,13 @@
    59.4      SDL_mutex *lock;
    59.5      volatile SDL_bool active;
    59.6      volatile int count;
    59.7 +    volatile int max_events_seen;
    59.8      SDL_EventEntry *head;
    59.9      SDL_EventEntry *tail;
   59.10      SDL_EventEntry *free;
   59.11      SDL_SysWMEntry *wmmsg_used;
   59.12      SDL_SysWMEntry *wmmsg_free;
   59.13 -} SDL_EventQ = { NULL, SDL_TRUE };
   59.14 +} SDL_EventQ = { NULL, SDL_TRUE, 0, 0, NULL, NULL, NULL, NULL, NULL };
   59.15  
   59.16  
   59.17  /* Public functions */
   59.18 @@ -88,6 +89,7 @@
   59.19  void
   59.20  SDL_StopEventLoop(void)
   59.21  {
   59.22 +    const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
   59.23      int i;
   59.24      SDL_EventEntry *entry;
   59.25      SDL_SysWMEntry *wmmsg;
   59.26 @@ -98,6 +100,11 @@
   59.27  
   59.28      SDL_EventQ.active = SDL_FALSE;
   59.29  
   59.30 +    if (report && SDL_atoi(report)) {
   59.31 +        SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
   59.32 +                SDL_EventQ.max_events_seen);
   59.33 +    }
   59.34 +
   59.35      /* Clean out EventQ */
   59.36      for (entry = SDL_EventQ.head; entry; ) {
   59.37          SDL_EventEntry *next = entry->next;
   59.38 @@ -119,7 +126,9 @@
   59.39          SDL_free(wmmsg);
   59.40          wmmsg = next;
   59.41      }
   59.42 +
   59.43      SDL_EventQ.count = 0;
   59.44 +    SDL_EventQ.max_events_seen = 0;
   59.45      SDL_EventQ.head = NULL;
   59.46      SDL_EventQ.tail = NULL;
   59.47      SDL_EventQ.free = NULL;
   59.48 @@ -218,6 +227,10 @@
   59.49      }
   59.50      ++SDL_EventQ.count;
   59.51  
   59.52 +    if (SDL_EventQ.count > SDL_EventQ.max_events_seen) {
   59.53 +        SDL_EventQ.max_events_seen = SDL_EventQ.count;
   59.54 +    }
   59.55 +
   59.56      return 1;
   59.57  }
   59.58  
    60.1 --- a/src/events/SDL_gesture.c	Sat Jan 24 23:58:07 2015 -0400
    60.2 +++ b/src/events/SDL_gesture.c	Mon Apr 06 15:26:37 2015 -0300
    60.3 @@ -24,6 +24,7 @@
    60.4  /* General mouse handling code for SDL */
    60.5  
    60.6  #include "SDL_events.h"
    60.7 +#include "SDL_endian.h"
    60.8  #include "SDL_events_c.h"
    60.9  #include "SDL_gesture_c.h"
   60.10  
   60.11 @@ -114,14 +115,34 @@
   60.12  
   60.13  static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops *dst)
   60.14  {
   60.15 -    if (dst == NULL) return 0;
   60.16 +    if (dst == NULL) {
   60.17 +        return 0;
   60.18 +    }
   60.19  
   60.20      /* No Longer storing the Hash, rehash on load */
   60.21      /* if (SDL_RWops.write(dst, &(templ->hash), sizeof(templ->hash), 1) != 1) return 0; */
   60.22  
   60.23 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN
   60.24      if (SDL_RWwrite(dst, templ->path,
   60.25 -                    sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
   60.26 +                    sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
   60.27          return 0;
   60.28 +    }
   60.29 +#else
   60.30 +    {
   60.31 +        SDL_DollarTemplate copy = *templ;
   60.32 +        SDL_FloatPoint *p = copy.path;
   60.33 +        int i;
   60.34 +        for (i = 0; i < DOLLARNPOINTS; i++, p++) {
   60.35 +            p->x = SDL_SwapFloatLE(p->x);
   60.36 +            p->y = SDL_SwapFloatLE(p->y);
   60.37 +        }
   60.38 +
   60.39 +        if (SDL_RWwrite(dst, copy.path,
   60.40 +                        sizeof(copy.path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) {
   60.41 +            return 0;
   60.42 +        }
   60.43 +    }
   60.44 +#endif
   60.45  
   60.46      return 1;
   60.47  }
   60.48 @@ -184,7 +205,7 @@
   60.49      int index = -1;
   60.50      int i = 0;
   60.51      if (inTouch == NULL) {
   60.52 -        if (SDL_numGestureTouches == 0) return -1;
   60.53 +        if (SDL_numGestureTouches == 0) return SDL_SetError("no gesture touch devices registered");
   60.54          for (i = 0; i < SDL_numGestureTouches; i++) {
   60.55              inTouch = &SDL_gestureTouch[i];
   60.56              index = SDL_AddDollarGesture_one(inTouch, path);
   60.57 @@ -203,17 +224,33 @@
   60.58      SDL_GestureTouch *touch = NULL;
   60.59      if (src == NULL) return 0;
   60.60      if (touchId >= 0) {
   60.61 -        for (i = 0; i < SDL_numGestureTouches; i++)
   60.62 -            if (SDL_gestureTouch[i].id == touchId)
   60.63 +        for (i = 0; i < SDL_numGestureTouches; i++) {
   60.64 +            if (SDL_gestureTouch[i].id == touchId) {
   60.65                  touch = &SDL_gestureTouch[i];
   60.66 -        if (touch == NULL) return -1;
   60.67 +            }
   60.68 +        }
   60.69 +        if (touch == NULL) {
   60.70 +            return SDL_SetError("given touch id not found");
   60.71 +        }
   60.72      }
   60.73  
   60.74      while (1) {
   60.75          SDL_DollarTemplate templ;
   60.76  
   60.77 -        if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) <
   60.78 -           DOLLARNPOINTS) break;
   60.79 +        if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) {
   60.80 +            if (loaded == 0) {
   60.81 +                return SDL_SetError("could not read any dollar gesture from rwops");
   60.82 +            }
   60.83 +            break;
   60.84 +        }
   60.85 +
   60.86 +#if SDL_BYTEORDER != SDL_LIL_ENDIAN
   60.87 +        for (i = 0; i < DOLLARNPOINTS; i++) {
   60.88 +            SDL_FloatPoint *p = &templ.path[i];
   60.89 +            p->x = SDL_SwapFloatLE(p->x);
   60.90 +            p->y = SDL_SwapFloatLE(p->y);
   60.91 +        }
   60.92 +#endif
   60.93  
   60.94          if (touchId >= 0) {
   60.95              /* printf("Adding loaded gesture to 1 touch\n"); */
    61.1 --- a/src/events/SDL_mouse.c	Sat Jan 24 23:58:07 2015 -0400
    61.2 +++ b/src/events/SDL_mouse.c	Mon Apr 06 15:26:37 2015 -0300
    61.3 @@ -293,9 +293,14 @@
    61.4          event.motion.yrel = yrel;
    61.5          posted = (SDL_PushEvent(&event) > 0);
    61.6      }
    61.7 -    /* Use unclamped values if we're getting events outside the window */
    61.8 -    mouse->last_x = x;
    61.9 -    mouse->last_y = y;
   61.10 +    if (relative) {
   61.11 +        mouse->last_x = mouse->x;
   61.12 +        mouse->last_y = mouse->y;
   61.13 +    } else {
   61.14 +        /* Use unclamped values if we're getting events outside the window */
   61.15 +        mouse->last_x = x;
   61.16 +        mouse->last_y = y;
   61.17 +    }
   61.18      return posted;
   61.19  }
   61.20  
   61.21 @@ -303,10 +308,11 @@
   61.22  {
   61.23      if (button >= mouse->num_clickstates) {
   61.24          int i, count = button + 1;
   61.25 -        mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
   61.26 -        if (!mouse->clickstate) {
   61.27 +        SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate));
   61.28 +        if (!clickstate) {
   61.29              return NULL;
   61.30          }
   61.31 +        mouse->clickstate = clickstate;
   61.32  
   61.33          for (i = mouse->num_clickstates; i < count; ++i) {
   61.34              SDL_zero(mouse->clickstate[i]);
    62.1 --- a/src/events/SDL_quit.c	Sat Jan 24 23:58:07 2015 -0400
    62.2 +++ b/src/events/SDL_quit.c	Mon Apr 06 15:26:37 2015 -0300
    62.3 @@ -19,6 +19,7 @@
    62.4    3. This notice may not be removed or altered from any source distribution.
    62.5  */
    62.6  #include "../SDL_internal.h"
    62.7 +#include "SDL_hints.h"
    62.8  
    62.9  /* General quit handling code for SDL */
   62.10  
   62.11 @@ -30,6 +31,8 @@
   62.12  #include "SDL_events_c.h"
   62.13  
   62.14  
   62.15 +static SDL_bool disable_signals = SDL_FALSE;
   62.16 +
   62.17  #ifdef HAVE_SIGNAL_H
   62.18  static void
   62.19  SDL_HandleSIG(int sig)
   62.20 @@ -43,8 +46,8 @@
   62.21  #endif /* HAVE_SIGNAL_H */
   62.22  
   62.23  /* Public functions */
   62.24 -int
   62.25 -SDL_QuitInit(void)
   62.26 +static int
   62.27 +SDL_QuitInit_Internal(void)
   62.28  {
   62.29  #ifdef HAVE_SIGACTION
   62.30      struct sigaction action;
   62.31 @@ -80,11 +83,22 @@
   62.32  #endif /* HAVE_SIGNAL_H */
   62.33  
   62.34      /* That's it! */
   62.35 -    return (0);
   62.36 +    return 0;
   62.37  }
   62.38  
   62.39 -void
   62.40 -SDL_QuitQuit(void)
   62.41 +int
   62.42 +SDL_QuitInit(void)
   62.43 +{
   62.44 +    const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS);
   62.45 +    disable_signals = hint && (SDL_atoi(hint) == 1);
   62.46 +    if (!disable_signals) {
   62.47 +        return SDL_QuitInit_Internal();
   62.48 +    }
   62.49 +    return 0;
   62.50 +}
   62.51 +
   62.52 +static void
   62.53 +SDL_QuitQuit_Internal(void)
   62.54  {
   62.55  #ifdef HAVE_SIGACTION
   62.56      struct sigaction action;
   62.57 @@ -110,6 +124,14 @@
   62.58  #endif /* HAVE_SIGNAL_H */
   62.59  }
   62.60  
   62.61 +void
   62.62 +SDL_QuitQuit(void)
   62.63 +{
   62.64 +    if (!disable_signals) {
   62.65 +        SDL_QuitQuit_Internal();
   62.66 +    }
   62.67 +}
   62.68 +
   62.69  /* This function returns 1 if it's okay to close the application window */
   62.70  int
   62.71  SDL_SendQuit(void)
    63.1 --- a/src/filesystem/nacl/SDL_sysfilesystem.c	Sat Jan 24 23:58:07 2015 -0400
    63.2 +++ b/src/filesystem/nacl/SDL_sysfilesystem.c	Mon Apr 06 15:26:37 2015 -0300
    63.3 @@ -38,4 +38,5 @@
    63.4      return NULL;
    63.5  }
    63.6  
    63.7 -#endif /* __NACL__ */
    63.8 \ No newline at end of file
    63.9 +#endif /* SDL_FILESYSTEM_NACL */
   63.10 +
    64.1 --- a/src/haptic/linux/SDL_syshaptic.c	Sat Jan 24 23:58:07 2015 -0400
    64.2 +++ b/src/haptic/linux/SDL_syshaptic.c	Mon Apr 06 15:26:37 2015 -0300
    64.3 @@ -288,8 +288,7 @@
    64.4      }
    64.5  
    64.6      item->fname = SDL_strdup(path);
    64.7 -    if ( (item->fname == NULL) ) {
    64.8 -        SDL_free(item->fname);
    64.9 +    if (item->fname == NULL) {
   64.10          SDL_free(item);
   64.11          return -1;
   64.12      }
    65.1 --- a/src/joystick/SDL_gamecontrollerdb.h	Sat Jan 24 23:58:07 2015 -0400
    65.2 +++ b/src/joystick/SDL_gamecontrollerdb.h	Mon Apr 06 15:26:37 2015 -0300
    65.3 @@ -63,6 +63,8 @@
    65.4      "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
    65.5      "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
    65.6      "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
    65.7 +    "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
    65.8 +    "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
    65.9      "050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
   65.10      "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
   65.11      "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
   65.12 @@ -73,12 +75,13 @@
   65.13      "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
   65.14      "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
   65.15      "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
   65.16 +    "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
   65.17  #endif
   65.18  #if defined(__ANDROID__)
   65.19      "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
   65.20  #endif
   65.21  #if defined(SDL_JOYSTICK_EMSCRIPTEN)
   65.22 -    "emscripten,Standard Gamepad,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,back:b8,start:b9,leftstick:b10,rightstick:b11,dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,guide:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,",
   65.23 +    "emscripten,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
   65.24  #endif
   65.25      NULL
   65.26  };
    66.1 --- a/src/joystick/SDL_joystick.c	Sat Jan 24 23:58:07 2015 -0400
    66.2 +++ b/src/joystick/SDL_joystick.c	Mon Apr 06 15:26:37 2015 -0300
    66.3 @@ -206,10 +206,6 @@
    66.4          valid = 1;
    66.5      }
    66.6  
    66.7 -    if (joystick && joystick->closed) {
    66.8 -        valid = 0;
    66.9 -    }
   66.10 -
   66.11      return valid;
   66.12  }
   66.13  
   66.14 @@ -412,6 +408,7 @@
   66.15      }
   66.16  
   66.17      SDL_SYS_JoystickClose(joystick);
   66.18 +    joystick->hwdata = NULL;
   66.19  
   66.20      joysticklist = SDL_joysticks;
   66.21      joysticklistprev = NULL;
   66.22 @@ -668,7 +665,7 @@
   66.23  
   66.24          SDL_SYS_JoystickUpdate(joystick);
   66.25  
   66.26 -        if (joystick->closed && joystick->uncentered) {
   66.27 +        if (joystick->force_recentering) {
   66.28              int i;
   66.29  
   66.30              /* Tell the app that everything is centered/unpressed...  */
   66.31 @@ -681,7 +678,7 @@
   66.32              for (i = 0; i < joystick->nhats; i++)
   66.33                  SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED);
   66.34  
   66.35 -            joystick->uncentered = SDL_FALSE;
   66.36 +            joystick->force_recentering = SDL_FALSE;
   66.37          }
   66.38  
   66.39          SDL_updating_joystick = NULL;
    67.1 --- a/src/joystick/SDL_sysjoystick.h	Sat Jan 24 23:58:07 2015 -0400
    67.2 +++ b/src/joystick/SDL_sysjoystick.h	Mon Apr 06 15:26:37 2015 -0300
    67.3 @@ -53,8 +53,7 @@
    67.4  
    67.5      int ref_count;              /* Reference count for multiple opens */
    67.6  
    67.7 -    SDL_bool closed;            /* SDL_TRUE if this device is no longer valid */
    67.8 -    SDL_bool uncentered;        /* SDL_TRUE if this device needs to have its state reset to 0 */
    67.9 +    SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
   67.10      struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
   67.11  };
   67.12  
   67.13 @@ -78,14 +77,14 @@
   67.14  extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index);
   67.15  
   67.16  /* Function to open a joystick for use.
   67.17 -   The joystick to open is specified by the index field of the joystick.
   67.18 +   The joystick to open is specified by the device index.
   67.19     This should fill the nbuttons and naxes fields of the joystick structure.
   67.20     It returns 0, or -1 if there is an error.
   67.21   */
   67.22  extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index);
   67.23  
   67.24  /* Function to query if the joystick is currently attached
   67.25 - *   It returns 1 if attached, 0 otherwise.
   67.26 + * It returns SDL_TRUE if attached, SDL_FALSE otherwise.
   67.27   */
   67.28  extern SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick);
   67.29  
    68.1 --- a/src/joystick/android/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    68.2 +++ b/src/joystick/android/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    68.3 @@ -467,7 +467,7 @@
    68.4  }
    68.5  
    68.6  /* Function to open a joystick for use.
    68.7 -   The joystick to open is specified by the index field of the joystick.
    68.8 +   The joystick to open is specified by the device index.
    68.9     This should fill the nbuttons and naxes fields of the joystick structure.
   68.10     It returns 0, or -1 if there is an error.
   68.11   */
   68.12 @@ -498,7 +498,7 @@
   68.13  /* Function to determine is this joystick is attached to the system right now */
   68.14  SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   68.15  {
   68.16 -    return !joystick->closed && (joystick->hwdata != NULL);
   68.17 +    return joystick->hwdata != NULL;
   68.18  }
   68.19  
   68.20  void
   68.21 @@ -529,11 +529,6 @@
   68.22  void
   68.23  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   68.24  {
   68.25 -    if (joystick->hwdata) {
   68.26 -        ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
   68.27 -        joystick->hwdata = NULL;
   68.28 -    }
   68.29 -    joystick->closed = 1;
   68.30  }
   68.31  
   68.32  /* Function to perform any system-specific joystick related cleanup */
    69.1 --- a/src/joystick/android/SDL_sysjoystick_c.h	Sat Jan 24 23:58:07 2015 -0400
    69.2 +++ b/src/joystick/android/SDL_sysjoystick_c.h	Mon Apr 06 15:26:37 2015 -0300
    69.3 @@ -19,7 +19,7 @@
    69.4   3. This notice may not be removed or altered from any source distribution.
    69.5   */
    69.6  
    69.7 -#include "SDL_config.h"
    69.8 +#include "../../SDL_internal.h"
    69.9  
   69.10  #ifdef SDL_JOYSTICK_ANDROID
   69.11  #include "../SDL_sysjoystick.h"
    70.1 --- a/src/joystick/bsd/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    70.2 +++ b/src/joystick/bsd/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    70.3 @@ -558,8 +558,6 @@
    70.4      close(joy->hwdata->fd);
    70.5      SDL_free(joy->hwdata->path);
    70.6      SDL_free(joy->hwdata);
    70.7 -
    70.8 -    return;
    70.9  }
   70.10  
   70.11  void
    71.1 --- a/src/joystick/darwin/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    71.2 +++ b/src/joystick/darwin/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    71.3 @@ -138,7 +138,7 @@
    71.4  JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
    71.5  {
    71.6      recDevice *device = (recDevice *) ctx;
    71.7 -    device->removed = 1;
    71.8 +    device->removed = SDL_TRUE;
    71.9      device->deviceRef = NULL; // deviceRef was invalidated due to the remove
   71.10  #if SDL_HAPTIC_IOKIT
   71.11      MacHaptic_MaybeRemoveDevice(device->ffservice);
   71.12 @@ -412,12 +412,12 @@
   71.13      /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */
   71.14      if (IOHIDDeviceGetService != NULL) {  /* weak reference: available in 10.6 and later. */
   71.15          const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
   71.16 +#if SDL_HAPTIC_IOKIT
   71.17          if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) {
   71.18              device->ffservice = ioservice;
   71.19 -#if SDL_HAPTIC_IOKIT
   71.20              MacHaptic_MaybeAddDevice(ioservice);
   71.21 +        }
   71.22  #endif
   71.23 -        }
   71.24      }
   71.25  
   71.26      device->send_open_event = 1;
   71.27 @@ -446,9 +446,9 @@
   71.28          return SDL_FALSE;
   71.29      }
   71.30  
   71.31 +    IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
   71.32      IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL);
   71.33      IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE);
   71.34 -    IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray);
   71.35  
   71.36      while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
   71.37          /* no-op. Callback fires once per existing device. */
   71.38 @@ -560,10 +560,6 @@
   71.39  void
   71.40  SDL_SYS_JoystickDetect()
   71.41  {
   71.42 -    while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
   71.43 -        /* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
   71.44 -    }
   71.45 -
   71.46      if (s_bDeviceAdded || s_bDeviceRemoved) {
   71.47          recDevice *device = gpDeviceList;
   71.48          s_bDeviceAdded = SDL_FALSE;
   71.49 @@ -613,6 +609,12 @@
   71.50              }
   71.51          }
   71.52      }
   71.53 +
   71.54 +	// run this after the checks above so we don't set device->removed and delete the device before
   71.55 +	// SDL_SYS_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device
   71.56 +	while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) {
   71.57 +		/* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */
   71.58 +	}
   71.59  }
   71.60  
   71.61  /* Function to get the device-dependent name of a joystick */
   71.62 @@ -644,7 +646,7 @@
   71.63  }
   71.64  
   71.65  /* Function to open a joystick for use.
   71.66 - * The joystick to open is specified by the index field of the joystick.
   71.67 + * The joystick to open is specified by the device index.
   71.68   * This should fill the nbuttons and naxes fields of the joystick structure.
   71.69   * It returns 0, or -1 if there is an error.
   71.70   */
   71.71 @@ -670,21 +672,12 @@
   71.72  }
   71.73  
   71.74  /* Function to query if the joystick is currently attached
   71.75 - *   It returns 1 if attached, 0 otherwise.
   71.76 + * It returns SDL_TRUE if attached, SDL_FALSE otherwise.
   71.77   */
   71.78  SDL_bool
   71.79  SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
   71.80  {
   71.81 -    recDevice *device = gpDeviceList;
   71.82 -
   71.83 -    while (device) {
   71.84 -        if (joystick->instance_id == device->instance_id) {
   71.85 -            return SDL_TRUE;
   71.86 -        }
   71.87 -        device = device->pNext;
   71.88 -    }
   71.89 -
   71.90 -    return SDL_FALSE;
   71.91 +    return joystick->hwdata != NULL;
   71.92  }
   71.93  
   71.94  /* Function to update the state of a joystick - called as a device poll.
   71.95 @@ -705,9 +698,10 @@
   71.96      }
   71.97  
   71.98      if (device->removed) {      /* device was unplugged; ignore it. */
   71.99 -        joystick->closed = 1;
  71.100 -        joystick->uncentered = 1;
  71.101 -        joystick->hwdata = NULL;
  71.102 +        if (joystick->hwdata) {
  71.103 +            joystick->force_recentering = SDL_TRUE;
  71.104 +            joystick->hwdata = NULL;
  71.105 +        }
  71.106          return;
  71.107      }
  71.108  
  71.109 @@ -795,7 +789,6 @@
  71.110  void
  71.111  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  71.112  {
  71.113 -    joystick->closed = 1;
  71.114  }
  71.115  
  71.116  /* Function to perform any system-specific joystick related cleanup */
    72.1 --- a/src/joystick/darwin/SDL_sysjoystick_c.h	Sat Jan 24 23:58:07 2015 -0400
    72.2 +++ b/src/joystick/darwin/SDL_sysjoystick_c.h	Mon Apr 06 15:26:37 2015 -0300
    72.3 @@ -58,8 +58,7 @@
    72.4      recElement *firstButton;
    72.5      recElement *firstHat;
    72.6  
    72.7 -    int removed;
    72.8 -    int uncentered;
    72.9 +    SDL_bool removed;
   72.10  
   72.11      int instance_id;
   72.12      SDL_JoystickGUID guid;
    73.1 --- a/src/joystick/dummy/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    73.2 +++ b/src/joystick/dummy/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    73.3 @@ -34,7 +34,7 @@
    73.4  int
    73.5  SDL_SYS_JoystickInit(void)
    73.6  {
    73.7 -    return (0);
    73.8 +    return 0;
    73.9  }
   73.10  
   73.11  int SDL_SYS_NumJoysticks()
   73.12 @@ -61,7 +61,7 @@
   73.13  }
   73.14  
   73.15  /* Function to open a joystick for use.
   73.16 -   The joystick to open is specified by the index field of the joystick.
   73.17 +   The joystick to open is specified by the device index.
   73.18     This should fill the nbuttons and naxes fields of the joystick structure.
   73.19     It returns 0, or -1 if there is an error.
   73.20   */
   73.21 @@ -85,21 +85,18 @@
   73.22  void
   73.23  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   73.24  {
   73.25 -    return;
   73.26  }
   73.27  
   73.28  /* Function to close a joystick after use */
   73.29  void
   73.30  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   73.31  {
   73.32 -    return;
   73.33  }
   73.34  
   73.35  /* Function to perform any system-specific joystick related cleanup */
   73.36  void
   73.37  SDL_SYS_JoystickQuit(void)
   73.38  {
   73.39 -    return;
   73.40  }
   73.41  
   73.42  SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index )
    74.1 --- a/src/joystick/emscripten/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    74.2 +++ b/src/joystick/emscripten/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    74.3 @@ -46,7 +46,7 @@
    74.4  static int numjoysticks = 0;
    74.5  static int instance_counter = 0;
    74.6  
    74.7 -int
    74.8 +EM_BOOL
    74.9  Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
   74.10  {
   74.11      int i;
   74.12 @@ -105,12 +105,14 @@
   74.13      }
   74.14  
   74.15      ++numjoysticks;
   74.16 -    SDL_Log("%d",numjoysticks);
   74.17 +#ifdef DEBUG_JOYSTICK
   74.18 +    SDL_Log("Number of joysticks is %d", numjoysticks);
   74.19 +#endif
   74.20  #if !SDL_EVENTS_DISABLED
   74.21      event.type = SDL_JOYDEVICEADDED;
   74.22  
   74.23      if (SDL_GetEventState(event.type) == SDL_ENABLE) {
   74.24 -        event.jdevice.which = item->device_instance - 1;
   74.25 +        event.jdevice.which = numjoysticks - 1;
   74.26          if ( (SDL_EventOK == NULL) ||
   74.27               (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
   74.28              SDL_PushEvent(&event);
   74.29 @@ -118,12 +120,14 @@
   74.30      }
   74.31  #endif /* !SDL_EVENTS_DISABLED */
   74.32  
   74.33 +#ifdef DEBUG_JOYSTICK
   74.34      SDL_Log("Added joystick with index %d", item->index);
   74.35 +#endif
   74.36  
   74.37      return 1;
   74.38  }
   74.39  
   74.40 -int
   74.41 +EM_BOOL
   74.42  Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData)
   74.43  {
   74.44      SDL_joylist_item *item = SDL_joylist;
   74.45 @@ -144,7 +148,6 @@
   74.46          return 1;
   74.47      }
   74.48  
   74.49 -    const int retval = item->device_instance;
   74.50      if (item->joystick) {
   74.51          item->joystick->hwdata = NULL;
   74.52      }
   74.53 @@ -174,7 +177,9 @@
   74.54      }
   74.55  #endif /* !SDL_EVENTS_DISABLED */
   74.56  
   74.57 -    SDL_Log("Removed joystick with index %d", retval);
   74.58 +#ifdef DEBUG_JOYSTICK
   74.59 +    SDL_Log("Removed joystick with id %d", item->device_instance);
   74.60 +#endif
   74.61      SDL_free(item->name);
   74.62      SDL_free(item->mapping);
   74.63      SDL_free(item);
   74.64 @@ -215,6 +220,7 @@
   74.65                                                        Emscripten_JoyStickConnected);
   74.66  
   74.67      if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
   74.68 +        SDL_SYS_JoystickQuit();
   74.69          return -1;
   74.70      }
   74.71  
   74.72 @@ -222,12 +228,28 @@
   74.73                                                           0,
   74.74                                                           Emscripten_JoyStickDisconnected);
   74.75      if(retval != EMSCRIPTEN_RESULT_SUCCESS) {
   74.76 +        SDL_SYS_JoystickQuit();
   74.77          return -1;
   74.78      }
   74.79  
   74.80      return 0;
   74.81  }
   74.82  
   74.83 +/* Returns item matching given SDL device index. */
   74.84 +static SDL_joylist_item *
   74.85 +JoystickByDeviceIndex(int device_index)
   74.86 +{
   74.87 +    SDL_joylist_item *item = SDL_joylist;
   74.88 +
   74.89 +    while (0 < device_index) {
   74.90 +        --device_index;
   74.91 +        item = item->next;
   74.92 +    }
   74.93 +
   74.94 +    return item;
   74.95 +}
   74.96 +
   74.97 +/* Returns item matching given HTML gamepad index. */
   74.98  static SDL_joylist_item *
   74.99  JoystickByIndex(int index)
  74.100  {
  74.101 @@ -256,46 +278,28 @@
  74.102  {
  74.103  }
  74.104  
  74.105 -// we need to poll to see if the gamepad state has changed
  74.106 -SDL_bool SDL_SYS_JoystickNeedsPolling()
  74.107 -{
  74.108 -    return SDL_TRUE;
  74.109 -}
  74.110 -
  74.111  /* Function to get the device-dependent name of a joystick */
  74.112  const char *
  74.113 -SDL_SYS_JoystickNameForDeviceIndex(int index)
  74.114 +SDL_SYS_JoystickNameForDeviceIndex(int device_index)
  74.115  {
  74.116 -    SDL_joylist_item *item = JoystickByIndex(index);
  74.117 -    if (item == NULL) {
  74.118 -        SDL_SetError("Joystick with index %d not found", index);
  74.119 -        return NULL;
  74.120 -    }
  74.121 -
  74.122 -    return item->name;
  74.123 +    return JoystickByDeviceIndex(device_index)->name;
  74.124  }
  74.125  
  74.126  /* Function to perform the mapping from device index to the instance id for this index */
  74.127 -SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index)
  74.128 +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
  74.129  {
  74.130 -    SDL_joylist_item *item = JoystickByIndex(index);
  74.131 -    if (item == NULL) {
  74.132 -        SDL_SetError("Joystick with index %d not found", index);
  74.133 -        return 0;
  74.134 -    }
  74.135 -
  74.136 -    return item->device_instance;
  74.137 +    return JoystickByDeviceIndex(device_index)->device_instance;
  74.138  }
  74.139  
  74.140  /* Function to open a joystick for use.
  74.141 -   The joystick to open is specified by the index field of the joystick.
  74.142 +   The joystick to open is specified by the device index.
  74.143     This should fill the nbuttons and naxes fields of the joystick structure.
  74.144     It returns 0, or -1 if there is an error.
  74.145   */
  74.146  int
  74.147 -SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index)
  74.148 +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
  74.149  {
  74.150 -    SDL_joylist_item *item = JoystickByIndex(index);
  74.151 +    SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
  74.152  
  74.153      if (item == NULL ) {
  74.154          return SDL_SetError("No such device");
  74.155 @@ -322,7 +326,7 @@
  74.156  /* Function to determine is this joystick is attached to the system right now */
  74.157  SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
  74.158  {
  74.159 -    return !joystick->closed && (joystick->hwdata != NULL);
  74.160 +    return joystick->hwdata != NULL;
  74.161  }
  74.162  
  74.163  /* Function to update the state of a joystick - called as a device poll.
  74.164 @@ -334,10 +338,10 @@
  74.165  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
  74.166  {
  74.167      EmscriptenGamepadEvent gamepadState;
  74.168 -    SDL_joylist_item *item = SDL_joylist;
  74.169 +    SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
  74.170      int i, result, buttonState;
  74.171  
  74.172 -    while (item != NULL) {
  74.173 +    if (item) {
  74.174          result = emscripten_get_gamepad_status(item->index, &gamepadState);
  74.175          if( result == EMSCRIPTEN_RESULT_SUCCESS) {
  74.176              if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) {
  74.177 @@ -367,7 +371,6 @@
  74.178                  }
  74.179              }
  74.180          }
  74.181 -        item = item->next;
  74.182      }
  74.183  }
  74.184  
  74.185 @@ -375,11 +378,6 @@
  74.186  void
  74.187  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
  74.188  {
  74.189 -    if (joystick->hwdata) {
  74.190 -        ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL;
  74.191 -        joystick->hwdata = NULL;
  74.192 -    }
  74.193 -    joystick->closed = 1;
  74.194  }
  74.195  
  74.196  /* Function to perform any system-specific joystick related cleanup */
  74.197 @@ -400,20 +398,24 @@
  74.198  
  74.199      numjoysticks = 0;
  74.200      instance_counter = 0;
  74.201 +
  74.202 +    emscripten_set_gamepadconnected_callback(NULL, 0, NULL);
  74.203 +    emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL);
  74.204  }
  74.205  
  74.206 -SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index)
  74.207 +SDL_JoystickGUID
  74.208 +SDL_SYS_JoystickGetDeviceGUID(int device_index)
  74.209  {
  74.210      SDL_JoystickGUID guid;
  74.211      /* the GUID is just the first 16 chars of the name for now */
  74.212 -    const char *name = SDL_SYS_JoystickNameForDeviceIndex(index);
  74.213 +    const char *name = SDL_SYS_JoystickNameForDeviceIndex(device_index);
  74.214      SDL_zero(guid);
  74.215      SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name)));
  74.216      return guid;
  74.217  }
  74.218  
  74.219 -
  74.220 -SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
  74.221 +SDL_JoystickGUID
  74.222 +SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
  74.223  {
  74.224      SDL_JoystickGUID guid;
  74.225      /* the GUID is just the first 16 chars of the name for now */
    75.1 --- a/src/joystick/emscripten/SDL_sysjoystick_c.h	Sat Jan 24 23:58:07 2015 -0400
    75.2 +++ b/src/joystick/emscripten/SDL_sysjoystick_c.h	Mon Apr 06 15:26:37 2015 -0300
    75.3 @@ -19,7 +19,7 @@
    75.4   3. This notice may not be removed or altered from any source distribution.
    75.5   */
    75.6  
    75.7 -#include "SDL_config.h"
    75.8 +#include "../../SDL_internal.h"
    75.9  
   75.10  #ifdef SDL_JOYSTICK_EMSCRIPTEN
   75.11  #include "../SDL_sysjoystick.h"
    76.1 --- a/src/joystick/haiku/SDL_haikujoystick.cc	Sat Jan 24 23:58:07 2015 -0400
    76.2 +++ b/src/joystick/haiku/SDL_haikujoystick.cc	Mon Apr 06 15:26:37 2015 -0300
    76.3 @@ -106,7 +106,7 @@
    76.4      }
    76.5  
    76.6  /* Function to open a joystick for use.
    76.7 -   The joystick to open is specified by the index field of the joystick.
    76.8 +   The joystick to open is specified by the device index.
    76.9     This should fill the nbuttons and naxes fields of the joystick structure.
   76.10     It returns 0, or -1 if there is an error.
   76.11   */
   76.12 @@ -228,7 +228,6 @@
   76.13              SDL_free(joystick->hwdata->new_hats);
   76.14              SDL_free(joystick->hwdata->new_axes);
   76.15              SDL_free(joystick->hwdata);
   76.16 -            joystick->hwdata = NULL;
   76.17          }
   76.18      }
   76.19  
    77.1 --- a/src/joystick/iphoneos/SDL_sysjoystick.m	Sat Jan 24 23:58:07 2015 -0400
    77.2 +++ b/src/joystick/iphoneos/SDL_sysjoystick.m	Mon Apr 06 15:26:37 2015 -0300
    77.3 @@ -77,7 +77,7 @@
    77.4  }
    77.5  
    77.6  /* Function to open a joystick for use.
    77.7 -   The joystick to open is specified by the index field of the joystick.
    77.8 +   The joystick to open is specified by the device index.
    77.9     This should fill the nbuttons and naxes fields of the joystick structure.
   77.10     It returns 0, or -1 if there is an error.
   77.11   */
   77.12 @@ -167,7 +167,6 @@
   77.13      @autoreleasepool {
   77.14          [motionManager stopAccelerometerUpdates];
   77.15      }
   77.16 -    joystick->closed = 1;
   77.17  }
   77.18  
   77.19  /* Function to perform any system-specific joystick related cleanup */
    78.1 --- a/src/joystick/linux/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    78.2 +++ b/src/joystick/linux/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    78.3 @@ -142,13 +142,15 @@
    78.4  #if SDL_USE_LIBUDEV
    78.5  void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
    78.6  {
    78.7 -    if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
    78.8 +    if (devpath == NULL) {
    78.9          return;
   78.10      }
   78.11 -    
   78.12 -    switch( udev_type )
   78.13 -    {
   78.14 +
   78.15 +    switch (udev_type) {
   78.16          case SDL_UDEV_DEVICEADDED:
   78.17 +            if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) {
   78.18 +                return;
   78.19 +            }
   78.20              MaybeAddDevice(devpath);
   78.21              break;
   78.22              
   78.23 @@ -335,13 +337,12 @@
   78.24  static int
   78.25  JoystickInitWithUdev(void)
   78.26  {
   78.27 -
   78.28      if (SDL_UDEV_Init() < 0) {
   78.29          return SDL_SetError("Could not initialize UDEV");
   78.30      }
   78.31  
   78.32      /* Set up the udev callback */
   78.33 -    if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
   78.34 +    if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) {
   78.35          SDL_UDEV_Quit();
   78.36          return SDL_SetError("Could not set up joystick <-> udev callback");
   78.37      }
   78.38 @@ -565,7 +566,7 @@
   78.39  
   78.40  
   78.41  /* Function to open a joystick for use.
   78.42 -   The joystick to open is specified by the index field of the joystick.
   78.43 +   The joystick to open is specified by the device index.
   78.44     This should fill the nbuttons and naxes fields of the joystick structure.
   78.45     It returns 0, or -1 if there is an error.
   78.46   */
   78.47 @@ -623,7 +624,7 @@
   78.48  /* Function to determine is this joystick is attached to the system right now */
   78.49  SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
   78.50  {
   78.51 -    return !joystick->closed && (joystick->hwdata->item != NULL);
   78.52 +    return joystick->hwdata->item != NULL;
   78.53  }
   78.54  
   78.55  static SDL_INLINE void
   78.56 @@ -840,9 +841,7 @@
   78.57          SDL_free(joystick->hwdata->balls);
   78.58          SDL_free(joystick->hwdata->fname);
   78.59          SDL_free(joystick->hwdata);
   78.60 -        joystick->hwdata = NULL;
   78.61      }
   78.62 -    joystick->closed = 1;
   78.63  }
   78.64  
   78.65  /* Function to perform any system-specific joystick related cleanup */
    79.1 --- a/src/joystick/psp/SDL_sysjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    79.2 +++ b/src/joystick/psp/SDL_sysjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    79.3 @@ -18,6 +18,9 @@
    79.4       misrepresented as being the original software.
    79.5    3. This notice may not be removed or altered from any source distribution.
    79.6  */
    79.7 +#include "../../SDL_internal.h"
    79.8 +
    79.9 +#if SDL_JOYSTICK_PSP
   79.10  
   79.11  /* This is the PSP implementation of the SDL joystick API */
   79.12  #include <pspctrl.h>
   79.13 @@ -161,7 +164,7 @@
   79.14  }
   79.15  
   79.16  /* Function to open a joystick for use.
   79.17 -   The joystick to open is specified by the index field of the joystick.
   79.18 +   The joystick to open is specified by the device index.
   79.19     This should fill the nbuttons and naxes fields of the joystick structure.
   79.20     It returns 0, or -1 if there is an error.
   79.21   */
   79.22 @@ -179,12 +182,12 @@
   79.23  {
   79.24      return SDL_TRUE;
   79.25  }
   79.26 +
   79.27  /* Function to update the state of a joystick - called as a device poll.
   79.28   * This function shouldn't update the joystick structure directly,
   79.29   * but instead should call SDL_PrivateJoystick*() to deliver events
   79.30   * and update joystick device state.
   79.31   */
   79.32 -
   79.33  void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
   79.34  {
   79.35      int i;
   79.36 @@ -230,7 +233,6 @@
   79.37  /* Function to close a joystick after use */
   79.38  void SDL_SYS_JoystickClose(SDL_Joystick *joystick)
   79.39  {
   79.40 -    /* Do nothing. */
   79.41  }
   79.42  
   79.43  /* Function to perform any system-specific joystick related cleanup */
   79.44 @@ -262,5 +264,7 @@
   79.45      return guid;
   79.46  }
   79.47  
   79.48 +#endif /* SDL_JOYSTICK_PSP */
   79.49 +
   79.50  /* vim: ts=4 sw=4
   79.51   */
    80.1 --- a/src/joystick/windows/SDL_mmjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    80.2 +++ b/src/joystick/windows/SDL_mmjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    80.3 @@ -210,7 +210,7 @@
    80.4  }
    80.5  
    80.6  /* Function to open a joystick for use.
    80.7 -   The joystick to open is specified by the index field of the joystick.
    80.8 +   The joystick to open is specified by the device index.
    80.9     This should fill the nbuttons and naxes fields of the joystick structure.
   80.10     It returns 0, or -1 if there is an error.
   80.11   */
   80.12 @@ -383,9 +383,7 @@
   80.13  void
   80.14  SDL_SYS_JoystickClose(SDL_Joystick * joystick)
   80.15  {
   80.16 -    /* free system specific hardware data */
   80.17      SDL_free(joystick->hwdata);
   80.18 -    joystick->hwdata = NULL;
   80.19  }
   80.20  
   80.21  /* Function to perform any system-specific joystick related cleanup */
    81.1 --- a/src/joystick/windows/SDL_windowsjoystick.c	Sat Jan 24 23:58:07 2015 -0400
    81.2 +++ b/src/joystick/windows/SDL_windowsjoystick.c	Mon Apr 06 15:26:37 2015 -0300
    81.3 @@ -446,7 +446,7 @@
    81.4  }
    81.5  
    81.6  /* Function to open a joystick for use.
    81.7 -   The joystick to open is specified by the index field of the joystick.
    81.8 +   The joystick to open is specified by the device index.
    81.9     This should fill the nbuttons and naxes fields of the joystick structure.
   81.10     It returns 0, or -1 if there is an error.
   81.11   */
   81.12 @@ -460,7 +460,6 @@
   81.13  
   81.14      /* allocate memory for system specific hardware data */
   81.15      joystick->instance_id = joystickdevice->nInstanceID;
   81.16 -    joystick->closed = SDL_FALSE;
   81.17      joystick->hwdata =
   81.18          (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
   81.19      if (joystick->hwdata == NULL) {
   81.20 @@ -480,13 +479,13 @@
   81.21  SDL_bool 
   81.22  SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
   81.23  {
   81.24 -    return !joystick->closed && !joystick->hwdata->removed;
   81.25 +    return joystick->hwdata && !joystick->hwdata->removed;
   81.26  }
   81.27  
   81.28  void
   81.29  SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
   81.30  {
   81.31 -    if (joystick->closed || !joystick->hwdata) {
   81.32 +    if (!joystick->hwdata || joystick->hwdata->removed) {
   81.33          return;
   81.34      }
   81.35  
   81.36 @@ -497,8 +496,7 @@
   81.37      }
   81.38  
   81.39      if (joystick->hwdata->removed) {
   81.40 -        joystick->closed = SDL_TRUE;
   81.41 -        joystick->uncentered = SDL_TRUE;
   81.42 +        joystick->force_recentering = SDL_TRUE;
   81.43      }
   81.44  }
   81.45  
   81.46 @@ -512,10 +510,7 @@
   81.47          SDL_DINPUT_JoystickClose(joystick);
   81.48      }
   81.49  
   81.50 -    /* free system specific hardware data */
   81.51      SDL_free(joystick->hwdata);
   81.52 -
   81.53 -    joystick->closed = SDL_TRUE;
   81.54  }
   81.55  
   81.56  /* Function to perform any system-specific joystick related cleanup */
    82.1 --- a/src/main/psp/SDL_psp_main.c	Sat Jan 24 23:58:07 2015 -0400
    82.2 +++ b/src/main/psp/SDL_psp_main.c	Mon Apr 06 15:26:37 2015 -0300
    82.3 @@ -1,6 +1,9 @@
    82.4  /*
    82.5      SDL_psp_main.c, placed in the public domain by Sam Lantinga  3/13/14
    82.6  */
    82.7 +#include "SDL_config.h"
    82.8 +
    82.9 +#ifdef __PSP__
   82.10  
   82.11  #include "SDL_main.h"
   82.12  #include <pspkernel.h>
   82.13 @@ -61,3 +64,7 @@
   82.14      (void)SDL_main(argc, argv);
   82.15      return 0;
   82.16  }
   82.17 +
   82.18 +#endif /* __PSP__ */
   82.19 +
   82.20 +/* vi: set ts=4 sw=4 expandtab: */
    83.1 --- a/src/main/windows/SDL_windows_main.c	Sat Jan 24 23:58:07 2015 -0400
    83.2 +++ b/src/main/windows/SDL_windows_main.c	Mon Apr 06 15:26:37 2015 -0300
    83.3 @@ -109,13 +109,16 @@
    83.4  }
    83.5  
    83.6  #if defined(_MSC_VER)
    83.7 -/* The VC++ compiler needs main defined */
    83.8 -#define console_main main
    83.9 +/* The VC++ compiler needs main/wmain defined */
   83.10 +# define console_ansi_main main
   83.11 +# if UNICODE
   83.12 +#  define console_wmain wmain
   83.13 +# endif
   83.14  #endif
   83.15  
   83.16 -/* This is where execution begins [console apps] */
   83.17 -int
   83.18 -console_main(int argc, char *argv[])
   83.19 +/* WinMain, main, and wmain eventually call into here. */
   83.20 +static int
   83.21 +main_utf8(int argc, char *argv[])
   83.22  {
   83.23      SDL_SetMainReady();
   83.24  
   83.25 @@ -123,6 +126,37 @@
   83.26      return SDL_main(argc, argv);
   83.27  }
   83.28  
   83.29 +/* This is where execution begins [console apps, ansi] */
   83.30 +int
   83.31 +console_ansi_main(int argc, char *argv[])
   83.32 +{
   83.33 +    /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
   83.34 +    return main_utf8(argc, argv);
   83.35 +}
   83.36 +
   83.37 +
   83.38 +#if UNICODE
   83.39 +/* This is where execution begins [console apps, unicode] */
   83.40 +int
   83.41 +console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
   83.42 +{
   83.43 +    int retval = 0;
   83.44 +    char **argv = SDL_stack_alloc(char*, argc);
   83.45 +    int i;
   83.46 +
   83.47 +    for (i = 0; i < argc; ++i) {
   83.48 +        argv[i] = WIN_StringToUTF8(wargv[i]);
   83.49 +    }
   83.50 +
   83.51 +    retval = main_utf8(argc, argv);
   83.52 +
   83.53 +    /* !!! FIXME: we are leaking all the elements of argv we allocated. */
   83.54 +    SDL_stack_free(argv);
   83.55 +
   83.56 +    return retval;
   83.57 +}
   83.58 +#endif
   83.59 +
   83.60  /* This is where execution begins [windowed apps] */
   83.61  int WINAPI
   83.62  WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
   83.63 @@ -136,6 +170,7 @@
   83.64  #if UNICODE
   83.65      cmdline = WIN_StringToUTF8(text);
   83.66  #else
   83.67 +    /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
   83.68      cmdline = SDL_strdup(text);
   83.69  #endif
   83.70      if (cmdline == NULL) {
   83.71 @@ -151,7 +186,7 @@
   83.72      ParseCommandLine(cmdline, argv);
   83.73  
   83.74      /* Run the main program */
   83.75 -    console_main(argc, argv);
   83.76 +    main_utf8(argc, argv);
   83.77  
   83.78      SDL_stack_free(argv);
   83.79  
    84.1 --- a/src/render/direct3d11/SDL_render_d3d11.c	Sat Jan 24 23:58:07 2015 -0400
    84.2 +++ b/src/render/direct3d11/SDL_render_d3d11.c	Mon Apr 06 15:26:37 2015 -0300
    84.3 @@ -829,9 +829,24 @@
    84.4      renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    84.5      renderer->driverdata = data;
    84.6  
    84.7 +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
    84.8 +    /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1.
    84.9 +     * Failure to use it seems to either result in:
   84.10 +     *
   84.11 +     *  - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned
   84.12 +     *    off (framerate doesn't get capped), but nothing appears on-screen
   84.13 +     *
   84.14 +     *  - with the D3D11 debug runtime turned ON, vsync gets automatically
   84.15 +     *    turned back on, and the following gets output to the debug console:
   84.16 +     *    
   84.17 +     *    DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ] 
   84.18 +     */
   84.19 +    renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   84.20 +#else
   84.21      if ((flags & SDL_RENDERER_PRESENTVSYNC)) {
   84.22          renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   84.23      }
   84.24 +#endif
   84.25  
   84.26      /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in
   84.27       * order to give init functions access to the underlying window handle:
    85.1 --- a/src/render/opengl/SDL_render_gl.c	Sat Jan 24 23:58:07 2015 -0400
    85.2 +++ b/src/render/opengl/SDL_render_gl.c	Mon Apr 06 15:26:37 2015 -0300
    85.3 @@ -342,9 +342,11 @@
    85.4  
    85.5      if (type == GL_DEBUG_TYPE_ERROR_ARB) {
    85.6          /* Record this error */
    85.7 -        ++data->errors;
    85.8 -        data->error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages));
    85.9 -        if (data->error_messages) {
   85.10 +        int errors = data->errors + 1;
   85.11 +        char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages));
   85.12 +        if (error_messages) {
   85.13 +            data->errors = errors;
   85.14 +            data->error_messages = error_messages;
   85.15              data->error_messages[data->errors-1] = SDL_strdup(message);
   85.16          }
   85.17      }
    86.1 --- a/src/test/SDL_test_common.c	Sat Jan 24 23:58:07 2015 -0400
    86.2 +++ b/src/test/SDL_test_common.c	Mon Apr 06 15:26:37 2015 -0300
    86.3 @@ -1204,10 +1204,10 @@
    86.4                  event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure);
    86.5          break;
    86.6      case SDL_DOLLARGESTURE:
    86.7 -        SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (long long) event->dgesture.gestureId);
    86.8 +        SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
    86.9          break;
   86.10      case SDL_DOLLARRECORD:
   86.11 -        SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (long long) event->dgesture.gestureId);
   86.12 +        SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId);
   86.13          break;
   86.14      case SDL_MULTIGESTURE:
   86.15          SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers);
    87.1 --- a/src/thread/psp/SDL_syscond.c	Sat Jan 24 23:58:07 2015 -0400
    87.2 +++ b/src/thread/psp/SDL_syscond.c	Mon Apr 06 15:26:37 2015 -0300
    87.3 @@ -20,6 +20,8 @@
    87.4  */
    87.5  #include "../../SDL_internal.h"
    87.6  
    87.7 +#if SDL_THREAD_PSP
    87.8 +
    87.9  /* An implementation of condition variables using semaphores and mutexes */
   87.10  /*
   87.11     This implementation borrows heavily from the BeOS condition variable
   87.12 @@ -217,4 +219,6 @@
   87.13      return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
   87.14  }
   87.15  
   87.16 +#endif /* SDL_THREAD_PSP */
   87.17 +
   87.18  /* vi: set ts=4 sw=4 expandtab: */
    88.1 --- a/src/thread/psp/SDL_sysmutex.c	Sat Jan 24 23:58:07 2015 -0400
    88.2 +++ b/src/thread/psp/SDL_sysmutex.c	Mon Apr 06 15:26:37 2015 -0300
    88.3 @@ -20,6 +20,8 @@
    88.4  */
    88.5  #include "../../SDL_internal.h"
    88.6  
    88.7 +#if SDL_THREAD_PSP
    88.8 +
    88.9  /* An implementation of mutexes using semaphores */
   88.10  
   88.11  #include "SDL_thread.h"
   88.12 @@ -129,4 +131,6 @@
   88.13  #endif /* SDL_THREADS_DISABLED */
   88.14  }
   88.15  
   88.16 +#endif /* SDL_THREAD_PSP */
   88.17 +
   88.18  /* vi: set ts=4 sw=4 expandtab: */
    89.1 --- a/src/thread/psp/SDL_syssem.c	Sat Jan 24 23:58:07 2015 -0400
    89.2 +++ b/src/thread/psp/SDL_syssem.c	Mon Apr 06 15:26:37 2015 -0300
    89.3 @@ -18,6 +18,9 @@
    89.4       misrepresented as being the original software.
    89.5    3. This notice may not be removed or altered from any source distribution.
    89.6  */
    89.7 +#include "../../SDL_internal.h"
    89.8 +
    89.9 +#if SDL_THREAD_PSP
   89.10  
   89.11  /* Semaphore functions for the PSP. */
   89.12  
   89.13 @@ -152,5 +155,7 @@
   89.14      return 0;
   89.15  }
   89.16  
   89.17 +#endif /* SDL_THREAD_PSP */
   89.18 +
   89.19  /* vim: ts=4 sw=4
   89.20   */
    90.1 --- a/src/thread/psp/SDL_systhread.c	Sat Jan 24 23:58:07 2015 -0400
    90.2 +++ b/src/thread/psp/SDL_systhread.c	Mon Apr 06 15:26:37 2015 -0300
    90.3 @@ -18,7 +18,9 @@
    90.4       misrepresented as being the original software.
    90.5    3. This notice may not be removed or altered from any source distribution.
    90.6  */
    90.7 +#include "../../SDL_internal.h"
    90.8  
    90.9 +#if SDL_THREAD_PSP
   90.10  
   90.11  /* PSP thread management routines for SDL */
   90.12  
   90.13 @@ -104,5 +106,7 @@
   90.14  
   90.15  }
   90.16  
   90.17 +#endif /* SDL_THREAD_PSP */
   90.18 +
   90.19  /* vim: ts=4 sw=4
   90.20   */
    91.1 --- a/src/timer/psp/SDL_systimer.c	Sat Jan 24 23:58:07 2015 -0400
    91.2 +++ b/src/timer/psp/SDL_systimer.c	Mon Apr 06 15:26:37 2015 -0300
    91.3 @@ -18,6 +18,9 @@
    91.4       misrepresented as being the original software.
    91.5    3. This notice may not be removed or altered from any source distribution.
    91.6  */
    91.7 +#include "../../SDL_internal.h"
    91.8 +
    91.9 +#ifdef SDL_TIMERS_PSP
   91.10  
   91.11  #include "SDL_thread.h"
   91.12  #include "SDL_timer.h"
   91.13 @@ -82,5 +85,7 @@
   91.14      sceKernelDelayThreadCB(ms * 1000);
   91.15  }
   91.16  
   91.17 +#endif /* SDL_TIMERS_PSP */
   91.18 +
   91.19  /* vim: ts=4 sw=4
   91.20   */
    92.1 --- a/src/video/SDL_bmp.c	Sat Jan 24 23:58:07 2015 -0400
    92.2 +++ b/src/video/SDL_bmp.c	Mon Apr 06 15:26:37 2015 -0300
    92.3 @@ -306,16 +306,19 @@
    92.4              biClrUsed = 1 << biBitCount;
    92.5          }
    92.6          if ((int) biClrUsed > palette->ncolors) {
    92.7 -            palette->ncolors = biClrUsed;
    92.8 -            palette->colors =
    92.9 +            SDL_Color *colors;
   92.10 +            int ncolors = biClrUsed;
   92.11 +            colors =
   92.12                  (SDL_Color *) SDL_realloc(palette->colors,
   92.13 -                                          palette->ncolors *
   92.14 +                                          ncolors *
   92.15                                            sizeof(*palette->colors));
   92.16 -            if (!palette->colors) {
   92.17 +            if (!colors) {
   92.18                  SDL_OutOfMemory();
   92.19                  was_error = SDL_TRUE;
   92.20                  goto done;
   92.21              }
   92.22 +            palette->ncolors = ncolors;
   92.23 +            palette->colors = colors;
   92.24          } else if ((int) biClrUsed < palette->ncolors) {
   92.25              palette->ncolors = biClrUsed;
   92.26          }
    93.1 --- a/src/video/SDL_clipboard.c	Sat Jan 24 23:58:07 2015 -0400
    93.2 +++ b/src/video/SDL_clipboard.c	Mon Apr 06 15:26:37 2015 -0300
    93.3 @@ -29,6 +29,10 @@
    93.4  {
    93.5      SDL_VideoDevice *_this = SDL_GetVideoDevice();
    93.6  
    93.7 +    if (!_this) {
    93.8 +        return SDL_SetError("Video subsystem must be initialized to set clipboard text");
    93.9 +    }
   93.10 +
   93.11      if (!text) {
   93.12          text = "";
   93.13      }
   93.14 @@ -46,6 +50,11 @@
   93.15  {
   93.16      SDL_VideoDevice *_this = SDL_GetVideoDevice();
   93.17  
   93.18 +    if (!_this) {
   93.19 +        SDL_SetError("Video subsystem must be initialized to get clipboard text");
   93.20 +        return SDL_strdup("");
   93.21 +    }
   93.22 +
   93.23      if (_this->GetClipboardText) {
   93.24          return _this->GetClipboardText(_this);
   93.25      } else {
   93.26 @@ -62,6 +71,11 @@
   93.27  {
   93.28      SDL_VideoDevice *_this = SDL_GetVideoDevice();
   93.29  
   93.30 +    if (!_this) {
   93.31 +        SDL_SetError("Video subsystem must be initialized to check clipboard text");
   93.32 +        return SDL_FALSE;
   93.33 +    }
   93.34 +
   93.35      if (_this->HasClipboardText) {
   93.36          return _this->HasClipboardText(_this);
   93.37      } else {
    94.1 --- a/src/video/SDL_fillrect.c	Sat Jan 24 23:58:07 2015 -0400
    94.2 +++ b/src/video/SDL_fillrect.c	Mon Apr 06 15:26:37 2015 -0300
    94.3 @@ -251,6 +251,10 @@
    94.4          rect = &clipped;
    94.5      } else {
    94.6          rect = &dst->clip_rect;
    94.7 +        /* Don't attempt to fill if the surface's clip_rect is empty */
    94.8 +        if (SDL_RectEmpty(rect)) {
    94.9 +            return 0;
   94.10 +        }
   94.11      }
   94.12  
   94.13      /* Perform software fill */
    95.1 --- a/src/video/SDL_sysvideo.h	Sat Jan 24 23:58:07 2015 -0400
    95.2 +++ b/src/video/SDL_sysvideo.h	Mon Apr 06 15:26:37 2015 -0300
    95.3 @@ -274,6 +274,7 @@
    95.4      int num_displays;
    95.5      SDL_VideoDisplay *displays;
    95.6      SDL_Window *windows;
    95.7 +    SDL_Window *grabbed_window;
    95.8      Uint8 window_magic;
    95.9      Uint32 next_object_id;
   95.10      char * clipboard_text;
   95.11 @@ -303,6 +304,7 @@
   95.12          int flags;
   95.13          int profile_mask;
   95.14          int share_with_current_context;
   95.15 +        int release_behavior;
   95.16          int framebuffer_srgb_capable;
   95.17          int retained_backing;
   95.18          int driver_loaded;
    96.1 --- a/src/video/SDL_video.c	Sat Jan 24 23:58:07 2015 -0400
    96.2 +++ b/src/video/SDL_video.c	Mon Apr 06 15:26:37 2015 -0300
    96.3 @@ -46,6 +46,10 @@
    96.4  #include "SDL_opengles2.h"
    96.5  #endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */
    96.6  
    96.7 +#ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR
    96.8 +#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB
    96.9 +#endif
   96.10 +
   96.11  /* On Windows, windows.h defines CreateWindow */
   96.12  #ifdef CreateWindow
   96.13  #undef CreateWindow
   96.14 @@ -1612,13 +1616,14 @@
   96.15      CHECK_WINDOW_MAGIC(window,);
   96.16  
   96.17      if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) {
   96.18 -        SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
   96.19 -        int displayIndex;
   96.20 +        int displayIndex = (x & 0xFFFF);
   96.21          SDL_Rect bounds;
   96.22 +        if (displayIndex > _this->num_displays) {
   96.23 +            displayIndex = 0;
   96.24 +        }
   96.25  
   96.26          SDL_zero(bounds);
   96.27  
   96.28 -        displayIndex = SDL_GetIndexOfDisplay(display);
   96.29          SDL_GetDisplayBounds(displayIndex, &bounds);
   96.30          if (SDL_WINDOWPOS_ISCENTERED(x)) {
   96.31              x = bounds.x + (bounds.w - window->w) / 2;
   96.32 @@ -2114,6 +2119,7 @@
   96.33  SDL_UpdateWindowGrab(SDL_Window * window)
   96.34  {
   96.35      if (_this->SetWindowGrab) {
   96.36 +        SDL_Window *grabbed_window;
   96.37          SDL_bool grabbed;
   96.38          if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
   96.39               (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
   96.40 @@ -2121,6 +2127,19 @@
   96.41          } else {
   96.42              grabbed = SDL_FALSE;
   96.43          }
   96.44 +
   96.45 +        grabbed_window = _this->grabbed_window;
   96.46 +        if (grabbed) {
   96.47 +            if (grabbed_window && (grabbed_window != window)) {
   96.48 +                /* stealing a grab from another window! */
   96.49 +                grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED;
   96.50 +                _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE);
   96.51 +            }
   96.52 +            _this->grabbed_window = window;
   96.53 +        } else if (grabbed_window == window) {
   96.54 +            _this->grabbed_window = NULL;  /* ungrabbing. */
   96.55 +        }
   96.56 +
   96.57          _this->SetWindowGrab(_this, window, grabbed);
   96.58      }
   96.59  }
   96.60 @@ -2145,8 +2164,15 @@
   96.61  SDL_GetWindowGrab(SDL_Window * window)
   96.62  {
   96.63      CHECK_WINDOW_MAGIC(window, SDL_FALSE);
   96.64 -
   96.65 -    return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0);
   96.66 +    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
   96.67 +    return window == _this->grabbed_window;
   96.68 +}
   96.69 +
   96.70 +SDL_Window *
   96.71 +SDL_GetGrabbedWindow(void)
   96.72 +{
   96.73 +    SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0));
   96.74 +    return _this->grabbed_window;
   96.75  }
   96.76  
   96.77  void
   96.78 @@ -2639,6 +2665,7 @@
   96.79  #endif
   96.80      _this->gl_config.flags = 0;
   96.81      _this->gl_config.framebuffer_srgb_capable = 0;
   96.82 +    _this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH;
   96.83  
   96.84      _this->gl_config.share_with_current_context = 0;
   96.85  }
   96.86 @@ -2745,6 +2772,9 @@
   96.87      case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE:
   96.88          _this->gl_config.framebuffer_srgb_capable = value;
   96.89          break;
   96.90 +    case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
   96.91 +        _this->gl_config.release_behavior = value;
   96.92 +        break;
   96.93      default:
   96.94          retval = SDL_SetError("Unknown OpenGL attribute");
   96.95          break;
   96.96 @@ -2847,6 +2877,13 @@
   96.97          attrib = GL_SAMPLES;
   96.98  #endif
   96.99          break;
  96.100 +    case SDL_GL_CONTEXT_RELEASE_BEHAVIOR:
  96.101 +#if SDL_VIDEO_OPENGL
  96.102 +        attrib = GL_CONTEXT_RELEASE_BEHAVIOR;
  96.103 +#else
  96.104 +        attrib = GL_CONTEXT_RELEASE_BEHAVIOR_KHR;
  96.105 +#endif
  96.106 +        break;
  96.107      case SDL_GL_BUFFER_SIZE:
  96.108          {
  96.109              GLint bits = 0;
    97.1 --- a/src/video/android/SDL_androidevents.c	Sat Jan 24 23:58:07 2015 -0400
    97.2 +++ b/src/video/android/SDL_androidevents.c	Mon Apr 06 15:26:37 2015 -0300
    97.3 @@ -32,8 +32,14 @@
    97.4  
    97.5  void android_egl_context_backup();
    97.6  void android_egl_context_restore();
    97.7 +
    97.8 +#if SDL_AUDIO_DRIVER_ANDROID
    97.9  void AndroidAUD_ResumeDevices(void);
   97.10  void AndroidAUD_PauseDevices(void);
   97.11 +#else
   97.12 +static void AndroidAUD_ResumeDevices(void) {}
   97.13 +static void AndroidAUD_PauseDevices(void) {}
   97.14 +#endif
   97.15  
   97.16  void 
   97.17  android_egl_context_restore() 
    98.1 --- a/src/video/android/SDL_androidmessagebox.c	Sat Jan 24 23:58:07 2015 -0400
    98.2 +++ b/src/video/android/SDL_androidmessagebox.c	Mon Apr 06 15:26:37 2015 -0300
    98.3 @@ -18,7 +18,7 @@
    98.4       misrepresented as being the original software.
    98.5    3. This notice may not be removed or altered from any source distribution.
    98.6  */
    98.7 -#include "SDL_config.h"
    98.8 +#include "../../SDL_internal.h"
    98.9  
   98.10  #if SDL_VIDEO_DRIVER_ANDROID
   98.11  
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/src/video/android/SDL_androidmouse.c	Mon Apr 06 15:26:37 2015 -0300
    99.3 @@ -0,0 +1,84 @@
    99.4 +/*
    99.5 +  Simple DirectMedia Layer
    99.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
    99.7 +
    99.8 +  This software is provided 'as-is', without any express or implied
    99.9 +  warranty.  In no event will the authors be held liable for any damages
   99.10 +  arising from the use of this software.
   99.11 +
   99.12 +  Permission is granted to anyone to use this software for any purpose,
   99.13 +  including commercial applications, and to alter it and redistribute it
   99.14 +  freely, subject to the following restrictions:
   99.15 +
   99.16 +  1. The origin of this software must not be misrepresented; you must not
   99.17 +     claim that you wrote the original software. If you use this software
   99.18 +     in a product, an acknowledgment in the product documentation would be
   99.19 +     appreciated but is not required.
   99.20 +  2. Altered source versions must be plainly marked as such, and must not be
   99.21 +     misrepresented as being the original software.
   99.22 +  3. This notice may not be removed or altered from any source distribution.
   99.23 +*/
   99.24 +
   99.25 +#include "../../SDL_internal.h"
   99.26 +
   99.27 +#if SDL_VIDEO_DRIVER_ANDROID
   99.28 +
   99.29 +#include "SDL_androidmouse.h"
   99.30 +
   99.31 +#include "SDL_events.h"
   99.32 +#include "../../events/SDL_mouse_c.h"
   99.33 +
   99.34 +#include "../../core/android/SDL_android.h"
   99.35 +
   99.36 +#define ACTION_DOWN 0
   99.37 +#define ACTION_UP 1
   99.38 +#define ACTION_HOVER_MOVE 7
   99.39 +#define ACTION_SCROLL 8
   99.40 +#define BUTTON_PRIMARY 1
   99.41 +#define BUTTON_SECONDARY 2
   99.42 +#define BUTTON_TERTIARY 4
   99.43 +
   99.44 +void Android_OnMouse( int androidButton, int action, float x, float y) {
   99.45 +    static Uint8 SDLButton;
   99.46 +
   99.47 +    if (!Android_Window) {
   99.48 +        return;
   99.49 +    }
   99.50 +
   99.51 +    switch(action) {
   99.52 +        case ACTION_DOWN:
   99.53 +            // Determine which button originated the event, and store it for ACTION_UP
   99.54 +            SDLButton = SDL_BUTTON_LEFT;
   99.55 +            if (androidButton == BUTTON_SECONDARY) {
   99.56 +                SDLButton = SDL_BUTTON_RIGHT;
   99.57 +            } else if (androidButton == BUTTON_TERTIARY) {
   99.58 +                SDLButton = SDL_BUTTON_MIDDLE;
   99.59 +            }
   99.60 +            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
   99.61 +            SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, SDLButton);
   99.62 +            break;
   99.63 +
   99.64 +        case ACTION_UP:
   99.65 +            // Android won't give us the button that originated the ACTION_DOWN event, so we'll
   99.66 +            // assume it's the one we stored
   99.67 +            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
   99.68 +            SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, SDLButton);
   99.69 +            break;
   99.70 +
   99.71 +        case ACTION_HOVER_MOVE:
   99.72 +            SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
   99.73 +            break;
   99.74 +
   99.75 +        case ACTION_SCROLL:
   99.76 +            SDL_SendMouseWheel(Android_Window, 0, x, y, SDL_MOUSEWHEEL_NORMAL);
   99.77 +            break;
   99.78 +
   99.79 +        default:
   99.80 +            break;
   99.81 +    }
   99.82 +}
   99.83 +
   99.84 +#endif /* SDL_VIDEO_DRIVER_ANDROID */
   99.85 +
   99.86 +/* vi: set ts=4 sw=4 expandtab: */
   99.87 +
   100.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   100.2 +++ b/src/video/android/SDL_androidmouse.h	Mon Apr 06 15:26:37 2015 -0300
   100.3 @@ -0,0 +1,31 @@
   100.4 +/*
   100.5 +  Simple DirectMedia Layer
   100.6 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
   100.7 +
   100.8 +  This software is provided 'as-is', without any express or implied
   100.9 +  warranty.  In no event will the authors be held liable for any damages
  100.10 +  arising from the use of this software.
  100.11 +
  100.12 +  Permission is granted to anyone to use this software for any purpose,
  100.13 +  including commercial applications, and to alter it and redistribute it
  100.14 +  freely, subject to the following restrictions:
  100.15 +
  100.16 +  1. The origin of this software must not be misrepresented; you must not
  100.17 +     claim that you wrote the original software. If you use this software
  100.18 +     in a product, an acknowledgment in the product documentation would be
  100.19 +     appreciated but is not required.
  100.20 +  2. Altered source versions must be plainly marked as such, and must not be
  100.21 +     misrepresented as being the original software.
  100.22 +  3. This notice may not be removed or altered from any source distribution.
  100.23 +*/
  100.24 +
  100.25 +#ifndef _SDL_androidmouse_h
  100.26 +#define _SDL_androidmouse_h
  100.27 +
  100.28 +#include "SDL_androidvideo.h"
  100.29 +
  100.30 +extern void Android_OnMouse( int button, int action, float x, float y);
  100.31 +
  100.32 +#endif /* _SDL_androidmouse_h */
  100.33 +
  100.34 +/* vi: set ts=4 sw=4 expandtab: */
   101.1 --- a/src/video/android/SDL_androidtouch.c	Sat Jan 24 23:58:07 2015 -0400
   101.2 +++ b/src/video/android/SDL_androidtouch.c	Mon Apr 06 15:26:37 2015 -0300
   101.3 @@ -24,13 +24,12 @@
   101.4  
   101.5  #include <android/log.h>
   101.6  
   101.7 +#include "SDL_hints.h"
   101.8  #include "SDL_events.h"
   101.9 +#include "SDL_log.h"
  101.10 +#include "SDL_androidtouch.h"
  101.11  #include "../../events/SDL_mouse_c.h"
  101.12  #include "../../events/SDL_touch_c.h"
  101.13 -#include "SDL_log.h"
  101.14 -
  101.15 -#include "SDL_androidtouch.h"
  101.16 -
  101.17  #include "../../core/android/SDL_android.h"
  101.18  
  101.19  #define ACTION_DOWN 0
  101.20 @@ -51,11 +50,29 @@
  101.21      *window_y = (int)(y * window_h);
  101.22  }
  101.23  
  101.24 +static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE;
  101.25 +
  101.26 +static void
  101.27 +SeparateEventsHintWatcher(void *userdata, const char *name,
  101.28 +                          const char *oldValue, const char *newValue)
  101.29 +{
  101.30 +    jclass mActivityClass = Android_JNI_GetActivityClass();
  101.31 +    JNIEnv *env = Android_JNI_GetEnv();
  101.32 +    jfieldID fid = (*env)->GetStaticFieldID(env, mActivityClass, "mSeparateMouseAndTouch", "Z");
  101.33 +
  101.34 +    separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0));
  101.35 +    (*env)->SetStaticBooleanField(env, mActivityClass, fid, separate_mouse_and_touch ? JNI_TRUE : JNI_FALSE);
  101.36 +}
  101.37 +
  101.38  void Android_InitTouch(void)
  101.39  {
  101.40      int i;
  101.41      int* ids;
  101.42 -    int number = Android_JNI_GetTouchDeviceIds(&ids);
  101.43 +    const int number = Android_JNI_GetTouchDeviceIds(&ids);
  101.44 +
  101.45 +    SDL_AddHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
  101.46 +                        SeparateEventsHintWatcher, NULL);
  101.47 +
  101.48      if (0 < number) {
  101.49          for (i = 0; i < number; ++i) {
  101.50              SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */
  101.51 @@ -64,6 +81,13 @@
  101.52      }
  101.53  }
  101.54  
  101.55 +void Android_QuitTouch(void)
  101.56 +{
  101.57 +    SDL_DelHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH,
  101.58 +                        SeparateEventsHintWatcher, NULL);
  101.59 +    separate_mouse_and_touch = SDL_FALSE;
  101.60 +}
  101.61 +
  101.62  void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p)
  101.63  {
  101.64      SDL_TouchID touchDeviceId = 0;
  101.65 @@ -85,36 +109,41 @@
  101.66          case ACTION_DOWN:
  101.67              /* Primary pointer down */
  101.68              Android_GetWindowCoordinates(x, y, &window_x, &window_y);
  101.69 -            /* send moved event */
  101.70 -            SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
  101.71 -            /* send mouse down event */
  101.72 -            SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
  101.73 +            if (!separate_mouse_and_touch) {
  101.74 +                /* send moved event */
  101.75 +                SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
  101.76 +                /* send mouse down event */
  101.77 +                SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
  101.78 +            }
  101.79              pointerFingerID = fingerId;
  101.80          case ACTION_POINTER_DOWN:
  101.81              /* Non primary pointer down */
  101.82              SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p);
  101.83              break;
  101.84 -            
  101.85 +
  101.86          case ACTION_MOVE:
  101.87              if (!pointerFingerID) {
  101.88                  Android_GetWindowCoordinates(x, y, &window_x, &window_y);
  101.89 -
  101.90 -                /* send moved event */
  101.91 -                SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
  101.92 +                if (!separate_mouse_and_touch) {
  101.93 +                    /* send moved event */
  101.94 +                    SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y);
  101.95 +                }
  101.96              }
  101.97              SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p);
  101.98              break;
  101.99 -            
 101.100 +
 101.101          case ACTION_UP:
 101.102              /* Primary pointer up */
 101.103 -            /* send mouse up */
 101.104 -            pointerFingerID = (SDL_FingerID) 0;
 101.105 -            SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
 101.106 +            if (!separate_mouse_and_touch) {
 101.107 +                /* send mouse up */
 101.108 +                pointerFingerID = (SDL_FingerID) 0;
 101.109 +                SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
 101.110 +            }
 101.111          case ACTION_POINTER_UP:
 101.112              /* Non primary pointer up */
 101.113              SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p);
 101.114              break;
 101.115 -            
 101.116 +
 101.117          default:
 101.118              break;
 101.119      }
   102.1 --- a/src/video/android/SDL_androidtouch.h	Sat Jan 24 23:58:07 2015 -0400
   102.2 +++ b/src/video/android/SDL_androidtouch.h	Mon Apr 06 15:26:37 2015 -0300
   102.3 @@ -23,6 +23,7 @@
   102.4  #include "SDL_androidvideo.h"
   102.5  
   102.6  extern void Android_InitTouch(void);
   102.7 +extern void Android_QuitTouch(void);
   102.8  extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p);
   102.9  
  102.10  /* vi: set ts=4 sw=4 expandtab: */
   103.1 --- a/src/video/android/SDL_androidvideo.c	Sat Jan 24 23:58:07 2015 -0400
   103.2 +++ b/src/video/android/SDL_androidvideo.c	Mon Apr 06 15:26:37 2015 -0300
   103.3 @@ -86,6 +86,7 @@
   103.4  static void
   103.5  Android_DeleteDevice(SDL_VideoDevice * device)
   103.6  {
   103.7 +    SDL_free(device->driverdata);
   103.8      SDL_free(device);
   103.9  }
  103.10  
  103.11 @@ -187,6 +188,7 @@
  103.12  void
  103.13  Android_VideoQuit(_THIS)
  103.14  {
  103.15 +    Android_QuitTouch();
  103.16  }
  103.17  
  103.18  /* This function gets called before VideoInit() */
   104.1 --- a/src/video/cocoa/SDL_cocoaevents.h	Sat Jan 24 23:58:07 2015 -0400
   104.2 +++ b/src/video/cocoa/SDL_cocoaevents.h	Mon Apr 06 15:26:37 2015 -0300
   104.3 @@ -25,6 +25,7 @@
   104.4  
   104.5  extern void Cocoa_RegisterApp(void);
   104.6  extern void Cocoa_PumpEvents(_THIS);
   104.7 +extern void Cocoa_SuspendScreenSaver(_THIS);
   104.8  
   104.9  #endif /* _SDL_cocoaevents_h */
  104.10  
   105.1 --- a/src/video/cocoa/SDL_cocoaevents.m	Sat Jan 24 23:58:07 2015 -0400
   105.2 +++ b/src/video/cocoa/SDL_cocoaevents.m	Mon Apr 06 15:26:37 2015 -0300
   105.3 @@ -27,6 +27,11 @@
   105.4  #include "../../events/SDL_events_c.h"
   105.5  #include "SDL_assert.h"
   105.6  
   105.7 +/* This define was added in the 10.9 SDK. */
   105.8 +#ifndef kIOPMAssertPreventUserIdleDisplaySleep
   105.9 +#define kIOPMAssertPreventUserIdleDisplaySleep kIOPMAssertionTypePreventUserIdleDisplaySleep
  105.10 +#endif
  105.11 +
  105.12  @interface SDLApplication : NSApplication
  105.13  
  105.14  - (void)terminate:(id)sender;
  105.15 @@ -61,11 +66,19 @@
  105.16  {
  105.17      self = [super init];
  105.18      if (self) {
  105.19 +        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
  105.20 +
  105.21          seenFirstActivate = NO;
  105.22 -        [[NSNotificationCenter defaultCenter] addObserver:self
  105.23 -                                                 selector:@selector(focusSomeWindow:)
  105.24 -                                                     name:NSApplicationDidBecomeActiveNotification
  105.25 -                                                   object:nil];
  105.26 +
  105.27 +        [center addObserver:self
  105.28 +                   selector:@selector(windowWillClose:)
  105.29 +                       name:NSWindowWillCloseNotification
  105.30 +                     object:nil];
  105.31 +
  105.32 +        [center addObserver:self
  105.33 +                   selector:@selector(focusSomeWindow:)
  105.34 +                       name:NSApplicationDidBecomeActiveNotification
  105.35 +                     object:nil];
  105.36      }
  105.37  
  105.38      return self;
  105.39 @@ -73,16 +86,65 @@
  105.40  
  105.41  - (void)dealloc
  105.42  {
  105.43 -    [[NSNotificationCenter defaultCenter] removeObserver:self];
  105.44 +    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
  105.45 +
  105.46 +    [center removeObserver:self name:NSWindowWillCloseNotification object:nil];
  105.47 +    [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
  105.48 +
  105.49      [super dealloc];
  105.50  }
  105.51  
  105.52 +- (void)windowWillClose:(NSNotification *)notification;
  105.53 +{
  105.54 +    NSWindow *win = (NSWindow*)[notification object];
  105.55 +
  105.56 +    if (![win isKeyWindow]) {
  105.57 +        return;
  105.58 +    }
  105.59 +
  105.60 +    /* HACK: Make the next window in the z-order key when the key window is
  105.61 +     * closed. The custom event loop and/or windowing code we have seems to
  105.62 +     * prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825
  105.63 +     */
  105.64 +
  105.65 +    /* +[NSApp orderedWindows] never includes the 'About' window, but we still
  105.66 +     * want to try its list first since the behavior in other apps is to only
  105.67 +     * make the 'About' window key if no other windows are on-screen.
  105.68 +     */
  105.69 +    for (NSWindow *window in [NSApp orderedWindows]) {
  105.70 +        if (window != win && [window canBecomeKeyWindow]) {
  105.71 +            if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
  105.72 +                if (![window isOnActiveSpace]) {
  105.73 +                    continue;
  105.74 +                }
  105.75 +            }
  105.76 +            [window makeKeyAndOrderFront:self];
  105.77 +            return;
  105.78 +        }
  105.79 +    }
  105.80 +
  105.81 +    /* If a window wasn't found above, iterate through all visible windows
  105.82 +     * (including the 'About' window, if it's shown) and make the first one key.
  105.83 +     * Note that +[NSWindow windowNumbersWithOptions:] was added in 10.6.
  105.84 +     */
  105.85 +    if ([NSWindow respondsToSelector:@selector(windowNumbersWithOptions:)]) {
  105.86 +        /* Get all visible windows in the active Space, in z-order. */
  105.87 +        for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
  105.88 +            NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
  105.89 +            if (window && window != win && [window canBecomeKeyWindow]) {
  105.90 +                [window makeKeyAndOrderFront:self];
  105.91 +                return;
  105.92 +            }
  105.93 +        }
  105.94 +    }
  105.95 +}
  105.96 +
  105.97  - (void)focusSomeWindow:(NSNotification *)aNotification
  105.98  {
  105.99      /* HACK: Ignore the first call. The application gets a
 105.100       * applicationDidBecomeActive: a little bit after the first window is
 105.101       * created, and if we don't ignore it, a window that has been created with
 105.102 -     * SDL_WINDOW_MINIZED will ~immediately be restored.
 105.103 +     * SDL_WINDOW_MINIMIZED will ~immediately be restored.
 105.104       */
 105.105      if (!seenFirstActivate) {
 105.106          seenFirstActivate = YES;
 105.107 @@ -251,17 +313,24 @@
 105.108  { @autoreleasepool
 105.109  {
 105.110      /* This can get called more than once! Be careful what you initialize! */
 105.111 -    ProcessSerialNumber psn;
 105.112 -
 105.113 -    if (!GetCurrentProcess(&psn)) {
 105.114 -        TransformProcessType(&psn, kProcessTransformToForegroundApplication);
 105.115 -        SetFrontProcess(&psn);
 105.116 -    }
 105.117  
 105.118      if (NSApp == nil) {
 105.119          [SDLApplication sharedApplication];
 105.120          SDL_assert(NSApp != nil);
 105.121  
 105.122 +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
 105.123 +        if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) {
 105.124 +#endif
 105.125 +            [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
 105.126 +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
 105.127 +        } else {
 105.128 +            ProcessSerialNumber psn = {0, kCurrentProcess};
 105.129 +            TransformProcessType(&psn, kProcessTransformToForegroundApplication);
 105.130 +        }
 105.131 +#endif
 105.132 +
 105.133 +        [NSApp activateIgnoringOtherApps:YES];
 105.134 +
 105.135          if ([NSApp mainMenu] == nil) {
 105.136              CreateApplicationMenus();
 105.137          }
 105.138 @@ -293,8 +362,8 @@
 105.139  { @autoreleasepool
 105.140  {
 105.141      /* Update activity every 30 seconds to prevent screensaver */
 105.142 -    if (_this->suspend_screensaver) {
 105.143 -        SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
 105.144 +    SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
 105.145 +    if (_this->suspend_screensaver && !data->screensaver_use_iopm) {
 105.146          Uint32 now = SDL_GetTicks();
 105.147          if (!data->screensaver_activity ||
 105.148              SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
 105.149 @@ -336,6 +405,35 @@
 105.150      }
 105.151  }}
 105.152  
 105.153 +void
 105.154 +Cocoa_SuspendScreenSaver(_THIS)
 105.155 +{ @autoreleasepool
 105.156 +{
 105.157 +    SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
 105.158 +
 105.159 +    if (!data->screensaver_use_iopm) {
 105.160 +        return;
 105.161 +    }
 105.162 +
 105.163 +    if (data->screensaver_assertion) {
 105.164 +        IOPMAssertionRelease(data->screensaver_assertion);
 105.165 +        data->screensaver_assertion = 0;
 105.166 +    }
 105.167 +
 105.168 +    if (_this->suspend_screensaver) {
 105.169 +        /* FIXME: this should ideally describe the real reason why the game
 105.170 +         * called SDL_DisableScreenSaver. Note that the name is only meant to be
 105.171 +         * seen by OS X power users. there's an additional optional human-readable
 105.172 +         * (localized) reason parameter which we don't set.
 105.173 +         */
 105.174 +        NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"];
 105.175 +        IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep,
 105.176 +                                           (CFStringRef) name,
 105.177 +                                           NULL, NULL, NULL, 0, NULL,
 105.178 +                                           &data->screensaver_assertion);
 105.179 +    }
 105.180 +}}
 105.181 +
 105.182  #endif /* SDL_VIDEO_DRIVER_COCOA */
 105.183  
 105.184  /* vi: set ts=4 sw=4 expandtab: */
   106.1 --- a/src/video/cocoa/SDL_cocoavideo.h	Sat Jan 24 23:58:07 2015 -0400
   106.2 +++ b/src/video/cocoa/SDL_cocoavideo.h	Mon Apr 06 15:26:37 2015 -0300
   106.3 @@ -26,6 +26,7 @@
   106.4  #include "SDL_opengl.h"
   106.5  
   106.6  #include <ApplicationServices/ApplicationServices.h>
   106.7 +#include <IOKit/pwr_mgt/IOPMLib.h>
   106.8  #include <Cocoa/Cocoa.h>
   106.9  
  106.10  #include "SDL_keycode.h"
  106.11 @@ -51,6 +52,9 @@
  106.12      SDLTranslatorResponder *fieldEdit;
  106.13      NSInteger clipboard_count;
  106.14      Uint32 screensaver_activity;
  106.15 +    BOOL screensaver_use_iopm;
  106.16 +    IOPMAssertionID screensaver_assertion;
  106.17 +
  106.18  } SDL_VideoData;
  106.19  
  106.20  /* Utility functions */
   107.1 --- a/src/video/cocoa/SDL_cocoavideo.m	Sat Jan 24 23:58:07 2015 -0400
   107.2 +++ b/src/video/cocoa/SDL_cocoavideo.m	Mon Apr 06 15:26:37 2015 -0300
   107.3 @@ -76,6 +76,7 @@
   107.4      device->GetDisplayModes = Cocoa_GetDisplayModes;
   107.5      device->SetDisplayMode = Cocoa_SetDisplayMode;
   107.6      device->PumpEvents = Cocoa_PumpEvents;
   107.7 +    device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
   107.8  
   107.9      device->CreateWindow = Cocoa_CreateWindow;
  107.10      device->CreateWindowFrom = Cocoa_CreateWindowFrom;
  107.11 @@ -148,6 +149,9 @@
  107.12      const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES);
  107.13      data->allow_spaces = ( (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && (!hint || (*hint != '0')) );
  107.14  
  107.15 +    /* The IOPM assertion API can disable the screensaver as of 10.7. */
  107.16 +    data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
  107.17 +
  107.18      return 0;
  107.19  }
  107.20  
   108.1 --- a/src/video/cocoa/SDL_cocoawindow.m	Sat Jan 24 23:58:07 2015 -0400
   108.2 +++ b/src/video/cocoa/SDL_cocoawindow.m	Mon Apr 06 15:26:37 2015 -0300
   108.3 @@ -374,7 +374,6 @@
   108.4      NSNotificationCenter *center;
   108.5      NSWindow *window = _data->nswindow;
   108.6      NSView *view = [window contentView];
   108.7 -    NSArray *windows = nil;
   108.8  
   108.9      center = [NSNotificationCenter defaultCenter];
  108.10  
  108.11 @@ -402,25 +401,6 @@
  108.12      if ([view nextResponder] == self) {
  108.13          [view setNextResponder:nil];
  108.14      }
  108.15 -
  108.16 -    /* Make the next window in the z-order Key. If we weren't the foreground
  108.17 -       when closed, this is a no-op.
  108.18 -       !!! FIXME: Note that this is a hack, and there are corner cases where
  108.19 -       !!! FIXME:  this fails (such as the About box). The typical nib+RunLoop
  108.20 -       !!! FIXME:  handles this for Cocoa apps, but we bypass all that in SDL.
  108.21 -       !!! FIXME:  We should remove this code when we find a better way to
  108.22 -       !!! FIXME:  have the system do this for us. See discussion in
  108.23 -       !!! FIXME:   http://bugzilla.libsdl.org/show_bug.cgi?id=1825
  108.24 -    */
  108.25 -    windows = [NSApp orderedWindows];
  108.26 -    for (NSWindow *win in windows) {
  108.27 -        if (win == window) {
  108.28 -            continue;
  108.29 -        }
  108.30 -
  108.31 -        [win makeKeyAndOrderFront:self];
  108.32 -        break;
  108.33 -    }
  108.34  }
  108.35  
  108.36  - (BOOL)isMoving
   109.1 --- a/src/video/dummy/SDL_nullvideo.c	Sat Jan 24 23:58:07 2015 -0400
   109.2 +++ b/src/video/dummy/SDL_nullvideo.c	Mon Apr 06 15:26:37 2015 -0300
   109.3 @@ -82,7 +82,6 @@
   109.4      device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
   109.5      if (!device) {
   109.6          SDL_OutOfMemory();
   109.7 -        SDL_free(device);
   109.8          return (0);
   109.9      }
  109.10  
   110.1 --- a/src/video/emscripten/SDL_emscriptenevents.c	Sat Jan 24 23:58:07 2015 -0400
   110.2 +++ b/src/video/emscripten/SDL_emscriptenevents.c	Mon Apr 06 15:26:37 2015 -0300
   110.3 @@ -296,7 +296,7 @@
   110.4      return SDL_TRUE;
   110.5  }
   110.6  
   110.7 -int
   110.8 +EM_BOOL
   110.9  Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  110.10  {
  110.11      SDL_WindowData *window_data = userData;
  110.12 @@ -322,7 +322,7 @@
  110.13      return 0;
  110.14  }
  110.15  
  110.16 -int
  110.17 +EM_BOOL
  110.18  Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  110.19  {
  110.20      SDL_WindowData *window_data = userData;
  110.21 @@ -344,7 +344,7 @@
  110.22      return 1;
  110.23  }
  110.24  
  110.25 -int
  110.26 +EM_BOOL
  110.27  Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
  110.28  {
  110.29      SDL_WindowData *window_data = userData;
  110.30 @@ -352,7 +352,7 @@
  110.31      return 1;
  110.32  }
  110.33  
  110.34 -int
  110.35 +EM_BOOL
  110.36  Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
  110.37  {
  110.38      SDL_WindowData *window_data = userData;
  110.39 @@ -360,7 +360,7 @@
  110.40      return 1;
  110.41  }
  110.42  
  110.43 -int
  110.44 +EM_BOOL
  110.45  Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
  110.46  {
  110.47      SDL_WindowData *window_data = userData;
  110.48 @@ -368,7 +368,7 @@
  110.49      return 1;
  110.50  }
  110.51  
  110.52 -int
  110.53 +EM_BOOL
  110.54  Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
  110.55  {
  110.56      /*SDL_WindowData *window_data = userData;*/
  110.57 @@ -404,7 +404,7 @@
  110.58      return 1;
  110.59  }
  110.60  
  110.61 -int
  110.62 +EM_BOOL
  110.63  Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
  110.64  {
  110.65      Uint32 scancode;
  110.66 @@ -443,16 +443,17 @@
  110.67              || keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
  110.68  }
  110.69  
  110.70 -int
  110.71 +EM_BOOL
  110.72  Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData)
  110.73  {
  110.74      char text[5];
  110.75 -    Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text);
  110.76 -    SDL_SendKeyboardText(text);
  110.77 +    if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) {
  110.78 +        SDL_SendKeyboardText(text);
  110.79 +    }
  110.80      return 1;
  110.81  }
  110.82  
  110.83 -int
  110.84 +EM_BOOL
  110.85  Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
  110.86  {
  110.87      /*make sure this is actually our element going fullscreen*/
  110.88 @@ -514,7 +515,7 @@
  110.89      return 0;
  110.90  }
  110.91  
  110.92 -int
  110.93 +EM_BOOL
  110.94  Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
  110.95  {
  110.96      SDL_WindowData *window_data = userData;
  110.97 @@ -554,7 +555,7 @@
  110.98      return 0;
  110.99  }
 110.100  
 110.101 -int
 110.102 +EM_BOOL
 110.103  Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
 110.104  {
 110.105      SDL_WindowData *window_data = userData;
 110.106 @@ -621,10 +622,15 @@
 110.107      emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL);
 110.108      emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL);
 110.109  
 110.110 -    emscripten_set_keydown_callback("#window", NULL, 0, NULL);
 110.111 -    emscripten_set_keyup_callback("#window", NULL, 0, NULL);
 110.112 +    const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT);
 110.113 +    if (!target) {
 110.114 +        target = "#window";
 110.115 +    }
 110.116  
 110.117 -    emscripten_set_keypress_callback("#window", NULL, 0, NULL);
 110.118 +    emscripten_set_keydown_callback(target, NULL, 0, NULL);
 110.119 +    emscripten_set_keyup_callback(target, NULL, 0, NULL);
 110.120 +
 110.121 +    emscripten_set_keypress_callback(target, NULL, 0, NULL);
 110.122  
 110.123      emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL);
 110.124  
   111.1 --- a/src/video/emscripten/SDL_emscriptenframebuffer.c	Sat Jan 24 23:58:07 2015 -0400
   111.2 +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c	Mon Apr 06 15:26:37 2015 -0300
   111.3 @@ -63,7 +63,7 @@
   111.4      SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
   111.5      surface = data->surface;
   111.6      if (!surface) {
   111.7 -        return SDL_SetError("Couldn't find dummy surface for window");
   111.8 +        return SDL_SetError("Couldn't find framebuffer surface for window");
   111.9      }
  111.10  
  111.11      /* Send the data to the display */
   112.1 --- a/src/video/nacl/SDL_naclevents.c	Sat Jan 24 23:58:07 2015 -0400
   112.2 +++ b/src/video/nacl/SDL_naclevents.c	Mon Apr 06 15:26:37 2015 -0300
   112.3 @@ -20,6 +20,8 @@
   112.4  */
   112.5  #include "../../SDL_internal.h"
   112.6  
   112.7 +#if SDL_VIDEO_DRIVER_NACL
   112.8 +
   112.9  #include "SDL.h"
  112.10  #include "../../events/SDL_sysevents.h"
  112.11  #include "../../events/SDL_events_c.h"
  112.12 @@ -430,3 +432,7 @@
  112.13      }
  112.14    }
  112.15  }
  112.16 +
  112.17 +#endif /* SDL_VIDEO_DRIVER_NACL */
  112.18 +
  112.19 +/* vi: set ts=4 sw=4 expandtab: */
   113.1 --- a/src/video/psp/SDL_pspevents.c	Sat Jan 24 23:58:07 2015 -0400
   113.2 +++ b/src/video/psp/SDL_pspevents.c	Mon Apr 06 15:26:37 2015 -0300
   113.3 @@ -18,6 +18,9 @@
   113.4       misrepresented as being the original software.
   113.5    3. This notice may not be removed or altered from any source distribution.
   113.6  */
   113.7 +#include "../../SDL_internal.h"
   113.8 +
   113.9 +#if SDL_VIDEO_DRIVER_PSP
  113.10  
  113.11  /* Being a null driver, there's no event stream. We just define stubs for
  113.12     most of the API. */
  113.13 @@ -282,3 +285,6 @@
  113.14  
  113.15  /* end of SDL_pspevents.c ... */
  113.16  
  113.17 +#endif /* SDL_VIDEO_DRIVER_PSP */
  113.18 +
  113.19 +/* vi: set ts=4 sw=4 expandtab: */
   114.1 --- a/src/video/psp/SDL_pspgl.c	Sat Jan 24 23:58:07 2015 -0400
   114.2 +++ b/src/video/psp/SDL_pspgl.c	Mon Apr 06 15:26:37 2015 -0300
   114.3 @@ -18,6 +18,9 @@
   114.4       misrepresented as being the original software.
   114.5    3. This notice may not be removed or altered from any source distribution.
   114.6  */
   114.7 +#include "../../SDL_internal.h"
   114.8 +
   114.9 +#if SDL_VIDEO_DRIVER_PSP
  114.10  
  114.11  #include <stdlib.h>
  114.12  #include <string.h>
  114.13 @@ -203,3 +206,6 @@
  114.14      return;
  114.15  }
  114.16  
  114.17 +#endif /* SDL_VIDEO_DRIVER_PSP */
  114.18 +
  114.19 +/* vi: set ts=4 sw=4 expandtab: */
   115.1 --- a/src/video/psp/SDL_pspmouse.c	Sat Jan 24 23:58:07 2015 -0400
   115.2 +++ b/src/video/psp/SDL_pspmouse.c	Mon Apr 06 15:26:37 2015 -0300
   115.3 @@ -18,7 +18,9 @@
   115.4       misrepresented as being the original software.
   115.5    3. This notice may not be removed or altered from any source distribution.
   115.6  */
   115.7 +#include "../../SDL_internal.h"
   115.8  
   115.9 +#if SDL_VIDEO_DRIVER_PSP
  115.10  
  115.11  #include <stdio.h>
  115.12  
  115.13 @@ -33,3 +35,7 @@
  115.14  struct WMcursor {
  115.15      int unused;
  115.16  };
  115.17 +
  115.18 +#endif /* SDL_VIDEO_DRIVER_PSP */
  115.19 +
  115.20 +/* vi: set ts=4 sw=4 expandtab: */
   116.1 --- a/src/video/psp/SDL_pspvideo.c	Sat Jan 24 23:58:07 2015 -0400
   116.2 +++ b/src/video/psp/SDL_pspvideo.c	Mon Apr 06 15:26:37 2015 -0300
   116.3 @@ -66,7 +66,7 @@
   116.4      SDL_GLDriverData *gldata;
   116.5      int status;
   116.6  
   116.7 -    /* Check if pandora could be initialized */
   116.8 +    /* Check if PSP could be initialized */
   116.9      status = PSP_Available();
  116.10      if (status == 0) {
  116.11          /* PSP could not be used */
  116.12 @@ -80,7 +80,7 @@
  116.13          return NULL;
  116.14      }
  116.15  
  116.16 -    /* Initialize internal Pandora specific data */
  116.17 +    /* Initialize internal PSP specific data */
  116.18      phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
  116.19      if (phdata == NULL) {
  116.20          SDL_OutOfMemory();
   117.1 --- a/src/video/psp/SDL_pspvideo.h	Sat Jan 24 23:58:07 2015 -0400
   117.2 +++ b/src/video/psp/SDL_pspvideo.h	Mon Apr 06 15:26:37 2015 -0300
   117.3 @@ -19,8 +19,8 @@
   117.4    3. This notice may not be removed or altered from any source distribution.
   117.5  */
   117.6  
   117.7 -#ifndef __SDL_PANDORA_H__
   117.8 -#define __SDL_PANDORA_H__
   117.9 +#ifndef _SDL_pspvideo_h
  117.10 +#define _SDL_pspvideo_h
  117.11  
  117.12  #include <GLES/egl.h>
  117.13  
  117.14 @@ -97,6 +97,6 @@
  117.15  void PSP_HideScreenKeyboard(_THIS, SDL_Window *window);
  117.16  SDL_bool PSP_IsScreenKeyboardShown(_THIS, SDL_Window *window);
  117.17  
  117.18 -#endif /* __SDL_PANDORA_H__ */
  117.19 +#endif /* _SDL_pspvideo_h */
  117.20  
  117.21  /* vi: set ts=4 sw=4 expandtab: */
   118.1 --- a/src/video/wayland/SDL_waylandwindow.c	Sat Jan 24 23:58:07 2015 -0400
   118.2 +++ b/src/video/wayland/SDL_waylandwindow.c	Mon Apr 06 15:26:37 2015 -0300
   118.3 @@ -29,6 +29,7 @@
   118.4  #include "SDL_waylandwindow.h"
   118.5  #include "SDL_waylandvideo.h"
   118.6  #include "SDL_waylandtouch.h"
   118.7 +#include "SDL_waylanddyn.h"
   118.8  
   118.9  static void
  118.10  handle_ping(void *data, struct wl_shell_surface *shell_surface,
   119.1 --- a/src/video/windows/SDL_windowsevents.c	Sat Jan 24 23:58:07 2015 -0400
   119.2 +++ b/src/video/windows/SDL_windowsevents.c	Mon Apr 06 15:26:37 2015 -0300
   119.3 @@ -559,10 +559,11 @@
   119.4  
   119.5              GetKeyboardState(keyboardState);
   119.6              if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) {
   119.7 -                WORD repetition;
   119.8 -                for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
   119.9 -                    WIN_ConvertUTF32toUTF8(utf32, text);
  119.10 -                    SDL_SendKeyboardText(text);
  119.11 +                if (WIN_ConvertUTF32toUTF8(utf32, text)) {
  119.12 +                    WORD repetition;
  119.13 +                    for (repetition = lParam & 0xffff; repetition > 0; repetition--) {
  119.14 +                        SDL_SendKeyboardText(text);
  119.15 +                    }
  119.16                  }
  119.17              }
  119.18          }
   120.1 --- a/src/video/windows/SDL_windowsopengl.c	Sat Jan 24 23:58:07 2015 -0400
   120.2 +++ b/src/video/windows/SDL_windowsopengl.c	Mon Apr 06 15:26:37 2015 -0300
   120.3 @@ -74,6 +74,13 @@
   120.4  #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB                0x20A9
   120.5  #endif
   120.6  
   120.7 +#ifndef WGL_ARB_context_flush_control
   120.8 +#define WGL_ARB_context_flush_control
   120.9 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB   0x2097
  120.10 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB           0x0000
  120.11 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB          0x2098
  120.12 +#endif
  120.13 +
  120.14  typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
  120.15                                                              HGLRC
  120.16                                                              hShareContext,
  120.17 @@ -405,6 +412,11 @@
  120.18          _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE;
  120.19      }
  120.20  
  120.21 +    /* Check for GLX_ARB_context_flush_control */
  120.22 +    if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
  120.23 +        _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
  120.24 +    }
  120.25 +
  120.26      _this->gl_data->wglMakeCurrent(hdc, NULL);
  120.27      _this->gl_data->wglDeleteContext(hglrc);
  120.28      ReleaseDC(hwnd, hdc);
  120.29 @@ -648,8 +660,8 @@
  120.30              SDL_SetError("GL 3.x is not supported");
  120.31              context = temp_context;
  120.32          } else {
  120.33 -        /* max 8 attributes plus terminator */
  120.34 -            int attribs[9] = {
  120.35 +        /* max 10 attributes plus terminator */
  120.36 +            int attribs[11] = {
  120.37                  WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version,
  120.38                  WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version,
  120.39                  0
  120.40 @@ -668,6 +680,14 @@
  120.41          attribs[iattr++] = _this->gl_config.flags;
  120.42          }
  120.43  
  120.44 +        /* only set if wgl extension is available */
  120.45 +        if( _this->gl_data->HAS_WGL_ARB_context_flush_control ) {
  120.46 +            attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
  120.47 +            attribs[iattr++] = _this->gl_config.release_behavior ?
  120.48 +                                    WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
  120.49 +                                    WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
  120.50 +        }
  120.51 +
  120.52          attribs[iattr++] = 0;
  120.53  
  120.54              /* Create the GL 3.x context */
   121.1 --- a/src/video/windows/SDL_windowsopengl.h	Sat Jan 24 23:58:07 2015 -0400
   121.2 +++ b/src/video/windows/SDL_windowsopengl.h	Mon Apr 06 15:26:37 2015 -0300
   121.3 @@ -30,6 +30,7 @@
   121.4      SDL_bool HAS_WGL_ARB_pixel_format;
   121.5      SDL_bool HAS_WGL_EXT_swap_control_tear;
   121.6      SDL_bool HAS_WGL_EXT_create_context_es2_profile;
   121.7 +    SDL_bool HAS_WGL_ARB_context_flush_control;
   121.8  
   121.9      void *(WINAPI * wglGetProcAddress) (const char *proc);
  121.10        HGLRC(WINAPI * wglCreateContext) (HDC hdc);
   122.1 --- a/src/video/windows/SDL_windowswindow.c	Sat Jan 24 23:58:07 2015 -0400
   122.2 +++ b/src/video/windows/SDL_windowswindow.c	Mon Apr 06 15:26:37 2015 -0300
   122.3 @@ -643,10 +643,11 @@
   122.4  SDL_bool
   122.5  WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
   122.6  {
   122.7 -    HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
   122.8 +    const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
   122.9      if (info->version.major <= SDL_MAJOR_VERSION) {
  122.10          info->subsystem = SDL_SYSWM_WINDOWS;
  122.11 -        info->info.win.window = hwnd;
  122.12 +        info->info.win.window = data->hwnd;
  122.13 +        info->info.win.hdc = data->hdc;
  122.14          return SDL_TRUE;
  122.15      } else {
  122.16          SDL_SetError("Application not compiled with SDL %d.%d\n",
   123.1 --- a/src/video/winrt/SDL_winrtopengles.cpp	Sat Jan 24 23:58:07 2015 -0400
   123.2 +++ b/src/video/winrt/SDL_winrtopengles.cpp	Mon Apr 06 15:26:37 2015 -0300
   123.3 @@ -36,10 +36,17 @@
   123.4  
   123.5  /* ANGLE/WinRT constants */
   123.6  static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0;
   123.7 -#define EGL_PLATFORM_ANGLE_ANGLE                0x3201
   123.8 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3202
   123.9 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE   0x3203
  123.10 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3205
  123.11 +#define EGL_PLATFORM_ANGLE_ANGLE                        0x3202
  123.12 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE                   0x3203
  123.13 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE      0x3204
  123.14 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE      0x3205
  123.15 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE             0x3208
  123.16 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE            0x3209
  123.17 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE       0x320B
  123.18 +#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE  0x320F
  123.19 +
  123.20 +#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER   0x320B
  123.21 +
  123.22  
  123.23  /*
  123.24   * SDL/EGL top-level implementation
  123.25 @@ -80,11 +87,40 @@
  123.26          Microsoft::WRL::ComPtr<IUnknown> cpp_display = video_data->winrtEglWindow;
  123.27          _this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display);
  123.28          if (!_this->egl_data->egl_display) {
  123.29 -            return SDL_SetError("Could not get EGL display");
  123.30 +            return SDL_SetError("Could not get Windows 8.0 EGL display");
  123.31 +        }
  123.32 +
  123.33 +        if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
  123.34 +            return SDL_SetError("Could not initialize Windows 8.0 EGL");
  123.35          }
  123.36      } else {
  123.37 -        const EGLint displayAttributes[] = {
  123.38 +        /* Declare some ANGLE/EGL initialization property-sets, as suggested by
  123.39 +         * MSOpenTech's ANGLE-for-WinRT template apps:
  123.40 +         */
  123.41 +        const EGLint defaultDisplayAttributes[] =
  123.42 +        {
  123.43              EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  123.44 +            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  123.45 +            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  123.46 +            EGL_NONE,
  123.47 +        };
  123.48 +
  123.49 +        const EGLint fl9_3DisplayAttributes[] =
  123.50 +        {
  123.51 +            EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  123.52 +            EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
  123.53 +            EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
  123.54 +            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  123.55 +            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  123.56 +            EGL_NONE,
  123.57 +        };
  123.58 +
  123.59 +        const EGLint warpDisplayAttributes[] =
  123.60 +        {
  123.61 +            EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  123.62 +            EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
  123.63 +            EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  123.64 +            EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  123.65              EGL_NONE,
  123.66          };
  123.67  
  123.68 @@ -99,14 +135,41 @@
  123.69              return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)");
  123.70          }
  123.71  
  123.72 -        _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes);
  123.73 +#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
  123.74 +        /* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not
  123.75 +         * supported on WinPhone 8.x.
  123.76 +         */
  123.77 +        _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
  123.78          if (!_this->egl_data->egl_display) {
  123.79 -            return SDL_SetError("Could not get EGL display");
  123.80 +            return SDL_SetError("Could not get 10_0+ EGL display");
  123.81          }
  123.82 -    }
  123.83  
  123.84 -    if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
  123.85 -        return SDL_SetError("Could not initialize EGL");
  123.86 +        if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE)
  123.87 +#endif
  123.88 +        {
  123.89 +            /* Try initializing EGL at D3D11 Feature Level 9_3, in case the
  123.90 +             * 10_0 init fails, or we're on Windows Phone (which only supports
  123.91 +             * 9_3).
  123.92 +             */
  123.93 +            _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
  123.94 +            if (!_this->egl_data->egl_display) {
  123.95 +                return SDL_SetError("Could not get 9_3 EGL display");
  123.96 +            }
  123.97 +
  123.98 +            if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
  123.99 +                /* Try initializing EGL at D3D11 Feature Level 11_0 on WARP
 123.100 +                 * (a Windows-provided, software rasterizer) if all else fails.
 123.101 +                 */
 123.102 +                _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
 123.103 +                if (!_this->egl_data->egl_display) {
 123.104 +                    return SDL_SetError("Could not get WARP EGL display");
 123.105 +                }
 123.106 +
 123.107 +                if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
 123.108 +                    return SDL_SetError("Could not initialize WinRT 8.x+ EGL");
 123.109 +                }
 123.110 +            }
 123.111 +        }
 123.112      }
 123.113  
 123.114      return 0;
   124.1 --- a/src/video/x11/SDL_x11events.c	Sat Jan 24 23:58:07 2015 -0400
   124.2 +++ b/src/video/x11/SDL_x11events.c	Mon Apr 06 15:26:37 2015 -0300
   124.3 @@ -677,8 +677,17 @@
   124.4                  data->window == SDL_GetKeyboardFocus()) {
   124.5                  ReconcileKeyboardState(_this, data);
   124.6              }
   124.7 -            data->pending_focus = PENDING_FOCUS_IN;
   124.8 -            data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME;
   124.9 +            if (!videodata->last_mode_change_deadline) /* no recent mode changes */
  124.10 +            {
  124.11 +                data->pending_focus = PENDING_FOCUS_NONE;
  124.12 +                data->pending_focus_time = 0;
  124.13 +                X11_DispatchFocusIn(data);
  124.14 +            }
  124.15 +            else
  124.16 +            {
  124.17 +                data->pending_focus = PENDING_FOCUS_IN;
  124.18 +                data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
  124.19 +            }
  124.20          }
  124.21          break;
  124.22  
  124.23 @@ -701,8 +710,17 @@
  124.24  #ifdef DEBUG_XEVENTS
  124.25              printf("window %p: FocusOut!\n", data);
  124.26  #endif
  124.27 -            data->pending_focus = PENDING_FOCUS_OUT;
  124.28 -            data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME;
  124.29 +            if (!videodata->last_mode_change_deadline) /* no recent mode changes */
  124.30 +            {
  124.31 +                data->pending_focus = PENDING_FOCUS_NONE;
  124.32 +                data->pending_focus_time = 0;
  124.33 +                X11_DispatchFocusOut(data);
  124.34 +            }
  124.35 +            else
  124.36 +            {
  124.37 +                data->pending_focus = PENDING_FOCUS_OUT;
  124.38 +                data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
  124.39 +            }
  124.40          }
  124.41          break;
  124.42  
  124.43 @@ -1090,15 +1108,25 @@
  124.44                     without ever mapping / unmapping them, so we handle that here,
  124.45                     because they use the NETWM protocol to notify us of changes.
  124.46                   */
  124.47 -                Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
  124.48 -				if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN ||
  124.49 -					(flags^data->window->flags) & SDL_WINDOW_FULLSCREEN ) {
  124.50 -                    if (flags & SDL_WINDOW_HIDDEN) {
  124.51 -                        X11_DispatchUnmapNotify(data);
  124.52 -                    } else {
  124.53 -                        X11_DispatchMapNotify(data);
  124.54 +                const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window);
  124.55 +                const Uint32 changed = flags ^ data->window->flags;
  124.56 +
  124.57 +                if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) {
  124.58 +                     if (flags & SDL_WINDOW_HIDDEN) {
  124.59 +                         X11_DispatchUnmapNotify(data);
  124.60 +                     } else {
  124.61 +                         X11_DispatchMapNotify(data);
  124.62                      }
  124.63                  }
  124.64 +
  124.65 +                if (changed & SDL_WINDOW_MAXIMIZED) {
  124.66 +                    if (flags & SDL_WINDOW_MAXIMIZED) {
  124.67 +                        SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
  124.68 +                    } else {
  124.69 +                        SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0);
  124.70 +                    }
  124.71 +                 }
  124.72 +
  124.73              }
  124.74          }
  124.75          break;
  124.76 @@ -1283,9 +1311,15 @@
  124.77  {
  124.78      SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
  124.79  
  124.80 +    if (data->last_mode_change_deadline) {
  124.81 +        if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) {
  124.82 +            data->last_mode_change_deadline = 0;  /* assume we're done. */
  124.83 +        }
  124.84 +    }
  124.85 +
  124.86      /* Update activity every 30 seconds to prevent screensaver */
  124.87      if (_this->suspend_screensaver) {
  124.88 -        Uint32 now = SDL_GetTicks();
  124.89 +        const Uint32 now = SDL_GetTicks();
  124.90          if (!data->screensaver_activity ||
  124.91              SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) {
  124.92              X11_XResetScreenSaver(data->display);
   125.1 --- a/src/video/x11/SDL_x11messagebox.c	Sat Jan 24 23:58:07 2015 -0400
   125.2 +++ b/src/video/x11/SDL_x11messagebox.c	Mon Apr 06 15:26:37 2015 -0300
   125.3 @@ -31,8 +31,8 @@
   125.4  #include <locale.h>
   125.5  
   125.6  
   125.7 -#define SDL_FORK_MESSAGEBOX 0
   125.8 -#define SDL_SET_LOCALE      0
   125.9 +#define SDL_FORK_MESSAGEBOX 1
  125.10 +#define SDL_SET_LOCALE      1
  125.11  
  125.12  #if SDL_FORK_MESSAGEBOX
  125.13  #include <sys/types.h>
  125.14 @@ -366,6 +366,7 @@
  125.15      int x, y;
  125.16      XSizeHints *sizehints;
  125.17      XSetWindowAttributes wnd_attr;
  125.18 +    Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG;
  125.19      Display *display = data->display;
  125.20      SDL_WindowData *windowdata = NULL;
  125.21      const SDL_MessageBoxData *messageboxdata = data->messageboxdata;
  125.22 @@ -401,6 +402,13 @@
  125.23  
  125.24      X11_XStoreName( display, data->window, messageboxdata->title );
  125.25  
  125.26 +    /* Let the window manager know this is a dialog box */
  125.27 +    _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
  125.28 +    _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False);
  125.29 +    X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
  125.30 +                    PropModeReplace,
  125.31 +                    (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1);
  125.32 +
  125.33      /* Allow the window to be deleted by the window manager */
  125.34      data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False );
  125.35      data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False );
  125.36 @@ -710,9 +718,6 @@
  125.37      int fds[2];
  125.38      int status = 0;
  125.39  
  125.40 -    /* Need to flush here in case someone has turned grab off and it hasn't gone through yet, etc. */
  125.41 -    X11_XFlush(data->display);
  125.42 -
  125.43      if (pipe(fds) == -1) {
  125.44          return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */
  125.45      }
   126.1 --- a/src/video/x11/SDL_x11modes.c	Sat Jan 24 23:58:07 2015 -0400
   126.2 +++ b/src/video/x11/SDL_x11modes.c	Mon Apr 06 15:26:37 2015 -0300
   126.3 @@ -24,6 +24,7 @@
   126.4  
   126.5  #include "SDL_hints.h"
   126.6  #include "SDL_x11video.h"
   126.7 +#include "SDL_timer.h"
   126.8  #include "edid.h"
   126.9  
  126.10  /* #define X11MODES_DEBUG */
  126.11 @@ -813,10 +814,13 @@
  126.12  int
  126.13  X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode)
  126.14  {
  126.15 -    Display *display = ((SDL_VideoData *) _this->driverdata)->display;
  126.16 +    SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata;
  126.17 +    Display *display = viddata->display;
  126.18      SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata;
  126.19      SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata;
  126.20  
  126.21 +    viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2);
  126.22 +
  126.23  #if SDL_VIDEO_DRIVER_X11_XRANDR
  126.24      if (data->use_xrandr) {
  126.25          XRRScreenResources *res;
   127.1 --- a/src/video/x11/SDL_x11opengl.c	Sat Jan 24 23:58:07 2015 -0400
   127.2 +++ b/src/video/x11/SDL_x11opengl.c	Mon Apr 06 15:26:37 2015 -0300
   127.3 @@ -122,6 +122,13 @@
   127.4  #define GLX_LATE_SWAPS_TEAR_EXT 0x20F3
   127.5  #endif
   127.6  
   127.7 +#ifndef GLX_ARB_context_flush_control
   127.8 +#define GLX_ARB_context_flush_control
   127.9 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB   0x2097
  127.10 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB           0x0000
  127.11 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB          0x2098
  127.12 +#endif
  127.13 +
  127.14  #define OPENGL_REQUIRES_DLOPEN
  127.15  #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
  127.16  #include <dlfcn.h>
  127.17 @@ -279,14 +286,14 @@
  127.18      const char *start;
  127.19      const char *where, *terminator;
  127.20  
  127.21 +    if (!extensions)
  127.22 +        return SDL_FALSE;
  127.23 +
  127.24      /* Extension names should not have spaces. */
  127.25      where = SDL_strchr(extension, ' ');
  127.26      if (where || *extension == '\0')
  127.27          return SDL_FALSE;
  127.28  
  127.29 -    if (!extensions)
  127.30 -        return SDL_FALSE;
  127.31 -
  127.32      /* It takes a bit of care to be fool-proof about parsing the
  127.33       * OpenGL extensions string. Don't be fooled by sub-strings,
  127.34       * etc. */
  127.35 @@ -312,32 +319,10 @@
  127.36  X11_GL_InitExtensions(_THIS)
  127.37  {
  127.38      Display *display = ((SDL_VideoData *) _this->driverdata)->display;
  127.39 -    int screen = DefaultScreen(display);
  127.40 -    XVisualInfo *vinfo;
  127.41 -    XSetWindowAttributes xattr;
  127.42 -    Window w;
  127.43 -    GLXContext context;
  127.44 +    const int screen = DefaultScreen(display);
  127.45      const char *(*glXQueryExtensionsStringFunc) (Display *, int);
  127.46      const char *extensions;
  127.47  
  127.48 -    vinfo = X11_GL_GetVisual(_this, display, screen);
  127.49 -    if (!vinfo) {
  127.50 -        return;
  127.51 -    }
  127.52 -    xattr.background_pixel = 0;
  127.53 -    xattr.border_pixel = 0;
  127.54 -    xattr.colormap =
  127.55 -        X11_XCreateColormap(display, RootWindow(display, screen), vinfo->visual,
  127.56 -                        AllocNone);
  127.57 -    w = X11_XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0,
  127.58 -                      vinfo->depth, InputOutput, vinfo->visual,
  127.59 -                      (CWBackPixel | CWBorderPixel | CWColormap), &xattr);
  127.60 -    context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
  127.61 -    if (context) {
  127.62 -        _this->gl_data->glXMakeCurrent(display, w, context);
  127.63 -    }
  127.64 -    X11_XFree(vinfo);
  127.65 -
  127.66      glXQueryExtensionsStringFunc =
  127.67          (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this,
  127.68                                                                  "glXQueryExtensionsString");
  127.69 @@ -373,6 +358,16 @@
  127.70              (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI");
  127.71      }
  127.72  
  127.73 +    /* Check for GLX_ARB_create_context */
  127.74 +    if (HasExtension("GLX_ARB_create_context", extensions)) {
  127.75 +        _this->gl_data->glXCreateContextAttribsARB =
  127.76 +            (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *))
  127.77 +                X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB");
  127.78 +        _this->gl_data->glXChooseFBConfig =
  127.79 +            (GLXFBConfig *(*)(Display *, int, const int *, int *))
  127.80 +                X11_GL_GetProcAddress(_this, "glXChooseFBConfig");
  127.81 +    }
  127.82 +
  127.83      /* Check for GLX_EXT_visual_rating */
  127.84      if (HasExtension("GLX_EXT_visual_rating", extensions)) {
  127.85          _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE;
  127.86 @@ -388,18 +383,16 @@
  127.87          _this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE;
  127.88      }
  127.89  
  127.90 -    if (context) {
  127.91 -        _this->gl_data->glXMakeCurrent(display, None, NULL);
  127.92 -        _this->gl_data->glXDestroyContext(display, context);
  127.93 +    /* Check for GLX_ARB_context_flush_control */
  127.94 +    if (HasExtension("GLX_ARB_context_flush_control", extensions)) {
  127.95 +        _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE;
  127.96      }
  127.97 -    X11_XDestroyWindow(display, w);
  127.98 -    X11_PumpEvents(_this);
  127.99  }
 127.100  
 127.101  /* glXChooseVisual and glXChooseFBConfig have some small differences in
 127.102   * the attribute encoding, it can be chosen with the for_FBConfig parameter.
 127.103   */
 127.104 -int
 127.105 +static int
 127.106  X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig)
 127.107  {
 127.108      int i = 0;
 127.109 @@ -481,9 +474,7 @@
 127.110  
 127.111      if (_this->gl_config.framebuffer_srgb_capable) {
 127.112          attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
 127.113 -        if( for_FBConfig ) {
 127.114 -            attribs[i++] = True;
 127.115 -        }
 127.116 +        attribs[i++] = True;  /* always needed, for_FBConfig or not! */
 127.117      }
 127.118  
 127.119      if (_this->gl_config.accelerated >= 0 &&
 127.120 @@ -576,7 +567,6 @@
 127.121      XVisualInfo v, *vinfo;
 127.122      int n;
 127.123      GLXContext context = NULL, share_context;
 127.124 -    PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL;
 127.125  
 127.126      if (_this->gl_config.share_with_current_context) {
 127.127          share_context = (GLXContext)SDL_GL_GetCurrentContext();
 127.128 @@ -601,78 +591,61 @@
 127.129              context =
 127.130                  _this->gl_data->glXCreateContext(display, vinfo, share_context, True);
 127.131          } else {
 127.132 -            /* If we want a GL 3.0 context or later we need to get a temporary
 127.133 -               context to grab the new context creation function */
 127.134 -            GLXContext temp_context =
 127.135 -                _this->gl_data->glXCreateContext(display, vinfo, NULL, True);
 127.136 -            if (temp_context) {
 127.137 -                /* max 8 attributes plus terminator */
 127.138 -                int attribs[9] = {
 127.139 -                    GLX_CONTEXT_MAJOR_VERSION_ARB,
 127.140 -                    _this->gl_config.major_version,
 127.141 -                    GLX_CONTEXT_MINOR_VERSION_ARB,
 127.142 -                    _this->gl_config.minor_version,
 127.143 -                    0
 127.144 -                };
 127.145 -                int iattr = 4;
 127.146 +            /* max 10 attributes plus terminator */
 127.147 +            int attribs[11] = {
 127.148 +                GLX_CONTEXT_MAJOR_VERSION_ARB,
 127.149 +                _this->gl_config.major_version,
 127.150 +                GLX_CONTEXT_MINOR_VERSION_ARB,
 127.151 +                _this->gl_config.minor_version,
 127.152 +                0
 127.153 +            };
 127.154 +            int iattr = 4;
 127.155  
 127.156 -                /* SDL profile bits match GLX profile bits */
 127.157 -                if( _this->gl_config.profile_mask != 0 ) {
 127.158 -                    attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
 127.159 -                    attribs[iattr++] = _this->gl_config.profile_mask;
 127.160 -                }
 127.161 +            /* SDL profile bits match GLX profile bits */
 127.162 +            if( _this->gl_config.profile_mask != 0 ) {
 127.163 +                attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB;
 127.164 +                attribs[iattr++] = _this->gl_config.profile_mask;
 127.165 +            }
 127.166  
 127.167 -                /* SDL flags match GLX flags */
 127.168 -                if( _this->gl_config.flags != 0 ) {
 127.169 -                    attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
 127.170 -                    attribs[iattr++] = _this->gl_config.flags;
 127.171 -                }
 127.172 +            /* SDL flags match GLX flags */
 127.173 +            if( _this->gl_config.flags != 0 ) {
 127.174 +                attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB;
 127.175 +                attribs[iattr++] = _this->gl_config.flags;
 127.176 +            }
 127.177  
 127.178 -                attribs[iattr++] = 0;
 127.179 +            /* only set if glx extension is available */
 127.180 +            if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) {
 127.181 +                attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB;
 127.182 +                attribs[iattr++] = 
 127.183 +                    _this->gl_config.release_behavior ? 
 127.184 +                    GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : 
 127.185 +                    GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
 127.186 +            }
 127.187  
 127.188 -                /* Get a pointer to the context creation function for GL 3.0 */
 127.189 -                glXCreateContextAttribs =
 127.190 -                    (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
 127.191 -                    glXGetProcAddress((GLubyte *)
 127.192 -                                      "glXCreateContextAttribsARB");
 127.193 -                if (!glXCreateContextAttribs) {
 127.194 -                    SDL_SetError("GL 3.x is not supported");
 127.195 -                    context = temp_context;
 127.196 +            attribs[iattr++] = 0;
 127.197 +
 127.198 +            /* Get a pointer to the context creation function for GL 3.0 */
 127.199 +            if (!_this->gl_data->glXCreateContextAttribsARB) {
 127.200 +                SDL_SetError("OpenGL 3.0 and later are not supported by this system");
 127.201 +            } else {
 127.202 +                int glxAttribs[64];
 127.203 +
 127.204 +                /* Create a GL 3.x context */
 127.205 +                GLXFBConfig *framebuffer_config = NULL;
 127.206 +                int fbcount = 0;
 127.207 +
 127.208 +                X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
 127.209 +
 127.210 +                if (!_this->gl_data->glXChooseFBConfig
 127.211 +                    || !(framebuffer_config =
 127.212 +                        _this->gl_data->glXChooseFBConfig(display,
 127.213 +                                          DefaultScreen(display), glxAttribs,
 127.214 +                                          &fbcount))) {
 127.215 +                    SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable");
 127.216                  } else {
 127.217 -                    int glxAttribs[64];
 127.218 -
 127.219 -                    /* Create a GL 3.x context */
 127.220 -                    GLXFBConfig *framebuffer_config = NULL;
 127.221 -                    int fbcount = 0;
 127.222 -                    GLXFBConfig *(*glXChooseFBConfig) (Display * disp,
 127.223 -                                                       int screen,
 127.224 -                                                       const int *attrib_list,
 127.225 -                                                       int *nelements);
 127.226 -
 127.227 -                    glXChooseFBConfig =
 127.228 -                        (GLXFBConfig *
 127.229 -                         (*)(Display *, int, const int *,
 127.230 -                             int *)) _this->gl_data->
 127.231 -                        glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
 127.232 -
 127.233 -                    X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE);
 127.234 -
 127.235 -                    if (!glXChooseFBConfig
 127.236 -                        || !(framebuffer_config =
 127.237 -                             glXChooseFBConfig(display,
 127.238 -                                               DefaultScreen(display), glxAttribs,
 127.239 -                                               &fbcount))) {
 127.240 -                        SDL_SetError
 127.241 -                            ("No good framebuffers found. GL 3.x disabled");
 127.242 -                        context = temp_context;
 127.243 -                    } else {
 127.244 -                        context =
 127.245 -                            glXCreateContextAttribs(display,
 127.246 +                    context = _this->gl_data->glXCreateContextAttribsARB(display,
 127.247                                                      framebuffer_config[0],
 127.248                                                      share_context, True, attribs);
 127.249 -                        _this->gl_data->glXDestroyContext(display,
 127.250 -                                                          temp_context);
 127.251 -                    }
 127.252                  }
 127.253              }
 127.254          }
   128.1 --- a/src/video/x11/SDL_x11opengl.h	Sat Jan 24 23:58:07 2015 -0400
   128.2 +++ b/src/video/x11/SDL_x11opengl.h	Mon Apr 06 15:26:37 2015 -0300
   128.3 @@ -35,11 +35,14 @@
   128.4      SDL_bool HAS_GLX_EXT_visual_info;
   128.5      SDL_bool HAS_GLX_EXT_swap_control_tear;
   128.6      SDL_bool HAS_GLX_EXT_create_context_es2_profile;
   128.7 +    SDL_bool HAS_GLX_ARB_context_flush_control;
   128.8  
   128.9      Bool (*glXQueryExtension) (Display*,int*,int*);
  128.10      void *(*glXGetProcAddress) (const GLubyte*);
  128.11      XVisualInfo *(*glXChooseVisual) (Display*,int,int*);
  128.12      GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool);
  128.13 +    GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *);
  128.14 +    GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *);
  128.15      void (*glXDestroyContext) (Display*, GLXContext);
  128.16      Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext);
  128.17      void (*glXSwapBuffers) (Display*, GLXDrawable);
   129.1 --- a/src/video/x11/SDL_x11video.h	Sat Jan 24 23:58:07 2015 -0400
   129.2 +++ b/src/video/x11/SDL_x11video.h	Mon Apr 06 15:26:37 2015 -0300
   129.3 @@ -112,6 +112,7 @@
   129.4      SDL_Scancode key_layout[256];
   129.5      SDL_bool selection_waiting;
   129.6  
   129.7 +    Uint32 last_mode_change_deadline;
   129.8  } SDL_VideoData;
   129.9  
  129.10  extern SDL_bool X11_UseDirectColorVisuals(void);
   130.1 --- a/src/video/x11/SDL_x11window.h	Sat Jan 24 23:58:07 2015 -0400
   130.2 +++ b/src/video/x11/SDL_x11window.h	Mon Apr 06 15:26:37 2015 -0300
   130.3 @@ -27,8 +27,7 @@
   130.4     video mode changes and we can respond to them by triggering more mode
   130.5     changes.
   130.6  */
   130.7 -#define PENDING_FOCUS_IN_TIME   200
   130.8 -#define PENDING_FOCUS_OUT_TIME  200
   130.9 +#define PENDING_FOCUS_TIME   200
  130.10  
  130.11  #if SDL_VIDEO_OPENGL_EGL   
  130.12  #include <EGL/egl.h>
   131.1 --- a/test/Makefile.in	Sat Jan 24 23:58:07 2015 -0400
   131.2 +++ b/test/Makefile.in	Mon Apr 06 15:26:37 2015 -0300
   131.3 @@ -38,6 +38,7 @@
   131.4  	testloadso$(EXE) \
   131.5  	testlock$(EXE) \
   131.6  	testmultiaudio$(EXE) \
   131.7 +	testaudiohotplug$(EXE) \
   131.8  	testnative$(EXE) \
   131.9  	testoverlay2$(EXE) \
  131.10  	testplatform$(EXE) \
  131.11 @@ -105,6 +106,9 @@
  131.12  testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
  131.13  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
  131.14  
  131.15 +testaudiohotplug$(EXE): $(srcdir)/testaudiohotplug.c
  131.16 +	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
  131.17 +
  131.18  testatomic$(EXE): $(srcdir)/testatomic.c
  131.19  	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
  131.20  
   132.1 --- a/test/loopwave.c	Sat Jan 24 23:58:07 2015 -0400
   132.2 +++ b/test/loopwave.c	Mon Apr 06 15:26:37 2015 -0300
   132.3 @@ -29,7 +29,6 @@
   132.4  #endif
   132.5  
   132.6  #include "SDL.h"
   132.7 -#include "SDL_audio.h"
   132.8  
   132.9  struct
  132.10  {
   133.1 --- a/test/loopwavequeue.c	Sat Jan 24 23:58:07 2015 -0400
   133.2 +++ b/test/loopwavequeue.c	Mon Apr 06 15:26:37 2015 -0300
   133.3 @@ -15,6 +15,10 @@
   133.4  #include <stdio.h>
   133.5  #include <stdlib.h>
   133.6  
   133.7 +#ifdef __EMSCRIPTEN__
   133.8 +#include <emscripten/emscripten.h>
   133.9 +#endif
  133.10 +
  133.11  #include "SDL.h"
  133.12  
  133.13  #if HAVE_SIGNAL_H
  133.14 @@ -45,10 +49,32 @@
  133.15      done = 1;
  133.16  }
  133.17  
  133.18 +void
  133.19 +loop()
  133.20 +{
  133.21 +#ifdef __EMSCRIPTEN__
  133.22 +    if (done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)) {
  133.23 +        emscripten_cancel_main_loop();
  133.24 +    }
  133.25 +    else
  133.26 +#endif
  133.27 +    {
  133.28 +        /* The device from SDL_OpenAudio() is always device #1. */
  133.29 +        const Uint32 queued = SDL_GetQueuedAudioSize(1);
  133.30 +        SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued);
  133.31 +        if (queued <= 8192) {  /* time to requeue the whole thing? */
  133.32 +            if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) {
  133.33 +                SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen);
  133.34 +            } else {
  133.35 +                SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError());
  133.36 +            }
  133.37 +        }
  133.38 +    }
  133.39 +}
  133.40 +
  133.41  int
  133.42  main(int argc, char *argv[])
  133.43  {
  133.44 -    int i;
  133.45      char filename[4096];
  133.46  
  133.47  	/* Enable standard application logging */
  133.48 @@ -97,25 +123,22 @@
  133.49      /* Let the audio run */
  133.50      SDL_PauseAudio(0);
  133.51  
  133.52 +    done = 0;
  133.53 +
  133.54      /* Note that we stuff the entire audio buffer into the queue in one
  133.55         shot. Most apps would want to feed it a little at a time, as it
  133.56         plays, but we're going for simplicity here. */
  133.57      
  133.58 +#ifdef __EMSCRIPTEN__
  133.59 +    emscripten_set_main_loop(loop, 0, 1);
  133.60 +#else
  133.61      while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING))
  133.62      {
  133.63 -        /* The device from SDL_OpenAudio() is always device #1. */
  133.64 -        const Uint32 queued = SDL_GetQueuedAudioSize(1);
  133.65 -        SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued);
  133.66 -        if (queued <= 8192) {  /* time to requeue the whole thing? */
  133.67 -            if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) {
  133.68 -                SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen);
  133.69 -            } else {
  133.70 -                SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError());
  133.71 -            }
  133.72 -        }
  133.73 +        loop();
  133.74  
  133.75          SDL_Delay(100);  /* let it play for awhile. */
  133.76      }
  133.77 +#endif
  133.78  
  133.79      /* Clean up on signal */
  133.80      SDL_CloseAudio();
   134.1 --- a/test/relative_mode.markdown	Sat Jan 24 23:58:07 2015 -0400
   134.2 +++ b/test/relative_mode.markdown	Mon Apr 06 15:26:37 2015 -0300
   134.3 @@ -37,9 +37,11 @@
   134.4  
   134.5      int main(int argc, char *argv[])
   134.6      {
   134.7 +        SDL_Window *win;
   134.8 +
   134.9          SDL_Init(SDL_INIT_VIDEO);
  134.10  
  134.11 -        SDL_Window *win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0);
  134.12 +        win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0);
  134.13          SDL_SetRelativeMouseMode(SDL_TRUE);
  134.14  
  134.15          while (1)
   135.1 --- a/test/testatomic.c	Sat Jan 24 23:58:07 2015 -0400
   135.2 +++ b/test/testatomic.c	Mon Apr 06 15:26:37 2015 -0300
   135.3 @@ -12,9 +12,6 @@
   135.4  #include <stdio.h>
   135.5  
   135.6  #include "SDL.h"
   135.7 -#include "SDL_atomic.h"
   135.8 -#include "SDL_assert.h"
   135.9 -#include "SDL_cpuinfo.h"
  135.10  
  135.11  /*
  135.12    Absolutely basic tests just to see if we get the expected value
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/test/testaudiohotplug.c	Mon Apr 06 15:26:37 2015 -0300
   136.3 @@ -0,0 +1,183 @@
   136.4 +/*
   136.5 +  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
   136.6 +
   136.7 +  This software is provided 'as-is', without any express or implied
   136.8 +  warranty.  In no event will the authors be held liable for any damages
   136.9 +  arising from the use of this software.
  136.10 +
  136.11 +  Permission is granted to anyone to use this software for any purpose,
  136.12 +  including commercial applications, and to alter it and redistribute it
  136.13 +  freely.
  136.14 +*/
  136.15 +
  136.16 +/* Program to test hotplugging of audio devices */
  136.17 +
  136.18 +#include "SDL_config.h"
  136.19 +
  136.20 +#include <stdio.h>
  136.21 +#include <stdlib.h>
  136.22 +
  136.23 +#if HAVE_SIGNAL_H
  136.24 +#include <signal.h>
  136.25 +#endif
  136.26 +
  136.27 +#ifdef __EMSCRIPTEN__
  136.28 +#include <emscripten/emscripten.h>
  136.29 +#endif
  136.30 +
  136.31 +#include "SDL.h"
  136.32 +
  136.33 +static SDL_AudioSpec spec;
  136.34 +static Uint8 *sound = NULL;     /* Pointer to wave data */
  136.35 +static Uint32 soundlen = 0;     /* Length of wave data */
  136.36 +
  136.37 +static int posindex = 0;
  136.38 +static Uint32 positions[64];
  136.39 +
  136.40 +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
  136.41 +static void
  136.42 +quit(int rc)
  136.43 +{
  136.44 +    SDL_Quit();
  136.45 +    exit(rc);
  136.46 +}
  136.47 +
  136.48 +void SDLCALL
  136.49 +fillerup(void *_pos, Uint8 * stream, int len)
  136.50 +{
  136.51 +    Uint32 pos = *((Uint32 *) _pos);
  136.52 +    Uint8 *waveptr;
  136.53 +    int waveleft;
  136.54 +
  136.55 +    /* Set up the pointers */
  136.56 +    waveptr = sound + pos;
  136.57 +    waveleft = soundlen - pos;
  136.58 +
  136.59 +    /* Go! */
  136.60 +    while (waveleft <= len) {
  136.61 +        SDL_memcpy(stream, waveptr, waveleft);
  136.62 +        stream += waveleft;
  136.63 +        len -= waveleft;
  136.64 +        waveptr = sound;
  136.65 +        waveleft = soundlen;
  136.66 +        pos = 0;
  136.67 +    }
  136.68 +    SDL_memcpy(stream, waveptr, len);
  136.69 +    pos += len;
  136.70 +    *((Uint32 *) _pos) = pos;
  136.71 +}
  136.72 +
  136.73 +static int done = 0;
  136.74 +void
  136.75 +poked(int sig)
  136.76 +{
  136.77 +    done = 1;
  136.78 +}
  136.79 +
  136.80 +static void
  136.81 +iteration()
  136.82 +{
  136.83 +    SDL_Event e;
  136.84 +    SDL_AudioDeviceID dev;
  136.85 +    while (SDL_PollEvent(&e)) {
  136.86 +        if (e.type == SDL_QUIT) {
  136.87 +            done = 1;
  136.88 +        } else if (e.type == SDL_AUDIODEVICEADDED) {
  136.89 +            const char *name = SDL_GetAudioDeviceName(e.adevice.which, 0);
  136.90 +            SDL_Log("New %s audio device: %s\n", e.adevice.iscapture ? "capture" : "output", name);
  136.91 +            if (!e.adevice.iscapture) {
  136.92 +                positions[posindex] = 0;
  136.93 +                spec.userdata = &positions[posindex++];
  136.94 +                spec.callback = fillerup;
  136.95 +                dev = SDL_OpenAudioDevice(name, 0, &spec, NULL, 0);
  136.96 +                if (!dev) {
  136.97 +                    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open '%s': %s\n", name, SDL_GetError());
  136.98 +                } else {
  136.99 +                    SDL_Log("Opened '%s' as %u\n", name, (unsigned int) dev);
 136.100 +                    SDL_PauseAudioDevice(dev, 0);
 136.101 +                }
 136.102 +            }
 136.103 +        } else if (e.type == SDL_AUDIODEVICEREMOVED) {
 136.104 +            dev = (SDL_AudioDeviceID) e.adevice.which;
 136.105 +            SDL_Log("%s device %u removed.\n", e.adevice.iscapture ? "capture" : "output", (unsigned int) dev);
 136.106 +            SDL_CloseAudioDevice(dev);
 136.107 +        }
 136.108 +    }
 136.109 +}
 136.110 +
 136.111 +#ifdef __EMSCRIPTEN__
 136.112 +void
 136.113 +loop()
 136.114 +{
 136.115 +    if(done)
 136.116 +        emscripten_cancel_main_loop();
 136.117 +    else
 136.118 +        iteration();
 136.119 +}
 136.120 +#endif
 136.121 +
 136.122 +int
 136.123 +main(int argc, char *argv[])
 136.124 +{
 136.125 +    int i;
 136.126 +    char filename[4096];
 136.127 +
 136.128 +	/* Enable standard application logging */
 136.129 +	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
 136.130 +
 136.131 +    /* Load the SDL library */
 136.132 +    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
 136.133 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
 136.134 +        return (1);
 136.135 +    }
 136.136 +
 136.137 +    /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */
 136.138 +    SDL_MinimizeWindow(SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0));
 136.139 +
 136.140 +    if (argc > 1) {
 136.141 +        SDL_strlcpy(filename, argv[1], sizeof(filename));
 136.142 +    } else {
 136.143 +        SDL_strlcpy(filename, "sample.wav", sizeof(filename));
 136.144 +    }
 136.145 +    /* Load the wave file into memory */
 136.146 +    if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL) {
 136.147 +        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError());
 136.148 +        quit(1);
 136.149 +    }
 136.150 +
 136.151 +#if HAVE_SIGNAL_H
 136.152 +    /* Set the signals */
 136.153 +#ifdef SIGHUP
 136.154 +    signal(SIGHUP, poked);
 136.155 +#endif
 136.156 +    signal(SIGINT, poked);
 136.157 +#ifdef SIGQUIT
 136.158 +    signal(SIGQUIT, poked);
 136.159 +#endif
 136.160 +    signal(SIGTERM, poked);
 136.161 +#endif /* HAVE_SIGNAL_H */
 136.162 +
 136.163 +    /* Show the list of available drivers */
 136.164 +    SDL_Log("Available audio drivers:");
 136.165 +    for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) {
 136.166 +		SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));
 136.167 +    }
 136.168 +
 136.169 +    SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
 136.170 +
 136.171 +#ifdef __EMSCRIPTEN__
 136.172 +    emscripten_set_main_loop(loop, 0, 1);
 136.173 +#else
 136.174 +    while (!done) {
 136.175 +        SDL_Delay(100);
 136.176 +        iteration();
 136.177 +    }
 136.178 +#endif
 136.179 +
 136.180 +    /* Clean up on signal */
 136.181 +    SDL_Quit();
 136.182 +    SDL_FreeWAV(sound);
 136.183 +    return (0);
 136.184 +}
 136.185 +
 136.186 +/* vi: set ts=4 sw=4 expandtab: */
   137.1 --- a/test/testerror.c	Sat Jan 24 23:58:07 2015 -0400
   137.2 +++ b/test/testerror.c	Mon Apr 06 15:26:37 2015 -0300
   137.3 @@ -17,7 +17,6 @@
   137.4  #include <signal.h>
   137.5  
   137.6  #include "SDL.h"
   137.7 -#include "SDL_thread.h"
   137.8  
   137.9  static int alive = 0;
  137.10  
   138.1 --- a/test/testfile.c	Sat Jan 24 23:58:07 2015 -0400
   138.2 +++ b/test/testfile.c	Mon Apr 06 15:26:37 2015 -0300
   138.3 @@ -22,7 +22,6 @@
   138.4  #endif
   138.5  
   138.6  #include "SDL.h"
   138.7 -#include "SDL_endian.h"
   138.8  
   138.9  
  138.10  #include <stdio.h>
   139.1 --- a/test/testgamecontroller.c	Sat Jan 24 23:58:07 2015 -0400
   139.2 +++ b/test/testgamecontroller.c	Mon Apr 06 15:26:37 2015 -0300
   139.3 @@ -163,6 +163,10 @@
   139.4      const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1;
   139.5      char *title = (char *)SDL_malloc(titlelen);
   139.6      SDL_Window *window = NULL;
   139.7 +
   139.8 +    retval = SDL_FALSE;
   139.9 +    done = SDL_FALSE;
  139.10 +
  139.11      if (title) {
  139.12          SDL_snprintf(title, titlelen, "%s%s", basetitle, name);
  139.13      }
  139.14 @@ -219,6 +223,10 @@
  139.15  #endif
  139.16  
  139.17      SDL_DestroyRenderer(screen);
  139.18 +    screen = NULL;
  139.19 +    background = NULL;
  139.20 +    button = NULL;
  139.21 +    axis = NULL;
  139.22      SDL_DestroyWindow(window);
  139.23      return retval;
  139.24  }
   140.1 --- a/test/testhaptic.c	Sat Jan 24 23:58:07 2015 -0400
   140.2 +++ b/test/testhaptic.c	Mon Apr 06 15:26:37 2015 -0300
   140.3 @@ -22,8 +22,6 @@
   140.4  
   140.5  #ifndef SDL_HAPTIC_DISABLED
   140.6  
   140.7 -#include "SDL_haptic.h"
   140.8 -
   140.9  static SDL_Haptic *haptic;
  140.10  
  140.11  
   141.1 --- a/test/testhotplug.c	Sat Jan 24 23:58:07 2015 -0400
   141.2 +++ b/test/testhotplug.c	Mon Apr 06 15:26:37 2015 -0300
   141.3 @@ -17,7 +17,6 @@
   141.4  #include <string.h>
   141.5  
   141.6  #include "SDL.h"
   141.7 -#include "SDL_haptic.h"
   141.8  
   141.9  #if !defined SDL_JOYSTICK_DISABLED && !defined SDL_HAPTIC_DISABLED
  141.10  
   142.1 --- a/test/testjoystick.c	Sat Jan 24 23:58:07 2015 -0400
   142.2 +++ b/test/testjoystick.c	Mon Apr 06 15:26:37 2015 -0300
   142.3 @@ -56,6 +56,12 @@
   142.4  
   142.5          while (SDL_PollEvent(&event)) {
   142.6              switch (event.type) {
   142.7 +
   142.8 +            case SDL_JOYDEVICEREMOVED:
   142.9 +                SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which);
  142.10 +                SDL_Log("Our instance ID is %d\n", (int) SDL_JoystickInstanceID(joystick));
  142.11 +                break;
  142.12 +
  142.13              case SDL_JOYAXISMOTION:
  142.14                  SDL_Log("Joystick %d axis %d value: %d\n",
  142.15                         event.jaxis.which,
  142.16 @@ -177,6 +183,8 @@
  142.17      SDL_Window *window = NULL;
  142.18      const char *name = NULL;
  142.19  
  142.20 +    retval = SDL_FALSE;
  142.21 +    done = SDL_FALSE;
  142.22  
  142.23      /* Create a window to display joystick axis position */
  142.24      window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED,
  142.25 @@ -217,6 +225,7 @@
  142.26  #endif
  142.27  
  142.28      SDL_DestroyRenderer(screen);
  142.29 +    screen = NULL;
  142.30      SDL_DestroyWindow(window);
  142.31      return retval;
  142.32  }
   143.1 --- a/test/testlock.c	Sat Jan 24 23:58:07 2015 -0400
   143.2 +++ b/test/testlock.c	Mon Apr 06 15:26:37 2015 -0300
   143.3 @@ -19,8 +19,6 @@
   143.4  #include <stdlib.h> /* for atexit() */
   143.5  
   143.6  #include "SDL.h"
   143.7 -#include "SDL_mutex.h"
   143.8 -#include "SDL_thread.h"
   143.9  
  143.10  static SDL_mutex *mutex = NULL;
  143.11  static SDL_threadID mainthread;
   144.1 --- a/test/testmessage.c	Sat Jan 24 23:58:07 2015 -0400
   144.2 +++ b/test/testmessage.c	Mon Apr 06 15:26:37 2015 -0300
   144.3 @@ -17,7 +17,6 @@
   144.4  #include <signal.h>
   144.5  
   144.6  #include "SDL.h"
   144.7 -#include "SDL_thread.h"
   144.8  
   144.9  /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
  144.10  static void
   145.1 --- a/test/testplatform.c	Sat Jan 24 23:58:07 2015 -0400
   145.2 +++ b/test/testplatform.c	Mon Apr 06 15:26:37 2015 -0300
   145.3 @@ -13,9 +13,6 @@
   145.4  #include <stdio.h>
   145.5  
   145.6  #include "SDL.h"
   145.7 -#include "SDL_endian.h"
   145.8 -#include "SDL_cpuinfo.h"
   145.9 -#include "SDL_assert.h"
  145.10  
  145.11  /*
  145.12   * Watcom C flags these as Warning 201: "Unreachable code" if you just
  145.13 @@ -170,7 +167,7 @@
  145.14  #endif
  145.15  
  145.16      {
  145.17 -        const SDL_assert_data *item = SDL_GetAssertionReport();
  145.18 +        const SDL_AssertData *item = SDL_GetAssertionReport();
  145.19          while (item) {
  145.20              SDL_Log("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n",
  145.21                  item->condition, item->function, item->filename,
   146.1 --- a/test/testrelative.c	Sat Jan 24 23:58:07 2015 -0400
   146.2 +++ b/test/testrelative.c	Mon Apr 06 15:26:37 2015 -0300
   146.3 @@ -49,12 +49,20 @@
   146.4          }
   146.5      }
   146.6      for (i = 0; i < state->num_windows; ++i) {
   146.7 +        SDL_Rect viewport;
   146.8          SDL_Renderer *renderer = state->renderers[i];
   146.9          if (state->windows[i] == NULL)
  146.10              continue;
  146.11          SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
  146.12          SDL_RenderClear(renderer);
  146.13  
  146.14 +        /* Wrap the cursor rectangle at the screen edges to keep it visible */
  146.15 +        SDL_RenderGetViewport(renderer, &viewport);
  146.16 +        if (rect.x < viewport.x) rect.x += viewport.w;
  146.17 +        if (rect.y < viewport.y) rect.y += viewport.h;
  146.18 +        if (rect.x > viewport.x + viewport.w) rect.x -= viewport.w;
  146.19 +        if (rect.y > viewport.y + viewport.h) rect.y -= viewport.h;
  146.20 +
  146.21          DrawRects(renderer, &rect);
  146.22  
  146.23          SDL_RenderPresent(renderer);
   147.1 --- a/test/testrumble.c	Sat Jan 24 23:58:07 2015 -0400
   147.2 +++ b/test/testrumble.c	Mon Apr 06 15:26:37 2015 -0300
   147.3 @@ -33,8 +33,6 @@
   147.4  
   147.5  #ifndef SDL_HAPTIC_DISABLED
   147.6  
   147.7 -#include "SDL_haptic.h"
   147.8 -
   147.9  static SDL_Haptic *haptic;
  147.10  
  147.11  
   148.1 --- a/test/testsem.c	Sat Jan 24 23:58:07 2015 -0400
   148.2 +++ b/test/testsem.c	Mon Apr 06 15:26:37 2015 -0300
   148.3 @@ -17,7 +17,6 @@
   148.4  #include <signal.h>
   148.5  
   148.6  #include "SDL.h"
   148.7 -#include "SDL_thread.h"
   148.8  
   148.9  #define NUM_THREADS 10
  148.10  
   149.1 --- a/test/testthread.c	Sat Jan 24 23:58:07 2015 -0400
   149.2 +++ b/test/testthread.c	Mon Apr 06 15:26:37 2015 -0300
   149.3 @@ -17,7 +17,6 @@
   149.4  #include <signal.h>
   149.5  
   149.6  #include "SDL.h"
   149.7 -#include "SDL_thread.h"
   149.8  
   149.9  static SDL_TLSID tls;
  149.10  static int alive = 0;
   150.1 --- a/test/torturethread.c	Sat Jan 24 23:58:07 2015 -0400
   150.2 +++ b/test/torturethread.c	Mon Apr 06 15:26:37 2015 -0300
   150.3 @@ -18,7 +18,6 @@
   150.4  #include <string.h>
   150.5  
   150.6  #include "SDL.h"
   150.7 -#include "SDL_thread.h"
   150.8  
   150.9  #define NUMTHREADS 10
  150.10