From 1419eb12a422591579436e3e0911719b43a2ccdb Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 26 Jan 2015 22:00:29 +0100 Subject: [PATCH 001/142] Fixed bug 2802 - [patch] Fix android build compiling in wrong filesystem implementation Jonas Kulla The configure script didn't differentiate between Linux and Android, unconditionally compiling in the unix implementation of SDL_sysfilesystem.c. I'm probably one of the very few people building SDL for android using classic configure + standalone toolchain, so this has gone undetected all along. --- configure | 15 +++++++++++++-- configure.in | 15 ++++++++++++--- include/SDL_config.h.in | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/configure b/configure index d365902ad..324cfae08 100755 --- a/configure +++ b/configure @@ -23091,11 +23091,22 @@ $as_echo "#define SDL_POWER_ANDROID 1" >>confdefs.h fi # Set up files for the filesystem library if test x$enable_filesystem = xyes; then + case $ARCH in + linux) $as_echo "#define SDL_FILESYSTEM_UNIX 1" >>confdefs.h - SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" - have_filesystem=yes + SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" + have_filesystem=yes + ;; + android) + +$as_echo "#define SDL_FILESYSTEM_ANDROID 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c" + have_filesystem=yes + ;; + esac fi # Set up files for the timer library if test x$enable_timers = xyes; then diff --git a/configure.in b/configure.in index c546abec1..29d38bee9 100644 --- a/configure.in +++ b/configure.in @@ -2971,9 +2971,18 @@ case "$host" in fi # Set up files for the filesystem library if test x$enable_filesystem = xyes; then - AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ]) - SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" - have_filesystem=yes + case $ARCH in + linux) + AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" + have_filesystem=yes + ;; + android) + AC_DEFINE(SDL_FILESYSTEM_ANDROID, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c" + have_filesystem=yes + ;; + esac fi # Set up files for the timer library if test x$enable_timers = xyes; then diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 2c50ba406..925bfaa1a 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -349,6 +349,7 @@ #undef SDL_FILESYSTEM_UNIX #undef SDL_FILESYSTEM_WINDOWS #undef SDL_FILESYSTEM_NACL +#undef SDL_FILESYSTEM_ANDROID #undef SDL_FILESYSTEM_EMSCRIPTEN /* Enable assembly routines */ From 581841e8cf433520a037b1c245d70edee7b88e92 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 26 Jan 2015 22:02:53 +0100 Subject: [PATCH 002/142] Updated a README. --- docs/README-porting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README-porting.md b/docs/README-porting.md index d93c65bd3..cf2d3eaca 100644 --- a/docs/README-porting.md +++ b/docs/README-porting.md @@ -15,7 +15,7 @@ There are two basic ways of building SDL at the moment: If you have a GNUish system, then you might try this. Edit configure.in, take a look at the large section labelled: - "Set up the configuration based on the target platform!" + "Set up the configuration based on the host platform!" Add a section for your platform, and then re-run autogen.sh and build! 2. Using an IDE: From f6c04205cc7d694f0e077edab6cbb5f0b1bcf1a6 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 26 Jan 2015 22:12:38 +0100 Subject: [PATCH 003/142] Fixed memory leak in video quit implementation for Android. --- src/video/android/SDL_androidvideo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index ed3d3b323..5e034615b 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -86,6 +86,7 @@ Android_SuspendScreenSaver(_THIS) static void Android_DeleteDevice(SDL_VideoDevice * device) { + SDL_free(device->driverdata); SDL_free(device); } From cc3e7b2c095f67f822f8b36fd0fd8006e9ae49e9 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 26 Jan 2015 22:27:27 +0100 Subject: [PATCH 004/142] Fixed recently broken configure script for FreeBSD. Found by buildbot. --- configure | 14 +++++++------- configure.in | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 324cfae08..81e6b24b2 100755 --- a/configure +++ b/configure @@ -23092,13 +23092,6 @@ $as_echo "#define SDL_POWER_ANDROID 1" >>confdefs.h # Set up files for the filesystem library if test x$enable_filesystem = xyes; then case $ARCH in - linux) - -$as_echo "#define SDL_FILESYSTEM_UNIX 1" >>confdefs.h - - SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" - have_filesystem=yes - ;; android) $as_echo "#define SDL_FILESYSTEM_ANDROID 1" >>confdefs.h @@ -23106,6 +23099,13 @@ $as_echo "#define SDL_FILESYSTEM_ANDROID 1" >>confdefs.h SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c" have_filesystem=yes ;; + *) + +$as_echo "#define SDL_FILESYSTEM_UNIX 1" >>confdefs.h + + SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" + have_filesystem=yes + ;; esac fi # Set up files for the timer library diff --git a/configure.in b/configure.in index 29d38bee9..a2ad20a67 100644 --- a/configure.in +++ b/configure.in @@ -2972,16 +2972,16 @@ case "$host" in # Set up files for the filesystem library if test x$enable_filesystem = xyes; then case $ARCH in - linux) - AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ]) - SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" - have_filesystem=yes - ;; android) AC_DEFINE(SDL_FILESYSTEM_ANDROID, 1, [ ]) SOURCES="$SOURCES $srcdir/src/filesystem/android/*.c" have_filesystem=yes ;; + *) + AC_DEFINE(SDL_FILESYSTEM_UNIX, 1, [ ]) + SOURCES="$SOURCES $srcdir/src/filesystem/unix/*.c" + have_filesystem=yes + ;; esac fi # Set up files for the timer library From 5f6bd2032124eab312546377fb29ed3e7cfdf48c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 26 Jan 2015 17:46:39 -0500 Subject: [PATCH 005/142] X11: Don't delay delivery of focus events unless we just changed vidmodes. Normally there's a 200 millisecond delay on all focus events in case there was a vidmode change, now we note the last vidmode change and only impose this delay if a change happened extremely recently. Thanks to Epic Games for reporting this issue. --HG-- extra : rebase_source : 9258c16df171c48e13c0df99e8d3b12e7041de63 --- src/video/x11/SDL_x11events.c | 34 +++++++++++++++++++++++++++++----- src/video/x11/SDL_x11modes.c | 6 +++++- src/video/x11/SDL_x11video.h | 1 + src/video/x11/SDL_x11window.h | 3 +-- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 645c7741d..c99b1971b 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -677,8 +677,17 @@ X11_DispatchEvent(_THIS) data->window == SDL_GetKeyboardFocus()) { ReconcileKeyboardState(_this, data); } - data->pending_focus = PENDING_FOCUS_IN; - data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_IN_TIME; + if (!videodata->last_mode_change_deadline) /* no recent mode changes */ + { + data->pending_focus = PENDING_FOCUS_NONE; + data->pending_focus_time = 0; + X11_DispatchFocusIn(data); + } + else + { + data->pending_focus = PENDING_FOCUS_IN; + data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME; + } } break; @@ -701,8 +710,17 @@ X11_DispatchEvent(_THIS) #ifdef DEBUG_XEVENTS printf("window %p: FocusOut!\n", data); #endif - data->pending_focus = PENDING_FOCUS_OUT; - data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_OUT_TIME; + if (!videodata->last_mode_change_deadline) /* no recent mode changes */ + { + data->pending_focus = PENDING_FOCUS_NONE; + data->pending_focus_time = 0; + X11_DispatchFocusOut(data); + } + else + { + data->pending_focus = PENDING_FOCUS_OUT; + data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME; + } } break; @@ -1283,9 +1301,15 @@ X11_PumpEvents(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + if (data->last_mode_change_deadline) { + if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) { + data->last_mode_change_deadline = 0; /* assume we're done. */ + } + } + /* Update activity every 30 seconds to prevent screensaver */ if (_this->suspend_screensaver) { - Uint32 now = SDL_GetTicks(); + const Uint32 now = SDL_GetTicks(); if (!data->screensaver_activity || SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) { X11_XResetScreenSaver(data->display); diff --git a/src/video/x11/SDL_x11modes.c b/src/video/x11/SDL_x11modes.c index 0fc6d2386..5248f7655 100644 --- a/src/video/x11/SDL_x11modes.c +++ b/src/video/x11/SDL_x11modes.c @@ -24,6 +24,7 @@ #include "SDL_hints.h" #include "SDL_x11video.h" +#include "SDL_timer.h" #include "edid.h" /* #define X11MODES_DEBUG */ @@ -813,10 +814,13 @@ X11_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display) int X11_SetDisplayMode(_THIS, SDL_VideoDisplay * sdl_display, SDL_DisplayMode * mode) { - Display *display = ((SDL_VideoData *) _this->driverdata)->display; + SDL_VideoData *viddata = (SDL_VideoData *) _this->driverdata; + Display *display = viddata->display; SDL_DisplayData *data = (SDL_DisplayData *) sdl_display->driverdata; SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata; + viddata->last_mode_change_deadline = SDL_GetTicks() + (PENDING_FOCUS_TIME * 2); + #if SDL_VIDEO_DRIVER_X11_XRANDR if (data->use_xrandr) { XRRScreenResources *res; diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index f076ccec1..ed6b14fa4 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -112,6 +112,7 @@ typedef struct SDL_VideoData SDL_Scancode key_layout[256]; SDL_bool selection_waiting; + Uint32 last_mode_change_deadline; } SDL_VideoData; extern SDL_bool X11_UseDirectColorVisuals(void); diff --git a/src/video/x11/SDL_x11window.h b/src/video/x11/SDL_x11window.h index 789d2f7cc..ce3f58439 100644 --- a/src/video/x11/SDL_x11window.h +++ b/src/video/x11/SDL_x11window.h @@ -27,8 +27,7 @@ video mode changes and we can respond to them by triggering more mode changes. */ -#define PENDING_FOCUS_IN_TIME 200 -#define PENDING_FOCUS_OUT_TIME 200 +#define PENDING_FOCUS_TIME 200 #if SDL_VIDEO_OPENGL_EGL #include From af0ac084924ecb91743b46d7692c592cc045dc72 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 29 Jan 2015 13:33:20 -0800 Subject: [PATCH 006/142] Add binding layout for Xbone pad. --- src/joystick/SDL_gamecontrollerdb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index d151e95ef..ddd537139 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -73,6 +73,7 @@ static const char *s_ControllerMappings [] = "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", #endif #if defined(__ANDROID__) "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", From 81aaff41c95e57c3a7b4be52ec15550cf8f77e70 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 29 Jan 2015 13:33:53 -0800 Subject: [PATCH 007/142] Fixed game controller hotplug support for some embedded Linux devices When guessing the device class, it ends up being 0 for devices that have been removed (because the device node no longer exists) --- src/joystick/linux/SDL_sysjoystick.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index 05bf086f2..a66091298 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -142,13 +142,15 @@ IsJoystick(int fd, char *namebuf, const size_t namebuflen, SDL_JoystickGUID *gui #if SDL_USE_LIBUDEV void joystick_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath) { - if (devpath == NULL || !(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { + if (devpath == NULL) { return; } - - switch( udev_type ) - { + + switch (udev_type) { case SDL_UDEV_DEVICEADDED: + if (!(udev_class & SDL_UDEV_DEVICE_JOYSTICK)) { + return; + } MaybeAddDevice(devpath); break; @@ -335,13 +337,12 @@ JoystickInitWithoutUdev(void) static int JoystickInitWithUdev(void) { - if (SDL_UDEV_Init() < 0) { return SDL_SetError("Could not initialize UDEV"); } /* Set up the udev callback */ - if ( SDL_UDEV_AddCallback(joystick_udev_callback) < 0) { + if (SDL_UDEV_AddCallback(joystick_udev_callback) < 0) { SDL_UDEV_Quit(); return SDL_SetError("Could not set up joystick <-> udev callback"); } From 60192c3d03431e45df92e8e9d6e0c765f6ea31cd Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Fri, 30 Jan 2015 23:18:14 +0100 Subject: [PATCH 008/142] Changed static variable to local variable in implementation for Android. --- src/core/android/SDL_android.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index a9089548b..b29f7e4ee 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -548,12 +548,12 @@ int Android_JNI_SetupThread(void) * Audio support */ static jboolean audioBuffer16Bit = JNI_FALSE; -static jboolean audioBufferStereo = JNI_FALSE; static jobject audioBuffer = NULL; static void* audioBufferPinned = NULL; int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames) { + jboolean audioBufferStereo; int audioBufferFrames; JNIEnv *env = Android_JNI_GetEnv(); From 26ddac2631f64bd3e8d2da414b9213b045a032b8 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Fri, 30 Jan 2015 23:20:15 +0100 Subject: [PATCH 009/142] Fix typos in header file documentation comments. --- include/SDL_render.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/SDL_render.h b/include/SDL_render.h index e6084e9e7..12da6f8b3 100644 --- a/include/SDL_render.h +++ b/include/SDL_render.h @@ -81,8 +81,8 @@ typedef struct SDL_RendererInfo Uint32 flags; /**< Supported ::SDL_RendererFlags */ Uint32 num_texture_formats; /**< The number of available texture formats */ Uint32 texture_formats[16]; /**< The available texture formats */ - int max_texture_width; /**< The maximimum texture width */ - int max_texture_height; /**< The maximimum texture height */ + int max_texture_width; /**< The maximum texture width */ + int max_texture_height; /**< The maximum texture height */ } SDL_RendererInfo; /** @@ -792,7 +792,7 @@ extern DECLSPEC int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer, * \param dstrect A pointer to the destination rectangle, or NULL for the * entire rendering target. * \param angle An angle in degrees that indicates the rotation that will be applied to dstrect - * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done aroud dstrect.w/2, dstrect.h/2) + * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2). * \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture * * \return 0 on success, or -1 on error From 97b6937ee20372e994128a5076868b11df91fc59 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 10:32:45 +0100 Subject: [PATCH 010/142] Fixed wrong comment in implementation for Android. --- android-project/src/org/libsdl/app/SDLActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index a864aa07a..a39d05ef1 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -81,7 +81,6 @@ public class SDLActivity extends Activity { } /** - * This method is called by SDL using JNI. * This method is called by SDL before starting the native application thread. * It can be overridden to provide the arguments after the application name. * The default implementation returns an empty array. It never returns null. From 36ebb1f6c610aee8ff2eecd4c7b3a2152683423b Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 10:33:48 +0100 Subject: [PATCH 011/142] Fixed names in implementation for PSP. --- src/audio/psp/SDL_pspaudio.h | 2 +- src/video/psp/SDL_pspvideo.c | 4 ++-- src/video/psp/SDL_pspvideo.h | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/audio/psp/SDL_pspaudio.h b/src/audio/psp/SDL_pspaudio.h index 8e420f313..3b7ffb0a0 100644 --- a/src/audio/psp/SDL_pspaudio.h +++ b/src/audio/psp/SDL_pspaudio.h @@ -24,7 +24,7 @@ #include "../SDL_sysaudio.h" -/* Hidden "this" pointer for the video functions */ +/* Hidden "this" pointer for the audio functions */ #define _THIS SDL_AudioDevice *this #define NUM_BUFFERS 2 diff --git a/src/video/psp/SDL_pspvideo.c b/src/video/psp/SDL_pspvideo.c index b3787239c..61244093c 100644 --- a/src/video/psp/SDL_pspvideo.c +++ b/src/video/psp/SDL_pspvideo.c @@ -66,7 +66,7 @@ PSP_Create() SDL_GLDriverData *gldata; int status; - /* Check if pandora could be initialized */ + /* Check if PSP could be initialized */ status = PSP_Available(); if (status == 0) { /* PSP could not be used */ @@ -80,7 +80,7 @@ PSP_Create() return NULL; } - /* Initialize internal Pandora specific data */ + /* Initialize internal PSP specific data */ phdata = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); if (phdata == NULL) { SDL_OutOfMemory(); diff --git a/src/video/psp/SDL_pspvideo.h b/src/video/psp/SDL_pspvideo.h index 2e1bb241b..cb25b57d0 100644 --- a/src/video/psp/SDL_pspvideo.h +++ b/src/video/psp/SDL_pspvideo.h @@ -19,8 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef __SDL_PANDORA_H__ -#define __SDL_PANDORA_H__ +#ifndef _SDL_pspvideo_h +#define _SDL_pspvideo_h #include @@ -97,6 +97,6 @@ void PSP_ShowScreenKeyboard(_THIS, SDL_Window *window); void PSP_HideScreenKeyboard(_THIS, SDL_Window *window); SDL_bool PSP_IsScreenKeyboardShown(_THIS, SDL_Window *window); -#endif /* __SDL_PANDORA_H__ */ +#endif /* _SDL_pspvideo_h */ /* vi: set ts=4 sw=4 expandtab: */ From 93040fda2b58aed445f060c24efbae6b03b34ce8 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 21:02:56 +0100 Subject: [PATCH 012/142] Fixed including SDL_config.h in implementation for Android. SDL_internal.h should be included to support dynamic API. --- src/joystick/android/SDL_sysjoystick_c.h | 2 +- src/video/android/SDL_androidmessagebox.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/android/SDL_sysjoystick_c.h b/src/joystick/android/SDL_sysjoystick_c.h index 3d56b0b99..6ad6aa7a5 100644 --- a/src/joystick/android/SDL_sysjoystick_c.h +++ b/src/joystick/android/SDL_sysjoystick_c.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_config.h" +#include "../../SDL_internal.h" #ifdef SDL_JOYSTICK_ANDROID #include "../SDL_sysjoystick.h" diff --git a/src/video/android/SDL_androidmessagebox.c b/src/video/android/SDL_androidmessagebox.c index a55afb376..11f856999 100644 --- a/src/video/android/SDL_androidmessagebox.c +++ b/src/video/android/SDL_androidmessagebox.c @@ -18,7 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_config.h" +#include "../../SDL_internal.h" #if SDL_VIDEO_DRIVER_ANDROID From af3327018f06923ab7a39be0879f736aa01248f8 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 21:06:37 +0100 Subject: [PATCH 013/142] Fixed comment in implementation for NaCl. --- src/filesystem/nacl/SDL_sysfilesystem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filesystem/nacl/SDL_sysfilesystem.c b/src/filesystem/nacl/SDL_sysfilesystem.c index ff55b2ba9..0111683a2 100644 --- a/src/filesystem/nacl/SDL_sysfilesystem.c +++ b/src/filesystem/nacl/SDL_sysfilesystem.c @@ -38,4 +38,5 @@ SDL_GetPrefPath(const char *org, const char *app) return NULL; } -#endif /* __NACL__ */ \ No newline at end of file +#endif /* SDL_FILESYSTEM_NACL */ + From cc564951adc2e8fca69c186ea61c9e967d931160 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 22:43:05 +0100 Subject: [PATCH 014/142] Added missing include statements in implementation for PSP. SDL_internal.h should be included to support dynamic API and fix warnings. --- src/audio/psp/SDL_pspaudio.c | 1 + src/joystick/psp/SDL_sysjoystick.c | 1 + src/thread/psp/SDL_syssem.c | 1 + src/thread/psp/SDL_systhread.c | 2 +- src/timer/psp/SDL_systimer.c | 1 + src/video/psp/SDL_pspevents.c | 1 + src/video/psp/SDL_pspgl.c | 1 + src/video/psp/SDL_pspmouse.c | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index 5b1705926..3abe3a110 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include #include diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index f848d1cee..3f9bd2d92 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" /* This is the PSP implementation of the SDL joystick API */ #include diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index 27d3251a2..3abb83565 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" /* Semaphore functions for the PSP. */ diff --git a/src/thread/psp/SDL_systhread.c b/src/thread/psp/SDL_systhread.c index d2fbeeb2f..2d5433c53 100644 --- a/src/thread/psp/SDL_systhread.c +++ b/src/thread/psp/SDL_systhread.c @@ -18,7 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ - +#include "../../SDL_internal.h" /* PSP thread management routines for SDL */ diff --git a/src/timer/psp/SDL_systimer.c b/src/timer/psp/SDL_systimer.c index b706f4495..1ae3d7fe5 100644 --- a/src/timer/psp/SDL_systimer.c +++ b/src/timer/psp/SDL_systimer.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include "SDL_thread.h" #include "SDL_timer.h" diff --git a/src/video/psp/SDL_pspevents.c b/src/video/psp/SDL_pspevents.c index d096c0616..982186b47 100644 --- a/src/video/psp/SDL_pspevents.c +++ b/src/video/psp/SDL_pspevents.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" /* Being a null driver, there's no event stream. We just define stubs for most of the API. */ diff --git a/src/video/psp/SDL_pspgl.c b/src/video/psp/SDL_pspgl.c index d24e72292..8b2cd8865 100644 --- a/src/video/psp/SDL_pspgl.c +++ b/src/video/psp/SDL_pspgl.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include #include diff --git a/src/video/psp/SDL_pspmouse.c b/src/video/psp/SDL_pspmouse.c index 8df3d614e..d9d8eefd2 100644 --- a/src/video/psp/SDL_pspmouse.c +++ b/src/video/psp/SDL_pspmouse.c @@ -18,6 +18,7 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +#include "../../SDL_internal.h" #include From cb727e32b9e9823d146d61b73de3d4c0bf06d1c9 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 31 Jan 2015 22:45:54 +0100 Subject: [PATCH 015/142] Added missing guards in implementation for PSP. Thanks to Martin Gerhardy for pointing this out. --- src/audio/psp/SDL_pspaudio.c | 5 ++++- src/joystick/psp/SDL_sysjoystick.c | 4 ++++ src/main/psp/SDL_psp_main.c | 7 +++++++ src/thread/psp/SDL_syscond.c | 4 ++++ src/thread/psp/SDL_sysmutex.c | 4 ++++ src/thread/psp/SDL_syssem.c | 4 ++++ src/thread/psp/SDL_systhread.c | 4 ++++ src/timer/psp/SDL_systimer.c | 4 ++++ src/video/psp/SDL_pspevents.c | 5 +++++ src/video/psp/SDL_pspgl.c | 5 +++++ src/video/psp/SDL_pspmouse.c | 5 +++++ 11 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index 3abe3a110..360391164 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_AUDIO_DRIVER_PSP + #include #include #include @@ -192,5 +194,6 @@ AudioBootStrap PSPAUD_bootstrap = { /* SDL_AUDI */ +#endif /* SDL_AUDIO_DRIVER_PSP */ - +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index 3f9bd2d92..22bd6e9de 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_JOYSTICK_PSP + /* This is the PSP implementation of the SDL joystick API */ #include #include @@ -263,5 +265,7 @@ SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick) return guid; } +#endif /* SDL_JOYSTICK_PSP */ + /* vim: ts=4 sw=4 */ diff --git a/src/main/psp/SDL_psp_main.c b/src/main/psp/SDL_psp_main.c index d79135dbc..2ca8e446b 100644 --- a/src/main/psp/SDL_psp_main.c +++ b/src/main/psp/SDL_psp_main.c @@ -1,6 +1,9 @@ /* SDL_psp_main.c, placed in the public domain by Sam Lantinga 3/13/14 */ +#include "SDL_config.h" + +#ifdef __PSP__ #include "SDL_main.h" #include @@ -61,3 +64,7 @@ int main(int argc, char *argv[]) (void)SDL_main(argc, argv); return 0; } + +#endif /* __PSP__ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/psp/SDL_syscond.c b/src/thread/psp/SDL_syscond.c index 1abd9a3d9..3959a4c43 100644 --- a/src/thread/psp/SDL_syscond.c +++ b/src/thread/psp/SDL_syscond.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_THREAD_PSP + /* An implementation of condition variables using semaphores and mutexes */ /* This implementation borrows heavily from the BeOS condition variable @@ -217,4 +219,6 @@ SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); } +#endif /* SDL_THREAD_PSP */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/psp/SDL_sysmutex.c b/src/thread/psp/SDL_sysmutex.c index 478575b32..e1cf413c3 100644 --- a/src/thread/psp/SDL_sysmutex.c +++ b/src/thread/psp/SDL_sysmutex.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_THREAD_PSP + /* An implementation of mutexes using semaphores */ #include "SDL_thread.h" @@ -129,4 +131,6 @@ SDL_mutexV(SDL_mutex * mutex) #endif /* SDL_THREADS_DISABLED */ } +#endif /* SDL_THREAD_PSP */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/psp/SDL_syssem.c b/src/thread/psp/SDL_syssem.c index 3abb83565..609ba7375 100644 --- a/src/thread/psp/SDL_syssem.c +++ b/src/thread/psp/SDL_syssem.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_THREAD_PSP + /* Semaphore functions for the PSP. */ #include @@ -153,5 +155,7 @@ int SDL_SemPost(SDL_sem *sem) return 0; } +#endif /* SDL_THREAD_PSP */ + /* vim: ts=4 sw=4 */ diff --git a/src/thread/psp/SDL_systhread.c b/src/thread/psp/SDL_systhread.c index 2d5433c53..8cbd2f132 100644 --- a/src/thread/psp/SDL_systhread.c +++ b/src/thread/psp/SDL_systhread.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_THREAD_PSP + /* PSP thread management routines for SDL */ #include @@ -104,5 +106,7 @@ int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) } +#endif /* SDL_THREAD_PSP */ + /* vim: ts=4 sw=4 */ diff --git a/src/timer/psp/SDL_systimer.c b/src/timer/psp/SDL_systimer.c index 1ae3d7fe5..8488b284d 100644 --- a/src/timer/psp/SDL_systimer.c +++ b/src/timer/psp/SDL_systimer.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#ifdef SDL_TIMERS_PSP + #include "SDL_thread.h" #include "SDL_timer.h" #include "SDL_error.h" @@ -83,5 +85,7 @@ void SDL_Delay(Uint32 ms) sceKernelDelayThreadCB(ms * 1000); } +#endif /* SDL_TIMERS_PSP */ + /* vim: ts=4 sw=4 */ diff --git a/src/video/psp/SDL_pspevents.c b/src/video/psp/SDL_pspevents.c index 982186b47..399566bf6 100644 --- a/src/video/psp/SDL_pspevents.c +++ b/src/video/psp/SDL_pspevents.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_VIDEO_DRIVER_PSP + /* Being a null driver, there's no event stream. We just define stubs for most of the API. */ @@ -283,3 +285,6 @@ void PSP_EventQuit(_THIS) /* end of SDL_pspevents.c ... */ +#endif /* SDL_VIDEO_DRIVER_PSP */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/psp/SDL_pspgl.c b/src/video/psp/SDL_pspgl.c index 8b2cd8865..61620de38 100644 --- a/src/video/psp/SDL_pspgl.c +++ b/src/video/psp/SDL_pspgl.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_VIDEO_DRIVER_PSP + #include #include @@ -204,3 +206,6 @@ PSP_GL_DeleteContext(_THIS, SDL_GLContext context) return; } +#endif /* SDL_VIDEO_DRIVER_PSP */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/psp/SDL_pspmouse.c b/src/video/psp/SDL_pspmouse.c index d9d8eefd2..0c8f5a428 100644 --- a/src/video/psp/SDL_pspmouse.c +++ b/src/video/psp/SDL_pspmouse.c @@ -20,6 +20,7 @@ */ #include "../../SDL_internal.h" +#if SDL_VIDEO_DRIVER_PSP #include @@ -34,3 +35,7 @@ struct WMcursor { int unused; }; + +#endif /* SDL_VIDEO_DRIVER_PSP */ + +/* vi: set ts=4 sw=4 expandtab: */ From b6973e6179b8e4046f2425702b5ed57de6b7ced0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 2 Feb 2015 01:05:41 -0500 Subject: [PATCH 016/142] X11: Fixes for OpenGL 3.0 and later context creation. - Don't create a temporary context first; this was probably due to Windows needing one to get the address of wglCreateContextAttribsARB(), but that's a unique quirk of WGL, and doesn't apply to glX. The glX spec explicitly says you have to get a function pointer that works with any context from glXGetProcAddress(), including when no context exists. - Properly check for the GLX_ARB_create_context instead of just looking for a non-NULL glXCreateContextAttribsARB()...some implementations, like Mesa, never return NULL for function lookups (Mesa returns pointers into a jump table that is filled out when the GL is initialized; since you can look up functions before you have a valid context, it can't definitely say a function isn't valid at that point). --HG-- extra : rebase_source : 336f207a6395506e5a1402d1c25277194017db29 --- src/video/x11/SDL_x11opengl.c | 115 +++++++++++++++------------------- src/video/x11/SDL_x11opengl.h | 2 + 2 files changed, 51 insertions(+), 66 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 1e94b041c..c46710f94 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -373,6 +373,16 @@ X11_GL_InitExtensions(_THIS) (int (*)(int)) X11_GL_GetProcAddress(_this, "glXSwapIntervalSGI"); } + /* Check for GLX_ARB_create_context */ + if (HasExtension("GLX_ARB_create_context", extensions)) { + _this->gl_data->glXCreateContextAttribsARB = + (GLXContext (*)(Display*,GLXFBConfig,GLXContext,Bool,const int *)) + X11_GL_GetProcAddress(_this, "glXCreateContextAttribsARB"); + _this->gl_data->glXChooseFBConfig = + (GLXFBConfig *(*)(Display *, int, const int *, int *)) + X11_GL_GetProcAddress(_this, "glXChooseFBConfig"); + } + /* Check for GLX_EXT_visual_rating */ if (HasExtension("GLX_EXT_visual_rating", extensions)) { _this->gl_data->HAS_GLX_EXT_visual_rating = SDL_TRUE; @@ -576,7 +586,6 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) XVisualInfo v, *vinfo; int n; GLXContext context = NULL, share_context; - PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = NULL; if (_this->gl_config.share_with_current_context) { share_context = (GLXContext)SDL_GL_GetCurrentContext(); @@ -601,78 +610,52 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) context = _this->gl_data->glXCreateContext(display, vinfo, share_context, True); } else { - /* If we want a GL 3.0 context or later we need to get a temporary - context to grab the new context creation function */ - GLXContext temp_context = - _this->gl_data->glXCreateContext(display, vinfo, NULL, True); - if (temp_context) { - /* max 8 attributes plus terminator */ - int attribs[9] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, - _this->gl_config.major_version, - GLX_CONTEXT_MINOR_VERSION_ARB, - _this->gl_config.minor_version, - 0 - }; - int iattr = 4; + /* max 8 attributes plus terminator */ + int attribs[9] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, + _this->gl_config.major_version, + GLX_CONTEXT_MINOR_VERSION_ARB, + _this->gl_config.minor_version, + 0 + }; + int iattr = 4; - /* SDL profile bits match GLX profile bits */ - if( _this->gl_config.profile_mask != 0 ) { - attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; - attribs[iattr++] = _this->gl_config.profile_mask; - } + /* SDL profile bits match GLX profile bits */ + if( _this->gl_config.profile_mask != 0 ) { + attribs[iattr++] = GLX_CONTEXT_PROFILE_MASK_ARB; + attribs[iattr++] = _this->gl_config.profile_mask; + } - /* SDL flags match GLX flags */ - if( _this->gl_config.flags != 0 ) { - attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; - attribs[iattr++] = _this->gl_config.flags; - } + /* SDL flags match GLX flags */ + if( _this->gl_config.flags != 0 ) { + attribs[iattr++] = GLX_CONTEXT_FLAGS_ARB; + attribs[iattr++] = _this->gl_config.flags; + } - attribs[iattr++] = 0; + attribs[iattr++] = 0; - /* Get a pointer to the context creation function for GL 3.0 */ - glXCreateContextAttribs = - (PFNGLXCREATECONTEXTATTRIBSARBPROC) _this->gl_data-> - glXGetProcAddress((GLubyte *) - "glXCreateContextAttribsARB"); - if (!glXCreateContextAttribs) { - SDL_SetError("GL 3.x is not supported"); - context = temp_context; + /* Get a pointer to the context creation function for GL 3.0 */ + if (!_this->gl_data->glXCreateContextAttribsARB) { + SDL_SetError("OpenGL 3.0 and later are not supported by this system"); + } else { + int glxAttribs[64]; + + /* Create a GL 3.x context */ + GLXFBConfig *framebuffer_config = NULL; + int fbcount = 0; + + X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); + + if (!_this->gl_data->glXChooseFBConfig + || !(framebuffer_config = + _this->gl_data->glXChooseFBConfig(display, + DefaultScreen(display), glxAttribs, + &fbcount))) { + SDL_SetError("No good framebuffers found. OpenGL 3.0 and later unavailable"); } else { - int glxAttribs[64]; - - /* Create a GL 3.x context */ - GLXFBConfig *framebuffer_config = NULL; - int fbcount = 0; - GLXFBConfig *(*glXChooseFBConfig) (Display * disp, - int screen, - const int *attrib_list, - int *nelements); - - glXChooseFBConfig = - (GLXFBConfig * - (*)(Display *, int, const int *, - int *)) _this->gl_data-> - glXGetProcAddress((GLubyte *) "glXChooseFBConfig"); - - X11_GL_GetAttributes(_this,display,screen,glxAttribs,64,SDL_TRUE); - - if (!glXChooseFBConfig - || !(framebuffer_config = - glXChooseFBConfig(display, - DefaultScreen(display), glxAttribs, - &fbcount))) { - SDL_SetError - ("No good framebuffers found. GL 3.x disabled"); - context = temp_context; - } else { - context = - glXCreateContextAttribs(display, + context = _this->gl_data->glXCreateContextAttribsARB(display, framebuffer_config[0], share_context, True, attribs); - _this->gl_data->glXDestroyContext(display, - temp_context); - } } } } diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index ed7f292d4..b3410fd46 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -40,6 +40,8 @@ struct SDL_GLDriverData void *(*glXGetProcAddress) (const GLubyte*); XVisualInfo *(*glXChooseVisual) (Display*,int,int*); GLXContext (*glXCreateContext) (Display*,XVisualInfo*,GLXContext,Bool); + GLXContext (*glXCreateContextAttribsARB) (Display*,GLXFBConfig,GLXContext,Bool,const int *); + GLXFBConfig *(*glXChooseFBConfig) (Display*,int,const int *,int *); void (*glXDestroyContext) (Display*, GLXContext); Bool(*glXMakeCurrent) (Display*,GLXDrawable,GLXContext); void (*glXSwapBuffers) (Display*, GLXDrawable); From 2a5d30c5f8d975ff3d584ae2dcd712e9200e5a79 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 2 Feb 2015 01:21:02 -0500 Subject: [PATCH 017/142] X11: Add events related to maximizing a window (thanks, Andrei and Gergely!). Fixes Bugzilla #1447. --- src/video/x11/SDL_x11events.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index c99b1971b..02dc8a900 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1108,15 +1108,25 @@ X11_DispatchEvent(_THIS) without ever mapping / unmapping them, so we handle that here, because they use the NETWM protocol to notify us of changes. */ - Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window); - if ((flags^data->window->flags) & SDL_WINDOW_HIDDEN || - (flags^data->window->flags) & SDL_WINDOW_FULLSCREEN ) { - if (flags & SDL_WINDOW_HIDDEN) { - X11_DispatchUnmapNotify(data); - } else { - X11_DispatchMapNotify(data); + const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window); + const Uint32 changed = flags ^ data->window->flags; + + if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) { + if (flags & SDL_WINDOW_HIDDEN) { + X11_DispatchUnmapNotify(data); + } else { + X11_DispatchMapNotify(data); } } + + if (changed & SDL_WINDOW_MAXIMIZED) { + if (flags & SDL_WINDOW_MAXIMIZED) { + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MAXIMIZED, 0, 0); + } else { + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0); + } + } + } } break; From f6c184ae02e158aad5a6c7d12cb4ac07679080fb Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Tue, 3 Feb 2015 21:22:25 +0100 Subject: [PATCH 018/142] Added missing guards. --- src/audio/coreaudio/SDL_coreaudio.c | 5 +++++ src/audio/nacl/SDL_naclaudio.c | 7 +++++++ src/video/nacl/SDL_naclevents.c | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/audio/coreaudio/SDL_coreaudio.c b/src/audio/coreaudio/SDL_coreaudio.c index 7fc9ea94b..a263ae441 100644 --- a/src/audio/coreaudio/SDL_coreaudio.c +++ b/src/audio/coreaudio/SDL_coreaudio.c @@ -19,6 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "../../SDL_internal.h" + +#if SDL_AUDIO_DRIVER_COREAUDIO + #include "SDL_audio.h" #include "../SDL_audio_c.h" #include "../SDL_sysaudio.h" @@ -554,4 +557,6 @@ AudioBootStrap COREAUDIO_bootstrap = { "coreaudio", "CoreAudio", COREAUDIO_Init, 0 }; +#endif /* SDL_AUDIO_DRIVER_COREAUDIO */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/nacl/SDL_naclaudio.c b/src/audio/nacl/SDL_naclaudio.c index d9179f272..741cb1392 100644 --- a/src/audio/nacl/SDL_naclaudio.c +++ b/src/audio/nacl/SDL_naclaudio.c @@ -20,6 +20,9 @@ */ #include "../../SDL_internal.h" + +#if SDL_AUDIO_DRIVER_NACL + #include "SDL_naclaudio.h" #include "SDL_audio.h" @@ -145,3 +148,7 @@ AudioBootStrap NACLAUD_bootstrap = { NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver", NACLAUD_Init, 0 }; + +#endif /* SDL_AUDIO_DRIVER_NACL */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/nacl/SDL_naclevents.c b/src/video/nacl/SDL_naclevents.c index 3204a6b1d..ebdbbfa22 100644 --- a/src/video/nacl/SDL_naclevents.c +++ b/src/video/nacl/SDL_naclevents.c @@ -20,6 +20,8 @@ */ #include "../../SDL_internal.h" +#if SDL_VIDEO_DRIVER_NACL + #include "SDL.h" #include "../../events/SDL_sysevents.h" #include "../../events/SDL_events_c.h" @@ -430,3 +432,7 @@ void NACL_PumpEvents(_THIS) { } } } + +#endif /* SDL_VIDEO_DRIVER_NACL */ + +/* vi: set ts=4 sw=4 expandtab: */ From 1577f08faddb8c923473ff91293c4f567e275333 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 7 Feb 2015 22:40:36 +0100 Subject: [PATCH 019/142] Fixed bug 2866 - testrelative.c: patch to make the orange box wrap around Eric Wasylishen Here's a patch to make the 'testrelative' demo program more useful: it just makes the orange rectangle wrap around. Previously, the orange cursor would just disappear off screen if you move the mouse a lot in one direction, so it was hard to tell if relative mouse mode was still working. --- test/testrelative.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/testrelative.c b/test/testrelative.c index 4425cb8d3..3b6ef810e 100644 --- a/test/testrelative.c +++ b/test/testrelative.c @@ -49,12 +49,20 @@ loop(){ } } for (i = 0; i < state->num_windows; ++i) { + SDL_Rect viewport; SDL_Renderer *renderer = state->renderers[i]; if (state->windows[i] == NULL) continue; SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); SDL_RenderClear(renderer); + /* Wrap the cursor rectangle at the screen edges to keep it visible */ + SDL_RenderGetViewport(renderer, &viewport); + if (rect.x < viewport.x) rect.x += viewport.w; + if (rect.y < viewport.y) rect.y += viewport.h; + if (rect.x > viewport.x + viewport.w) rect.x -= viewport.w; + if (rect.y > viewport.y + viewport.h) rect.y -= viewport.h; + DrawRects(renderer, &rect); SDL_RenderPresent(renderer); From 21dbdf0eab28aa8fb18de5a8b7671b9daa7c0548 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 8 Feb 2015 21:25:37 +0100 Subject: [PATCH 020/142] Fixed three memory leaks on failed allocation. --- src/events/SDL_mouse.c | 5 +++-- src/render/opengl/SDL_render_gl.c | 5 +++-- src/video/SDL_bmp.c | 6 ++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 32eb0f902..0ce443a3c 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -303,10 +303,11 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button) { if (button >= mouse->num_clickstates) { int i, count = button + 1; - mouse->clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate)); - if (!mouse->clickstate) { + SDL_MouseClickState *clickstate = (SDL_MouseClickState *)SDL_realloc(mouse->clickstate, count * sizeof(*mouse->clickstate)); + if (!clickstate) { return NULL; } + mouse->clickstate = clickstate; for (i = mouse->num_clickstates; i < count; ++i) { SDL_zero(mouse->clickstate[i]); diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index ecd0d531f..f34bf1288 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -342,9 +342,10 @@ GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GL if (type == GL_DEBUG_TYPE_ERROR_ARB) { /* Record this error */ + char **error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages)); ++data->errors; - data->error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages)); - if (data->error_messages) { + if (error_messages) { + data->error_messages = error_messages; data->error_messages[data->errors-1] = SDL_strdup(message); } } diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index fcc48c6d5..c5de8f00f 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -306,16 +306,18 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) biClrUsed = 1 << biBitCount; } if ((int) biClrUsed > palette->ncolors) { + SDL_Color *colors; palette->ncolors = biClrUsed; - palette->colors = + colors = (SDL_Color *) SDL_realloc(palette->colors, palette->ncolors * sizeof(*palette->colors)); - if (!palette->colors) { + if (!colors) { SDL_OutOfMemory(); was_error = SDL_TRUE; goto done; } + palette->colors = colors; } else if ((int) biClrUsed < palette->ncolors) { palette->ncolors = biClrUsed; } From 445da2c73200679771c7413b204409cb290d8e25 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 8 Feb 2015 15:44:15 -0500 Subject: [PATCH 021/142] WinRT: made note that VSync is always enabled on WinPhone, due to OS Windows Phone does not appear to allow VSync to be turned off. Doing so appears to either result in content not getting drawn (when the D3D debug runtime is turned off), or forcing VSync back on and logging an error (when the D3D debug runtime is turned on). VSync had been getting turned on anyways, this change just notes such: - via the WinRT README - by always setting the SDL_RENDERER_PRESENTVSYNC flag when creating an SDL_Renderer on Windows Phone --HG-- extra : rebase_source : 504904b549f21d518919b2254319783da7c9bbdf --- docs/README-winrt.md | 5 +++++ src/render/direct3d11/SDL_render_d3d11.c | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/docs/README-winrt.md b/docs/README-winrt.md index fdc669f10..e188d7791 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -112,6 +112,11 @@ Here is a rough list of what works, and what doens't: supported by WinRT itself. * joysticks and game controllers that aren't supported by Microsoft's XInput API. + * turning off VSync when rendering on Windows Phone. Attempts to turn VSync + off on Windows Phone result either in Direct3D not drawing anything, or it + forcing VSync back on. As such, SDL_RENDERER_PRESENTVSYNC will always get + turned-on on Windows Phone. This limitation is not present in non-Phone + WinRT (such as Windows 8.x), where turning off VSync appears to work. * probably anything else that's not listed as supported diff --git a/src/render/direct3d11/SDL_render_d3d11.c b/src/render/direct3d11/SDL_render_d3d11.c index f99fdb1d5..c8a487a6b 100644 --- a/src/render/direct3d11/SDL_render_d3d11.c +++ b/src/render/direct3d11/SDL_render_d3d11.c @@ -829,9 +829,24 @@ D3D11_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); renderer->driverdata = data; +#if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP + /* VSync is required in Windows Phone, at least for Win Phone 8.0 and 8.1. + * Failure to use it seems to either result in: + * + * - with the D3D11 debug runtime turned OFF, vsync seemingly gets turned + * off (framerate doesn't get capped), but nothing appears on-screen + * + * - with the D3D11 debug runtime turned ON, vsync gets automatically + * turned back on, and the following gets output to the debug console: + * + * DXGI ERROR: IDXGISwapChain::Present: Interval 0 is not supported, changed to Interval 1. [ UNKNOWN ERROR #1024: ] + */ + renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; +#else if ((flags & SDL_RENDERER_PRESENTVSYNC)) { renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; } +#endif /* HACK: make sure the SDL_Renderer references the SDL_Window data now, in * order to give init functions access to the underlying window handle: From 65093881bcaacb019f3494aa8e62ed4320fac330 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 8 Feb 2015 22:50:16 +0100 Subject: [PATCH 022/142] Fixed two inconsistencies on failed allocation. --- src/render/opengl/SDL_render_gl.c | 5 +++-- src/video/SDL_bmp.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index f34bf1288..0c930f35d 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -342,9 +342,10 @@ GL_HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GL if (type == GL_DEBUG_TYPE_ERROR_ARB) { /* Record this error */ - char **error_messages = SDL_realloc(data->error_messages, data->errors * sizeof(*data->error_messages)); - ++data->errors; + int errors = data->errors + 1; + char **error_messages = SDL_realloc(data->error_messages, errors * sizeof(*data->error_messages)); if (error_messages) { + data->errors = errors; data->error_messages = error_messages; data->error_messages[data->errors-1] = SDL_strdup(message); } diff --git a/src/video/SDL_bmp.c b/src/video/SDL_bmp.c index c5de8f00f..f2b19fabd 100644 --- a/src/video/SDL_bmp.c +++ b/src/video/SDL_bmp.c @@ -307,16 +307,17 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) } if ((int) biClrUsed > palette->ncolors) { SDL_Color *colors; - palette->ncolors = biClrUsed; + int ncolors = biClrUsed; colors = (SDL_Color *) SDL_realloc(palette->colors, - palette->ncolors * + ncolors * sizeof(*palette->colors)); if (!colors) { SDL_OutOfMemory(); was_error = SDL_TRUE; goto done; } + palette->ncolors = ncolors; palette->colors = colors; } else if ((int) biClrUsed < palette->ncolors) { palette->ncolors = biClrUsed; From b5080e09ab7387570efacff59319ab81331c1242 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Tue, 10 Feb 2015 20:31:05 +0100 Subject: [PATCH 023/142] Fixed compiling test with older C. --- test/relative_mode.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/relative_mode.markdown b/test/relative_mode.markdown index 9ae88aa1c..5b2ed6185 100644 --- a/test/relative_mode.markdown +++ b/test/relative_mode.markdown @@ -37,9 +37,11 @@ Code int main(int argc, char *argv[]) { + SDL_Window *win; + SDL_Init(SDL_INIT_VIDEO); - SDL_Window *win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0); + win = SDL_CreateWindow("Test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, 0); SDL_SetRelativeMouseMode(SDL_TRUE); while (1) From bf73cbded14ac469c904a3566c6aecf3f867f8d1 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Tue, 10 Feb 2015 20:40:03 +0100 Subject: [PATCH 024/142] Fixed bug 2873 - Joystick test won't reload after reattach lectem -plug in the joystick -start testjoystick 0 -unplug -replug The joystick is detected but doesn't enter the loop anymore since done==SDL_TRUE --- test/testjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testjoystick.c b/test/testjoystick.c index 232213a69..3b2b5bf40 100644 --- a/test/testjoystick.c +++ b/test/testjoystick.c @@ -176,7 +176,7 @@ WatchJoystick(SDL_Joystick * joystick) { SDL_Window *window = NULL; const char *name = NULL; - + done = SDL_FALSE; /* Create a window to display joystick axis position */ window = SDL_CreateWindow("Joystick Test", SDL_WINDOWPOS_CENTERED, From 16369a49199a0b898f97faecf08082affa2061ff Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 11 Feb 2015 01:48:52 -0500 Subject: [PATCH 025/142] X11: Set dialog hint on message boxes (thanks, Melker!). This helps the window manager do the right thing with these windows. --- src/video/x11/SDL_x11messagebox.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index 2a98e3c3e..e8396c562 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -366,6 +366,7 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) int x, y; XSizeHints *sizehints; XSetWindowAttributes wnd_attr; + Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DIALOG; Display *display = data->display; SDL_WindowData *windowdata = NULL; const SDL_MessageBoxData *messageboxdata = data->messageboxdata; @@ -401,6 +402,13 @@ X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) X11_XStoreName( display, data->window, messageboxdata->title ); + /* Let the window manager know this is a dialog box */ + _NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False); + _NET_WM_WINDOW_TYPE_DIALOG = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_DIALOG", False); + X11_XChangeProperty(display, data->window, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, + PropModeReplace, + (unsigned char *)&_NET_WM_WINDOW_TYPE_DIALOG, 1); + /* Allow the window to be deleted by the window manager */ data->wm_protocols = X11_XInternAtom( display, "WM_PROTOCOLS", False ); data->wm_delete_message = X11_XInternAtom( display, "WM_DELETE_WINDOW", False ); From d9c3c62015093cc2ba317f952f157a4897dff590 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Thu, 12 Feb 2015 21:40:53 +0100 Subject: [PATCH 026/142] Fixed test programs for joystick not exiting on events after first disconnect. Exit was broken since the main loop extraction needed for Emscripten support because the former local but now global variables were not reset correctly. --- test/testgamecontroller.c | 8 ++++++++ test/testjoystick.c | 3 +++ 2 files changed, 11 insertions(+) diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 29e0308a4..414872cf2 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -163,6 +163,10 @@ WatchGameController(SDL_GameController * gamecontroller) const size_t titlelen = SDL_strlen(basetitle) + SDL_strlen(name) + 1; char *title = (char *)SDL_malloc(titlelen); SDL_Window *window = NULL; + + retval = SDL_FALSE; + done = SDL_FALSE; + if (title) { SDL_snprintf(title, titlelen, "%s%s", basetitle, name); } @@ -219,6 +223,10 @@ WatchGameController(SDL_GameController * gamecontroller) #endif SDL_DestroyRenderer(screen); + screen = NULL; + background = NULL; + button = NULL; + axis = NULL; SDL_DestroyWindow(window); return retval; } diff --git a/test/testjoystick.c b/test/testjoystick.c index 3b2b5bf40..72f056ccb 100644 --- a/test/testjoystick.c +++ b/test/testjoystick.c @@ -176,6 +176,8 @@ WatchJoystick(SDL_Joystick * joystick) { SDL_Window *window = NULL; const char *name = NULL; + + retval = SDL_FALSE; done = SDL_FALSE; /* Create a window to display joystick axis position */ @@ -217,6 +219,7 @@ WatchJoystick(SDL_Joystick * joystick) #endif SDL_DestroyRenderer(screen); + screen = NULL; SDL_DestroyWindow(window); return retval; } From 3506528b4d177ed06c2fba343a8401481daa30ad Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 00:08:48 +0100 Subject: [PATCH 027/142] Emscripten: Fixed SDL_GetPlatform() returning "Unknown" instead of "Emscripten". --- src/SDL.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SDL.c b/src/SDL.c index 69872dd6c..0e3512009 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -405,6 +405,8 @@ SDL_GetPlatform() return "BSDI"; #elif __DREAMCAST__ return "Dreamcast"; +#elif __EMSCRIPTEN__ + return "Emscripten"; #elif __FREEBSD__ return "FreeBSD"; #elif __HAIKU__ From c07f4809469b700bd2bbd445428df2ab54f9a20c Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 00:10:58 +0100 Subject: [PATCH 028/142] Emscripten: Fixed framebuffer error message. --- src/video/emscripten/SDL_emscriptenframebuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/emscripten/SDL_emscriptenframebuffer.c b/src/video/emscripten/SDL_emscriptenframebuffer.c index 1c76923dd..453865abb 100644 --- a/src/video/emscripten/SDL_emscriptenframebuffer.c +++ b/src/video/emscripten/SDL_emscriptenframebuffer.c @@ -63,7 +63,7 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec SDL_WindowData *data = (SDL_WindowData *) window->driverdata; surface = data->surface; if (!surface) { - return SDL_SetError("Couldn't find dummy surface for window"); + return SDL_SetError("Couldn't find framebuffer surface for window"); } /* Send the data to the display */ From 88c0cf919295a7fee7f455731e1263c15210643d Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 00:13:00 +0100 Subject: [PATCH 029/142] Emscripten: Fixed not including SDL_internal.h. --- src/joystick/emscripten/SDL_sysjoystick_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick_c.h b/src/joystick/emscripten/SDL_sysjoystick_c.h index 375ea0ef8..4c907a66c 100644 --- a/src/joystick/emscripten/SDL_sysjoystick_c.h +++ b/src/joystick/emscripten/SDL_sysjoystick_c.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_config.h" +#include "../../SDL_internal.h" #ifdef SDL_JOYSTICK_EMSCRIPTEN #include "../SDL_sysjoystick.h" From 77b70ccb7da518ee09101bc03695c19ad7d9f904 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 00:16:27 +0100 Subject: [PATCH 030/142] Emscripten: Fixed throwing JavaScript exception if no audio context available. Handling the error in C provides the possibility to just continue without audio. --- src/audio/emscripten/SDL_emscriptenaudio.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index d9334daec..f1ae929f3 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -157,6 +157,7 @@ Emscripten_OpenDevice(_THIS, const char *devname, int iscapture) SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int i; float f; + int result; while ((!valid_format) && (test_format)) { switch (test_format) { @@ -185,7 +186,7 @@ Emscripten_OpenDevice(_THIS, const char *devname, int iscapture) /* based on parts of library_sdl.js */ /* create context (TODO: this puts stuff in the global namespace...)*/ - EM_ASM({ + result = EM_ASM_INT_V({ if(typeof(SDL2) === 'undefined') SDL2 = {}; @@ -198,10 +199,14 @@ Emscripten_OpenDevice(_THIS, const char *devname, int iscapture) } else if (typeof(webkitAudioContext) !== 'undefined') { SDL2.audioContext = new webkitAudioContext(); } else { - throw 'Web Audio API is not available!'; + return -1; } } + return 0; }); + if (result < 0) { + return SDL_SetError("Web Audio API is not available!"); + } /* limit to native freq */ int sampleRate = EM_ASM_INT_V({ From 3c70a54e6d84dbd06a9fc2a8b506ff5b465d5f46 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 15:16:41 +0100 Subject: [PATCH 031/142] Emscripten: Deactivated and corrected debug log messages on joystick events. --- src/joystick/emscripten/SDL_sysjoystick.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 62283c9f6..324338cbe 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -105,7 +105,9 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa } ++numjoysticks; - SDL_Log("%d",numjoysticks); +#ifdef DEBUG_JOYSTICK + SDL_Log("Number of joysticks is %d", numjoysticks); +#endif #if !SDL_EVENTS_DISABLED event.type = SDL_JOYDEVICEADDED; @@ -118,7 +120,9 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa } #endif /* !SDL_EVENTS_DISABLED */ +#ifdef DEBUG_JOYSTICK SDL_Log("Added joystick with index %d", item->index); +#endif return 1; } @@ -144,7 +148,6 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam return 1; } - const int retval = item->device_instance; if (item->joystick) { item->joystick->hwdata = NULL; } @@ -174,7 +177,9 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam } #endif /* !SDL_EVENTS_DISABLED */ - SDL_Log("Removed joystick with index %d", retval); +#ifdef DEBUG_JOYSTICK + SDL_Log("Removed joystick with id %d", item->device_instance); +#endif SDL_free(item->name); SDL_free(item->mapping); SDL_free(item); From e18cf07b3a416fe4383ac88f83b85852a6b5128e Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 14 Feb 2015 15:22:04 +0100 Subject: [PATCH 032/142] Emscripten: Fixed sending SDL_JOYDEVICEADDED events with an index out of range. SDL_JOYDEVICEADDED events must contain the device index which is a value between 0 and the number of connected joysticks. The old implementation included a value based on the instance id instead. It worked in some cases because the values are similar initially. But after disconnecting joysticks this is no more the case and the always increasing instance id becomes larger than number of joysticks. --- src/joystick/emscripten/SDL_sysjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 324338cbe..ded4b62b8 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -112,7 +112,7 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa event.type = SDL_JOYDEVICEADDED; if (SDL_GetEventState(event.type) == SDL_ENABLE) { - event.jdevice.which = item->device_instance - 1; + event.jdevice.which = item->index; if ( (SDL_EventOK == NULL) || (*SDL_EventOK) (SDL_EventOKParam, &event) ) { SDL_PushEvent(&event); From 790d90535a81471bba0fbd78b2c493cabae546d9 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 15 Feb 2015 00:08:27 -0500 Subject: [PATCH 033/142] WinRT: fixed crash when using up-to-date versions of ANGLE/WinRT --- src/video/winrt/SDL_winrtopengles.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index e3a955be1..c29c5fed9 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -38,8 +38,8 @@ using namespace Windows::UI::Core; static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0; #define EGL_PLATFORM_ANGLE_ANGLE 0x3201 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 /* * SDL/EGL top-level implementation From 56146a8c13938be09c8f2a15776be82bcdecad72 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 15 Feb 2015 11:33:39 +0100 Subject: [PATCH 034/142] Fixed compile warning about unused variable in wave test program. --- test/loopwavequeue.c | 1 - 1 file changed, 1 deletion(-) diff --git a/test/loopwavequeue.c b/test/loopwavequeue.c index 8ca31dd03..6d7128575 100644 --- a/test/loopwavequeue.c +++ b/test/loopwavequeue.c @@ -48,7 +48,6 @@ poked(int sig) int main(int argc, char *argv[]) { - int i; char filename[4096]; /* Enable standard application logging */ From d1135e337ba6b5faf8b3c64a30036ef6834cc8d6 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 15 Feb 2015 11:35:07 +0100 Subject: [PATCH 035/142] Fixed crash if using clipboard functions without having initialized video. --- src/video/SDL_clipboard.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c index a3b38e045..f2b450152 100644 --- a/src/video/SDL_clipboard.c +++ b/src/video/SDL_clipboard.c @@ -29,6 +29,10 @@ SDL_SetClipboardText(const char *text) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this) { + return SDL_SetError("Video subsystem must be initialized to set clipboard text"); + } + if (!text) { text = ""; } @@ -46,6 +50,11 @@ SDL_GetClipboardText(void) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this) { + SDL_SetError("Video subsystem must be initialized to get clipboard text"); + return SDL_strdup(""); + } + if (_this->GetClipboardText) { return _this->GetClipboardText(_this); } else { @@ -62,6 +71,11 @@ SDL_HasClipboardText(void) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this) { + SDL_SetError("Video subsystem must be initialized to check clipboard text"); + return SDL_FALSE; + } + if (_this->HasClipboardText) { return _this->HasClipboardText(_this); } else { From e0a6da9b6df13465902775920b4a88d6b6fa96fc Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 15 Feb 2015 11:53:24 -0500 Subject: [PATCH 036/142] WinRT: improved OpenGL ES compatibility on WinPhone/ARM and Surface RT This change integrates initialization settings for ANGLE/WinRT, as suggested in MSOpenTech's latest ANGLE template-projects (for MSVC). This should fix some OpenGL initialization issues on WinPhone 8.1 on ARM, and on the 1st-generation Surface RT. --HG-- extra : rebase_source : af7dc2bd4f074cb3ec9cdfc4ff518f3182ed0abe --- src/video/winrt/SDL_winrtopengles.cpp | 76 +++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index c29c5fed9..07bccd6eb 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -36,10 +36,15 @@ using namespace Windows::UI::Core; /* ANGLE/WinRT constants */ static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0; -#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 +#define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B + /* * SDL/EGL top-level implementation @@ -82,9 +87,35 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) if (!_this->egl_data->egl_display) { return SDL_SetError("Could not get EGL display"); } + + if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { + return SDL_SetError("Could not initialize EGL"); + } } else { - const EGLint displayAttributes[] = { + /* Declare some ANGLE/EGL initialization property-sets, as suggested by + * MSOpenTech's ANGLE-for-WinRT template apps: + */ + const EGLint defaultDisplayAttributes[] = + { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_NONE, + }; + + const EGLint fl9_3DisplayAttributes[] = + { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, + EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_NONE, + }; + + const EGLint warpDisplayAttributes[] = + { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_NONE, }; @@ -99,14 +130,41 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) return SDL_SetError("Could not retrieve ANGLE/WinRT display function(s)"); } - _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, displayAttributes); +#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + /* Try initializing EGL at D3D11 Feature Level 10_0+ (which is not + * supported on WinPhone 8.x. + */ + _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); if (!_this->egl_data->egl_display) { return SDL_SetError("Could not get EGL display"); } - } - if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { - return SDL_SetError("Could not initialize EGL"); + if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) +#endif + { + /* Try initializing EGL at D3D11 Feature Level 9_3, in case the + * 10_0 init fails, or we're on Windows Phone (which only supports + * 9_3). + */ + _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); + if (!_this->egl_data->egl_display) { + return SDL_SetError("Could not get 9_3 EGL display"); + } + + if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { + /* Try initializing EGL at D3D11 Feature Level 11_0 on WARP + * (a Windows-provided, software rasterizer) if all else fails. + */ + _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes); + if (!_this->egl_data->egl_display) { + return SDL_SetError("Could not get WARP EGL display"); + } + + if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { + return SDL_SetError("Could not initialize EGL"); + } + } + } } return 0; From 83859b12eaf8a9b187a57966346fa8874e5764dd Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 15 Feb 2015 12:11:44 -0500 Subject: [PATCH 037/142] WinRT: a minor, nit-picky cleanup of some OpenGL code --- src/video/winrt/SDL_winrtopengles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 07bccd6eb..20a9a0bc9 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -38,8 +38,8 @@ using namespace Windows::UI::Core; static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0; #define EGL_PLATFORM_ANGLE_ANGLE 0x3201 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 #define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 #define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 #define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 #define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 From 34e9ba9c4552935a724fe44a4ee378149d5c1e97 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 15 Feb 2015 21:44:36 +0100 Subject: [PATCH 038/142] Emscripten: Changed return type of callback implementations from int to EM_BOOL. The prototypes are declared with EM_BOOL (which is currently an int) in html5.h. --- src/joystick/emscripten/SDL_sysjoystick.c | 4 ++-- src/video/emscripten/SDL_emscriptenevents.c | 22 ++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index ded4b62b8..2b2c26b59 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -46,7 +46,7 @@ static SDL_joylist_item *SDL_joylist_tail = NULL; static int numjoysticks = 0; static int instance_counter = 0; -int +EM_BOOL Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { int i; @@ -127,7 +127,7 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa return 1; } -int +EM_BOOL Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData) { SDL_joylist_item *item = SDL_joylist; diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index a2887bf56..ef746e5c6 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -296,7 +296,7 @@ Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char * text) return SDL_TRUE; } -int +EM_BOOL Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -322,7 +322,7 @@ Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent return 0; } -int +EM_BOOL Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -344,7 +344,7 @@ Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEve return 1; } -int +EM_BOOL Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -352,7 +352,7 @@ Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEven return 1; } -int +EM_BOOL Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -360,7 +360,7 @@ Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, vo return 1; } -int +EM_BOOL Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -368,7 +368,7 @@ Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, vo return 1; } -int +EM_BOOL Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) { /*SDL_WindowData *window_data = userData;*/ @@ -404,7 +404,7 @@ Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, vo return 1; } -int +EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { Uint32 scancode; @@ -443,7 +443,7 @@ Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, voi || keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */; } -int +EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { char text[5]; @@ -452,7 +452,7 @@ Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent return 1; } -int +EM_BOOL Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData) { /*make sure this is actually our element going fullscreen*/ @@ -514,7 +514,7 @@ Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChang return 0; } -int +EM_BOOL Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData) { SDL_WindowData *window_data = userData; @@ -554,7 +554,7 @@ Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *u return 0; } -int +EM_BOOL Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData) { SDL_WindowData *window_data = userData; From 6c134a60d068a454cced7baa3725a1b92a737d0a Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 15 Feb 2015 21:47:10 +0100 Subject: [PATCH 039/142] Emscripten: Removed unused internal function. --- src/joystick/emscripten/SDL_sysjoystick.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 2b2c26b59..8f44cf092 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -261,12 +261,6 @@ void SDL_SYS_JoystickDetect() { } -// we need to poll to see if the gamepad state has changed -SDL_bool SDL_SYS_JoystickNeedsPolling() -{ - return SDL_TRUE; -} - /* Function to get the device-dependent name of a joystick */ const char * SDL_SYS_JoystickNameForDeviceIndex(int index) From 21282ee01ff8565c891c731d3ea029fa18667df0 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 Feb 2015 22:59:56 -0500 Subject: [PATCH 040/142] glX HasExtension(): check for NULL ext string first. It's slightly faster than failing later, after a strchr() call, since this will get called multiple times with a NULL string if the system totally fails elsewhere. --HG-- extra : rebase_source : 72564776aed4ab255a65880e979f8dba4df4a527 --- src/video/x11/SDL_x11opengl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index c46710f94..93dcd8c2e 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -279,14 +279,14 @@ HasExtension(const char *extension, const char *extensions) const char *start; const char *where, *terminator; + if (!extensions) + return SDL_FALSE; + /* Extension names should not have spaces. */ where = SDL_strchr(extension, ' '); if (where || *extension == '\0') return SDL_FALSE; - if (!extensions) - return SDL_FALSE; - /* It takes a bit of care to be fool-proof about parsing the * OpenGL extensions string. Don't be fooled by sub-strings, * etc. */ From 1a17139cf16f222d652bede426a35b448eec5f13 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 Feb 2015 23:00:46 -0500 Subject: [PATCH 041/142] X11: Don't create a window and GL context to look up the glX extension string. It's not necessary. --HG-- extra : rebase_source : 6b2111b284a971832ce6d1315481c4a888e4e39a extra : amend_source : 95f007dae5432aa52c49861487756b9d7b0c9526 --- src/video/x11/SDL_x11opengl.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index 93dcd8c2e..f89a9cc0a 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -312,32 +312,10 @@ static void X11_GL_InitExtensions(_THIS) { Display *display = ((SDL_VideoData *) _this->driverdata)->display; - int screen = DefaultScreen(display); - XVisualInfo *vinfo; - XSetWindowAttributes xattr; - Window w; - GLXContext context; + const int screen = DefaultScreen(display); const char *(*glXQueryExtensionsStringFunc) (Display *, int); const char *extensions; - vinfo = X11_GL_GetVisual(_this, display, screen); - if (!vinfo) { - return; - } - xattr.background_pixel = 0; - xattr.border_pixel = 0; - xattr.colormap = - X11_XCreateColormap(display, RootWindow(display, screen), vinfo->visual, - AllocNone); - w = X11_XCreateWindow(display, RootWindow(display, screen), 0, 0, 32, 32, 0, - vinfo->depth, InputOutput, vinfo->visual, - (CWBackPixel | CWBorderPixel | CWColormap), &xattr); - context = _this->gl_data->glXCreateContext(display, vinfo, NULL, True); - if (context) { - _this->gl_data->glXMakeCurrent(display, w, context); - } - X11_XFree(vinfo); - glXQueryExtensionsStringFunc = (const char *(*)(Display *, int)) X11_GL_GetProcAddress(_this, "glXQueryExtensionsString"); @@ -397,13 +375,6 @@ X11_GL_InitExtensions(_THIS) if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) { _this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE; } - - if (context) { - _this->gl_data->glXMakeCurrent(display, None, NULL); - _this->gl_data->glXDestroyContext(display, context); - } - X11_XDestroyWindow(display, w); - X11_PumpEvents(_this); } /* glXChooseVisual and glXChooseFBConfig have some small differences in From f3b8ca2a36add5421bc59352db6a1e38d2d18259 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Wed, 18 Feb 2015 21:31:21 +0100 Subject: [PATCH 042/142] Removed redundant include statements from test programs. The needed header files are already included with SDL.h. Still including them in the test programs is confusing because it somehow suggests they would be needed. --- test/loopwave.c | 1 - test/testatomic.c | 3 --- test/testerror.c | 1 - test/testfile.c | 1 - test/testhaptic.c | 2 -- test/testhotplug.c | 1 - test/testlock.c | 2 -- test/testmessage.c | 1 - test/testplatform.c | 3 --- test/testrumble.c | 2 -- test/testsem.c | 1 - test/testthread.c | 1 - test/torturethread.c | 1 - 13 files changed, 20 deletions(-) diff --git a/test/loopwave.c b/test/loopwave.c index 9d50aaea5..e09fe0f72 100644 --- a/test/loopwave.c +++ b/test/loopwave.c @@ -29,7 +29,6 @@ #endif #include "SDL.h" -#include "SDL_audio.h" struct { diff --git a/test/testatomic.c b/test/testatomic.c index 662a017ca..178de7ac1 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -12,9 +12,6 @@ #include #include "SDL.h" -#include "SDL_atomic.h" -#include "SDL_assert.h" -#include "SDL_cpuinfo.h" /* Absolutely basic tests just to see if we get the expected value diff --git a/test/testerror.c b/test/testerror.c index 1fa60885b..8290680e0 100644 --- a/test/testerror.c +++ b/test/testerror.c @@ -17,7 +17,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" static int alive = 0; diff --git a/test/testfile.c b/test/testfile.c index 172da865c..38a6bb799 100644 --- a/test/testfile.c +++ b/test/testfile.c @@ -22,7 +22,6 @@ #endif #include "SDL.h" -#include "SDL_endian.h" #include diff --git a/test/testhaptic.c b/test/testhaptic.c index ac8ab4158..bffe4467d 100644 --- a/test/testhaptic.c +++ b/test/testhaptic.c @@ -22,8 +22,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #ifndef SDL_HAPTIC_DISABLED -#include "SDL_haptic.h" - static SDL_Haptic *haptic; diff --git a/test/testhotplug.c b/test/testhotplug.c index ba06dea0f..1b68db1e4 100644 --- a/test/testhotplug.c +++ b/test/testhotplug.c @@ -17,7 +17,6 @@ #include #include "SDL.h" -#include "SDL_haptic.h" #if !defined SDL_JOYSTICK_DISABLED && !defined SDL_HAPTIC_DISABLED diff --git a/test/testlock.c b/test/testlock.c index 9ca3ca199..92a5e9b3f 100644 --- a/test/testlock.c +++ b/test/testlock.c @@ -19,8 +19,6 @@ #include /* for atexit() */ #include "SDL.h" -#include "SDL_mutex.h" -#include "SDL_thread.h" static SDL_mutex *mutex = NULL; static SDL_threadID mainthread; diff --git a/test/testmessage.c b/test/testmessage.c index f44880c3f..b0bf39c89 100644 --- a/test/testmessage.c +++ b/test/testmessage.c @@ -17,7 +17,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ static void diff --git a/test/testplatform.c b/test/testplatform.c index e0dc29e7c..232bfe653 100644 --- a/test/testplatform.c +++ b/test/testplatform.c @@ -13,9 +13,6 @@ #include #include "SDL.h" -#include "SDL_endian.h" -#include "SDL_cpuinfo.h" -#include "SDL_assert.h" /* * Watcom C flags these as Warning 201: "Unreachable code" if you just diff --git a/test/testrumble.c b/test/testrumble.c index 74a7e98fc..d72e5d94a 100644 --- a/test/testrumble.c +++ b/test/testrumble.c @@ -33,8 +33,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #ifndef SDL_HAPTIC_DISABLED -#include "SDL_haptic.h" - static SDL_Haptic *haptic; diff --git a/test/testsem.c b/test/testsem.c index ca71ec2e6..8d41e083f 100644 --- a/test/testsem.c +++ b/test/testsem.c @@ -17,7 +17,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" #define NUM_THREADS 10 diff --git a/test/testthread.c b/test/testthread.c index d732320a5..75aed83fc 100644 --- a/test/testthread.c +++ b/test/testthread.c @@ -17,7 +17,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" static SDL_TLSID tls; static int alive = 0; diff --git a/test/torturethread.c b/test/torturethread.c index bc4e1132f..2e572b64c 100644 --- a/test/torturethread.c +++ b/test/torturethread.c @@ -18,7 +18,6 @@ #include #include "SDL.h" -#include "SDL_thread.h" #define NUMTHREADS 10 From 1a2231c115e51be57b17f22ba88e7ee54e10b5c5 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Wed, 18 Feb 2015 21:34:07 +0100 Subject: [PATCH 043/142] Emscripten: Fixed receiving joystick events after failed init or subsystem quit. The callbacks used to receive the HTML events were not removed if the joystick subsystem initialization failed or if the joystick subsystem was quit. Also, the already connected joysticks were not deleted if the initialization failed later. --- src/joystick/emscripten/SDL_sysjoystick.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 8f44cf092..cc5a6f668 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -220,6 +220,7 @@ SDL_SYS_JoystickInit(void) Emscripten_JoyStickConnected); if(retval != EMSCRIPTEN_RESULT_SUCCESS) { + SDL_SYS_JoystickQuit(); return -1; } @@ -227,6 +228,7 @@ SDL_SYS_JoystickInit(void) 0, Emscripten_JoyStickDisconnected); if(retval != EMSCRIPTEN_RESULT_SUCCESS) { + SDL_SYS_JoystickQuit(); return -1; } @@ -399,6 +401,9 @@ SDL_SYS_JoystickQuit(void) numjoysticks = 0; instance_counter = 0; + + emscripten_set_gamepadconnected_callback(NULL, 0, NULL); + emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL); } SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index) From 25c786a0d9589d439356beb30ec29476519f2875 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Feb 2015 16:17:53 -0500 Subject: [PATCH 044/142] We maintain the list of platforms on the wiki now. Also, I don't really want people emailing community members directly with problems, so I'm removing their email addresses. Fixes Bugzilla #2304. --HG-- extra : rebase_source : 3be8e4d6bb5c9fb121ffab0847e868cfce068e27 --- docs/README-platforms.md | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/docs/README-platforms.md b/docs/README-platforms.md index 4bf77b206..14454ec5d 100644 --- a/docs/README-platforms.md +++ b/docs/README-platforms.md @@ -1,34 +1,8 @@ Platforms ========= - -This is a list of the platforms SDL supports, and who maintains them. - -Officially supported platforms -============================== -(code compiles, and thoroughly tested for release) -============================== -* Windows XP/Vista/7/8 -* Mac OS X 10.5+ -* Linux 2.6+ -* iOS 5.1.1+ -* Android 2.3.3+ - -Unofficially supported platforms -================================ -(code compiles, but not thoroughly tested) -================================ -* FreeBSD -* NetBSD -* OpenBSD -* Solaris - -Platforms supported by volunteers -================================= -* Haiku - maintained by Axel Dörfler -* PSP - maintained by 527721088@qq.com -* Pandora - maintained by Scott Smith -* NaCl - maintained by Gabriel Jacobo - -Platforms that need maintainers -=============================== +We maintain the list of supported platforms on our wiki now, and how to +build and install SDL for those platforms: + + https://wiki.libsdl.org/Installation + From 139252cb4ee6a8f0575dc745b75266ce43a7a0b4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Feb 2015 16:25:15 -0500 Subject: [PATCH 045/142] Corrected documentation about triggers values in SDL_GameControllerGetAxis(). Fixes Bugzilla #2319. --- include/SDL_gamecontroller.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index 9df526a76..5c9082ced 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -241,7 +241,8 @@ SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller, /** * Get the current state of an axis control on a game controller. * - * The state is a value ranging from -32768 to 32767. + * The state is a value ranging from -32768 to 32767 (except for the triggers, + * which range from 0 to 32767). * * The axis indices start at index 0. */ From e08e2cd4eb2a44ca8c59480892be129aded8a773 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 13:11:19 -0500 Subject: [PATCH 046/142] Remove unnecessary parentheses and an unnecessary free() of a NULL pointer. (Thanks, Simon!) Fixes Bugzilla #2881. --- src/haptic/linux/SDL_syshaptic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 63c81ab9b..fba536b48 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -288,8 +288,7 @@ MaybeAddDevice(const char *path) } item->fname = SDL_strdup(path); - if ( (item->fname == NULL) ) { - SDL_free(item->fname); + if (item->fname == NULL) { SDL_free(item); return -1; } From 8b1b079795e7feccc02960c2b71e219205e4866d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 13:42:56 -0500 Subject: [PATCH 047/142] Some corrections to the SDL2.spec.in (thanks, Simone!). Fixes Bugzilla #2809. --- SDL2.spec.in | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/SDL2.spec.in b/SDL2.spec.in index 2a5c47924..628a9a0c6 100644 --- a/SDL2.spec.in +++ b/SDL2.spec.in @@ -1,7 +1,7 @@ Summary: Simple DirectMedia Layer Name: SDL2 Version: @SDL_VERSION@ -Release: 1 +Release: 2 Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz URL: http://www.libsdl.org/ License: zlib @@ -63,12 +63,12 @@ rm -rf $RPM_BUILD_ROOT %files %{__defattr} -%doc README-SDL.txt COPYING.txt CREDITS.txt BUGS.txt +%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt %{_libdir}/lib*.%{__soext}.* %files devel %{__defattr} -%doc README README-SDL.txt COPYING CREDITS BUGS WhatsNew +%doc README*.txt COPYING.txt CREDITS.txt BUGS.txt WhatsNew.txt %{_bindir}/*-config %{_libdir}/lib*.a %{_libdir}/lib*.la @@ -78,13 +78,16 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/aclocal/* %changelog +* Sun Dec 07 2014 Simone Contini +- Fixed changelog date issue and docs filenames + * Sun Jan 22 2012 Sam Lantinga - Updated for SDL 2.0 * Tue May 16 2006 Sam Lantinga - Removed support for Darwin, due to build problems on ps2linux -* Mon Jan 03 2004 Anders Bjorklund +* Sat Jan 03 2004 Anders Bjorklund - Added support for Darwin, updated spec file * Wed Jan 19 2000 Sam Lantinga From 551c20baf21ad4edeb99ed571da40954f719c2a4 Mon Sep 17 00:00:00 2001 From: Arne Janbu Date: Sat, 10 Jan 2015 13:47:37 +0100 Subject: [PATCH 048/142] Fix build on Linux when wayland is enabled Bug: https://bugzilla.libsdl.org/show_bug.cgi?id=2838 --- src/video/wayland/SDL_waylandwindow.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 3760c0d3b..81bdc81b1 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -29,6 +29,7 @@ #include "SDL_waylandwindow.h" #include "SDL_waylandvideo.h" #include "SDL_waylandtouch.h" +#include "SDL_waylanddyn.h" static void handle_ping(void *data, struct wl_shell_surface *shell_surface, From 05b4247f94b55befd2383b703dc3bda03afaf388 Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Thu, 19 Feb 2015 19:40:58 -0500 Subject: [PATCH 049/142] SDL_SetWindowPosition respects display num for SDL_WINDOWPOS_CENTERED_DISPLAY. This allows for this kind of code in an application: int monitorID = 1; // the second monitor! SDL_SetWindowPosition(sdlWin, SDL_WINDOWPOS_CENTERED_DISPLAY(monitorID), SDL_WINDOWPOS_CENTERED_DISPLAY(monitorID)); Fixes Bugzilla #2849. --- src/video/SDL_video.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index db777db32..1dcfabf08 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1607,13 +1607,14 @@ SDL_SetWindowPosition(SDL_Window * window, int x, int y) CHECK_WINDOW_MAGIC(window,); if (SDL_WINDOWPOS_ISCENTERED(x) || SDL_WINDOWPOS_ISCENTERED(y)) { - SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); - int displayIndex; + int displayIndex = (x & 0xFFFF); SDL_Rect bounds; + if (displayIndex > _this->num_displays) { + displayIndex = 0; + } SDL_zero(bounds); - displayIndex = SDL_GetIndexOfDisplay(display); SDL_GetDisplayBounds(displayIndex, &bounds); if (SDL_WINDOWPOS_ISCENTERED(x)) { x = bounds.x + (bounds.w - window->w) / 2; From a33b3fca958a39f895708ae5f8937f59225d5c5a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 19:55:30 -0500 Subject: [PATCH 050/142] Mac OS X: replace some deprecated APIs with modern equivalents (thanks, Alex!). Fixes Bugzilla #2858. --- src/video/cocoa/SDL_cocoaevents.h | 1 + src/video/cocoa/SDL_cocoaevents.m | 57 ++++++++++++++++++++++++++----- src/video/cocoa/SDL_cocoavideo.h | 4 +++ src/video/cocoa/SDL_cocoavideo.m | 4 +++ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaevents.h b/src/video/cocoa/SDL_cocoaevents.h index 687cf647e..1d27bbf99 100644 --- a/src/video/cocoa/SDL_cocoaevents.h +++ b/src/video/cocoa/SDL_cocoaevents.h @@ -25,6 +25,7 @@ extern void Cocoa_RegisterApp(void); extern void Cocoa_PumpEvents(_THIS); +extern void Cocoa_SuspendScreenSaver(_THIS); #endif /* _SDL_cocoaevents_h */ diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 13aeb4502..51020347e 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -27,6 +27,11 @@ #include "../../events/SDL_events_c.h" #include "SDL_assert.h" +/* This define was added in the 10.9 SDK. */ +#ifndef kIOPMAssertPreventUserIdleDisplaySleep +#define kIOPMAssertPreventUserIdleDisplaySleep kIOPMAssertionTypePreventUserIdleDisplaySleep +#endif + @interface SDLApplication : NSApplication - (void)terminate:(id)sender; @@ -251,17 +256,24 @@ Cocoa_RegisterApp(void) { @autoreleasepool { /* This can get called more than once! Be careful what you initialize! */ - ProcessSerialNumber psn; - - if (!GetCurrentProcess(&psn)) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - } if (NSApp == nil) { [SDLApplication sharedApplication]; SDL_assert(NSApp != nil); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) { +#endif + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + } else { + ProcessSerialNumber psn = {0, kCurrentProcess}; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + } +#endif + + [NSApp activateIgnoringOtherApps:YES]; + if ([NSApp mainMenu] == nil) { CreateApplicationMenus(); } @@ -293,8 +305,8 @@ Cocoa_PumpEvents(_THIS) { @autoreleasepool { /* Update activity every 30 seconds to prevent screensaver */ - if (_this->suspend_screensaver) { - SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + if (_this->suspend_screensaver && !data->screensaver_use_iopm) { Uint32 now = SDL_GetTicks(); if (!data->screensaver_activity || SDL_TICKS_PASSED(now, data->screensaver_activity + 30000)) { @@ -336,6 +348,35 @@ Cocoa_PumpEvents(_THIS) } }} +void +Cocoa_SuspendScreenSaver(_THIS) +{ @autoreleasepool +{ + SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; + + if (!data->screensaver_use_iopm) { + return; + } + + if (data->screensaver_assertion) { + IOPMAssertionRelease(data->screensaver_assertion); + data->screensaver_assertion = 0; + } + + if (_this->suspend_screensaver) { + /* FIXME: this should ideally describe the real reason why the game + * called SDL_DisableScreenSaver. Note that the name is only meant to be + * seen by OS X power users. there's an additional optional human-readable + * (localized) reason parameter which we don't set. + */ + NSString *name = [GetApplicationName() stringByAppendingString:@" using SDL_DisableScreenSaver"]; + IOPMAssertionCreateWithDescription(kIOPMAssertPreventUserIdleDisplaySleep, + (CFStringRef) name, + NULL, NULL, NULL, 0, NULL, + &data->screensaver_assertion); + } +}} + #endif /* SDL_VIDEO_DRIVER_COCOA */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoavideo.h b/src/video/cocoa/SDL_cocoavideo.h index 288c41fca..cf254db1b 100644 --- a/src/video/cocoa/SDL_cocoavideo.h +++ b/src/video/cocoa/SDL_cocoavideo.h @@ -26,6 +26,7 @@ #include "SDL_opengl.h" #include +#include #include #include "SDL_keycode.h" @@ -51,6 +52,9 @@ typedef struct SDL_VideoData SDLTranslatorResponder *fieldEdit; NSInteger clipboard_count; Uint32 screensaver_activity; + BOOL screensaver_use_iopm; + IOPMAssertionID screensaver_assertion; + } SDL_VideoData; /* Utility functions */ diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index ad4f14c21..f31218b3a 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -76,6 +76,7 @@ Cocoa_CreateDevice(int devindex) device->GetDisplayModes = Cocoa_GetDisplayModes; device->SetDisplayMode = Cocoa_SetDisplayMode; device->PumpEvents = Cocoa_PumpEvents; + device->SuspendScreenSaver = Cocoa_SuspendScreenSaver; device->CreateWindow = Cocoa_CreateWindow; device->CreateWindowFrom = Cocoa_CreateWindowFrom; @@ -148,6 +149,9 @@ Cocoa_VideoInit(_THIS) const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES); data->allow_spaces = ( (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && (!hint || (*hint != '0')) ); + /* The IOPM assertion API can disable the screensaver as of 10.7. */ + data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6; + return 0; } From c2ba56ccb77ed1cfdae3a5bcdfab42d842fd127b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 21:44:41 -0500 Subject: [PATCH 051/142] Windows: Support unicode arguments for console applications (thanks, Jorgen!). Fixes Bugzilla #2864. --- src/main/windows/SDL_windows_main.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c index 7886fe3a8..69634a291 100644 --- a/src/main/windows/SDL_windows_main.c +++ b/src/main/windows/SDL_windows_main.c @@ -109,13 +109,16 @@ OutOfMemory(void) } #if defined(_MSC_VER) -/* The VC++ compiler needs main defined */ -#define console_main main +/* The VC++ compiler needs main/wmain defined */ +# define console_utf8_main main +# if UNICODE +# define console_wmain wmain +# endif #endif -/* This is where execution begins [console apps] */ +/* This is where execution begins [console apps, ansi] */ int -console_main(int argc, char *argv[]) +console_utf8_main(int argc, char *argv[]) { SDL_SetMainReady(); @@ -123,6 +126,22 @@ console_main(int argc, char *argv[]) return SDL_main(argc, argv); } +#if UNICODE +/* This is where execution begins [console apps, unicode] */ +int +console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) +{ + char **argv = SDL_stack_alloc(char*, argc); + int i; + + for (i = 0; i < argc; ++i) { + argv[i] = WIN_StringToUTF8(wargv[i]); + } + + return console_utf8_main(argc, argv); +} +#endif + /* This is where execution begins [windowed apps] */ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) @@ -151,7 +170,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) ParseCommandLine(cmdline, argv); /* Run the main program */ - console_main(argc, argv); + console_utf8_main(argc, argv); SDL_stack_free(argv); From f9cd47e1871f4b8175b0d24b7752acbd71e1e8e6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 21:49:15 -0500 Subject: [PATCH 052/142] Windows: Make a distinction between ANSI mainline and UTF-8 mainline. --- src/main/windows/SDL_windows_main.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c index 69634a291..dc51dc04d 100644 --- a/src/main/windows/SDL_windows_main.c +++ b/src/main/windows/SDL_windows_main.c @@ -110,15 +110,15 @@ OutOfMemory(void) #if defined(_MSC_VER) /* The VC++ compiler needs main/wmain defined */ -# define console_utf8_main main +# define console_ansi_main main # if UNICODE # define console_wmain wmain # endif #endif -/* This is where execution begins [console apps, ansi] */ -int -console_utf8_main(int argc, char *argv[]) +/* WinMain, main, and wmain eventually call into here. */ +static int +main_utf8(int argc, char *argv[]) { SDL_SetMainReady(); @@ -126,6 +126,15 @@ console_utf8_main(int argc, char *argv[]) return SDL_main(argc, argv); } +/* This is where execution begins [console apps, ansi] */ +int +console_ansi_main(int argc, char *argv[]) +{ + /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */ + return main_utf8(argc, argv); +} + + #if UNICODE /* This is where execution begins [console apps, unicode] */ int @@ -138,7 +147,7 @@ console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) argv[i] = WIN_StringToUTF8(wargv[i]); } - return console_utf8_main(argc, argv); + return main_utf8(argc, argv); } #endif @@ -170,7 +179,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) ParseCommandLine(cmdline, argv); /* Run the main program */ - console_utf8_main(argc, argv); + main_utf8(argc, argv); SDL_stack_free(argv); From d0c74b7b23adc9cd51b5b6f89796ec6fc65c3f97 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 21:49:30 -0500 Subject: [PATCH 053/142] Windows: Added a FIXME. --- src/main/windows/SDL_windows_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c index dc51dc04d..eac904e27 100644 --- a/src/main/windows/SDL_windows_main.c +++ b/src/main/windows/SDL_windows_main.c @@ -164,6 +164,7 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) #if UNICODE cmdline = WIN_StringToUTF8(text); #else + /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */ cmdline = SDL_strdup(text); #endif if (cmdline == NULL) { From b549a0f79744583edbbf5111568e21e0c89ed587 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 21:50:40 -0500 Subject: [PATCH 054/142] Windows: Free the argv we allocated for console_wmain(). --- src/main/windows/SDL_windows_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c index eac904e27..7ccca75e6 100644 --- a/src/main/windows/SDL_windows_main.c +++ b/src/main/windows/SDL_windows_main.c @@ -140,6 +140,7 @@ console_ansi_main(int argc, char *argv[]) int console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) { + int retval = 0; char **argv = SDL_stack_alloc(char*, argc); int i; @@ -147,7 +148,11 @@ console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) argv[i] = WIN_StringToUTF8(wargv[i]); } - return main_utf8(argc, argv); + retval = main_utf8(argc, argv); + + SDL_stack_free(argv); + + return retval; } #endif From 3951d03c49553ffe887993d3ecb7a52977e64844 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 21:51:13 -0500 Subject: [PATCH 055/142] Windows: Added a FIXME. --HG-- extra : amend_source : c4478dd58e8560a9636d8dd64c79f9b5c15e0621 --- src/main/windows/SDL_windows_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c index 7ccca75e6..e6378081f 100644 --- a/src/main/windows/SDL_windows_main.c +++ b/src/main/windows/SDL_windows_main.c @@ -150,6 +150,7 @@ console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp) retval = main_utf8(argc, argv); + /* !!! FIXME: we are leaking all the elements of argv we allocated. */ SDL_stack_free(argv); return retval; From 984d72502dedc9bb5e1f6ab0c0b2ae7023dfe071 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Feb 2015 23:52:10 -0500 Subject: [PATCH 056/142] Mac OS X: Better way to stop duplicate joystick reports (thanks, Kyungdahm!). Fixes Bugzilla #2822. --- src/joystick/darwin/SDL_sysjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 0518cc75b..ac40e322d 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -446,9 +446,9 @@ ConfigHIDManager(CFArrayRef matchingArray) return SDL_FALSE; } + IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray); IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL); IOHIDManagerScheduleWithRunLoop(hidman, runloop, SDL_JOYSTICK_RUNLOOP_MODE); - IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray); while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) { /* no-op. Callback fires once per existing device. */ From 79abb08b76db857239c97e6216fa1f0a0ff08a1d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 21 Feb 2015 00:33:25 -0500 Subject: [PATCH 057/142] Fixed naming conventions in some SDL_assert types, added compat #defines. Fixes Bugzilla #1997. --- include/SDL_assert.h | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/include/SDL_assert.h b/include/SDL_assert.h index 94d998770..0be90470f 100644 --- a/include/SDL_assert.h +++ b/include/SDL_assert.h @@ -102,9 +102,9 @@ typedef enum SDL_ASSERTION_ABORT, /**< Terminate the program. */ SDL_ASSERTION_IGNORE, /**< Ignore the assert. */ SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */ -} SDL_assert_state; +} SDL_AssertState; -typedef struct SDL_assert_data +typedef struct SDL_AssertData { int always_ignore; unsigned int trigger_count; @@ -112,13 +112,13 @@ typedef struct SDL_assert_data const char *filename; int linenum; const char *function; - const struct SDL_assert_data *next; -} SDL_assert_data; + const struct SDL_AssertData *next; +} SDL_AssertData; #if (SDL_ASSERT_LEVEL > 0) /* Never call this directly. Use the SDL_assert* macros. */ -extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, +extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *, const char *, const char *, int) #if defined(__clang__) @@ -141,10 +141,10 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, #define SDL_enabled_assert(condition) \ do { \ while ( !(condition) ) { \ - static struct SDL_assert_data sdl_assert_data = { \ + static struct SDL_AssertData sdl_assert_data = { \ 0, 0, #condition, 0, 0, 0, 0 \ }; \ - const SDL_assert_state sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ + const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ continue; /* go again. */ \ } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ @@ -181,8 +181,8 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *, #define SDL_assert_always(condition) SDL_enabled_assert(condition) -typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)( - const SDL_assert_data* data, void* userdata); +typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)( + const SDL_AssertData* data, void* userdata); /** * \brief Set an application-defined assertion handler. @@ -199,7 +199,7 @@ typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)( * * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! * - * \return SDL_assert_state value of how to handle the assertion failure. + * \return SDL_AssertState value of how to handle the assertion failure. * * \param handler Callback function, called when an assertion fails. * \param userdata A pointer passed to the callback as-is. @@ -246,7 +246,7 @@ extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puse * The proper way to examine this data looks something like this: * * - * const SDL_assert_data *item = SDL_GetAssertionReport(); + * const SDL_AssertData *item = SDL_GetAssertionReport(); * while (item) { * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n", * item->condition, item->function, item->filename, @@ -259,7 +259,7 @@ extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puse * \return List of all assertions. * \sa SDL_ResetAssertionReport */ -extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void); +extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void); /** * \brief Reset the list of all assertion failures. @@ -270,6 +270,12 @@ extern DECLSPEC const SDL_assert_data * SDLCALL SDL_GetAssertionReport(void); */ extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void); + +/* these had wrong naming conventions until 2.0.4. Please update your app! */ +#define SDL_assert_state SDL_AssertState +#define SDL_assert_data SDL_AssertData + + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } From eb9d37950306ffb80f856656e552e76c85397bb5 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 22 Feb 2015 21:00:35 +0100 Subject: [PATCH 058/142] Emscripten: Fixed sending button and motion events for not opened joysticks. SDL_SYS_JoystickUpdate() was implemented incorrectly. For every call to it all attached joysticks were checked. But actually only the given SDL_Joystick should be checked then. This allowed sending broken events for attached but not opened joysticks. It also checked the opened joysticks more often than actually needed. --- src/joystick/emscripten/SDL_sysjoystick.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index cc5a6f668..4e4809047 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -335,10 +335,10 @@ void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { EmscriptenGamepadEvent gamepadState; - SDL_joylist_item *item = SDL_joylist; + SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata; int i, result, buttonState; - while (item != NULL) { + if (item) { result = emscripten_get_gamepad_status(item->index, &gamepadState); if( result == EMSCRIPTEN_RESULT_SUCCESS) { if(gamepadState.timestamp == 0 || gamepadState.timestamp != item->timestamp) { @@ -368,7 +368,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) } } } - item = item->next; } } From e4f4a0e0afba316d9801398e881dcbf8a8d45cc3 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 22 Feb 2015 23:21:32 +0100 Subject: [PATCH 059/142] Emscripten: Fixed out of range joystick device index after joystick disconnect. After disconnecting a joystick the remaining kept their original device index. This was not correct because the device index must be a number between 0 and SDL_NumJoysticks(). It was fixed with ideas from SDL's joystick implementation for Android. Some range checks were removed as the caller already checks them. --- src/joystick/emscripten/SDL_sysjoystick.c | 50 ++++++++++++----------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 4e4809047..0fdbcb9de 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -112,7 +112,7 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa event.type = SDL_JOYDEVICEADDED; if (SDL_GetEventState(event.type) == SDL_ENABLE) { - event.jdevice.which = item->index; + event.jdevice.which = numjoysticks - 1; if ( (SDL_EventOK == NULL) || (*SDL_EventOK) (SDL_EventOKParam, &event) ) { SDL_PushEvent(&event); @@ -235,6 +235,21 @@ SDL_SYS_JoystickInit(void) return 0; } +/* Returns item matching given SDL device index. */ +static SDL_joylist_item * +JoystickByDeviceIndex(int device_index) +{ + SDL_joylist_item *item = SDL_joylist; + + while (0 < device_index) { + --device_index; + item = item->next; + } + + return item; +} + +/* Returns item matching given HTML gamepad index. */ static SDL_joylist_item * JoystickByIndex(int index) { @@ -265,27 +280,15 @@ void SDL_SYS_JoystickDetect() /* Function to get the device-dependent name of a joystick */ const char * -SDL_SYS_JoystickNameForDeviceIndex(int index) +SDL_SYS_JoystickNameForDeviceIndex(int device_index) { - SDL_joylist_item *item = JoystickByIndex(index); - if (item == NULL) { - SDL_SetError("Joystick with index %d not found", index); - return NULL; - } - - return item->name; + return JoystickByDeviceIndex(device_index)->name; } /* Function to perform the mapping from device index to the instance id for this index */ -SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index) +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) { - SDL_joylist_item *item = JoystickByIndex(index); - if (item == NULL) { - SDL_SetError("Joystick with index %d not found", index); - return 0; - } - - return item->device_instance; + return JoystickByDeviceIndex(device_index)->device_instance; } /* Function to open a joystick for use. @@ -294,9 +297,9 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int index) It returns 0, or -1 if there is an error. */ int -SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int index) +SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) { - SDL_joylist_item *item = JoystickByIndex(index); + SDL_joylist_item *item = JoystickByDeviceIndex(device_index); if (item == NULL ) { return SDL_SetError("No such device"); @@ -405,18 +408,19 @@ SDL_SYS_JoystickQuit(void) emscripten_set_gamepaddisconnected_callback(NULL, 0, NULL); } -SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID(int index) +SDL_JoystickGUID +SDL_SYS_JoystickGetDeviceGUID(int device_index) { SDL_JoystickGUID guid; /* the GUID is just the first 16 chars of the name for now */ - const char *name = SDL_SYS_JoystickNameForDeviceIndex(index); + const char *name = SDL_SYS_JoystickNameForDeviceIndex(device_index); SDL_zero(guid); SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); return guid; } - -SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick) +SDL_JoystickGUID +SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick) { SDL_JoystickGUID guid; /* the GUID is just the first 16 chars of the name for now */ From 2287c7b0328e6b966de77514630a6beda84f6be1 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Sun, 22 Feb 2015 20:34:08 -0500 Subject: [PATCH 060/142] Fixed bug 2868 - SDL_FillRect can crash if surface's clip-rect is out-of-bounds Thanks to John Skaller for the research into this, and for the fix! --- src/video/SDL_fillrect.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/SDL_fillrect.c b/src/video/SDL_fillrect.c index 5f343eaf2..84707842e 100644 --- a/src/video/SDL_fillrect.c +++ b/src/video/SDL_fillrect.c @@ -251,6 +251,10 @@ SDL_FillRect(SDL_Surface * dst, const SDL_Rect * rect, Uint32 color) rect = &clipped; } else { rect = &dst->clip_rect; + /* Don't attempt to fill if the surface's clip_rect is empty */ + if (SDL_RectEmpty(rect)) { + return 0; + } } /* Perform software fill */ From f1bdf20e1dea7e9591fc6b91e3dedf5b1502a05e Mon Sep 17 00:00:00 2001 From: Alfred Reynolds Date: Mon, 2 Mar 2015 11:43:24 -0800 Subject: [PATCH 061/142] SDL - fix crash on OSX when removing a device. If the remove happened due to the CFRunLoopRunInMode call in SDL_SYS_JoystickDetect then we would delete the device right away, before SDL_SYS_JoystickUpdate could clean it up. So move the CFRunLoopRunInMode to after the cleanup logic, preventing this case. This does mean that adds and removes of joysticks now take 1 extra frame to show up. --- src/joystick/darwin/SDL_sysjoystick.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index ac40e322d..8e641d496 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -560,10 +560,6 @@ SDL_SYS_NumJoysticks() void SDL_SYS_JoystickDetect() { - while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) { - /* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */ - } - if (s_bDeviceAdded || s_bDeviceRemoved) { recDevice *device = gpDeviceList; s_bDeviceAdded = SDL_FALSE; @@ -613,6 +609,12 @@ SDL_SYS_JoystickDetect() } } } + + // run this after the checks above so we don't set device->removed and delete the device before + // SDL_SYS_JoystickUpdate can run to clean up the SDL_Joystick object that owns this device + while (CFRunLoopRunInMode(SDL_JOYSTICK_RUNLOOP_MODE,0,TRUE) == kCFRunLoopRunHandledSource) { + /* no-op. Pending callbacks will fire in CFRunLoopRunInMode(). */ + } } /* Function to get the device-dependent name of a joystick */ From 12d065e7e1cded1dddd93e9e403a86116e49d681 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 2 Mar 2015 21:36:45 -0500 Subject: [PATCH 062/142] Fixed SDL_PRI?64 for 64-bit Linux. 64-bit Linux uses a "long" instead of "long long" for 64-bit ints. Added a special-case this so SDL_PRI?64 doesn't trigger compiler warnings when used with SDL's 64-bit datatypes on 64-bit Linux. --HG-- extra : rebase_source : 573ae86baa2648ab2b84479f2d8058e2c6dec009 --- include/SDL_stdinc.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index 7a061a9c8..7cf020841 100644 --- a/include/SDL_stdinc.h +++ b/include/SDL_stdinc.h @@ -173,6 +173,8 @@ typedef uint64_t Uint64; #define SDL_PRIs64 PRIs64 #elif defined(__WIN32__) #define SDL_PRIs64 "I64d" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIs64 "ld" #else #define SDL_PRIs64 "lld" #endif @@ -182,6 +184,8 @@ typedef uint64_t Uint64; #define SDL_PRIu64 PRIu64 #elif defined(__WIN32__) #define SDL_PRIu64 "I64u" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIu64 "lu" #else #define SDL_PRIu64 "llu" #endif @@ -191,6 +195,8 @@ typedef uint64_t Uint64; #define SDL_PRIx64 PRIx64 #elif defined(__WIN32__) #define SDL_PRIx64 "I64x" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIx64 "lx" #else #define SDL_PRIx64 "llx" #endif @@ -200,6 +206,8 @@ typedef uint64_t Uint64; #define SDL_PRIX64 PRIX64 #elif defined(__WIN32__) #define SDL_PRIX64 "I64X" +#elif defined(__LINUX__) && defined(__LP64__) +#define SDL_PRIX64 "lX" #else #define SDL_PRIX64 "llX" #endif From 0eb350f9eca48372c62b240738cbd68bce9c1a4b Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Fri, 6 Mar 2015 21:26:37 +0100 Subject: [PATCH 063/142] Emscripten: Partially fixed not removing key event callbacks if hint was used. The key event callbacks were always removed from the same target although it is possible to set them to different targets using the hint. This is only a partial fix because it assumes that the hint is not changed to a different value later. --- src/video/emscripten/SDL_emscriptenevents.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index ef746e5c6..d61ff4fe0 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -621,10 +621,15 @@ Emscripten_UnregisterEventHandlers(SDL_WindowData *data) emscripten_set_touchmove_callback("#canvas", NULL, 0, NULL); emscripten_set_touchcancel_callback("#canvas", NULL, 0, NULL); - emscripten_set_keydown_callback("#window", NULL, 0, NULL); - emscripten_set_keyup_callback("#window", NULL, 0, NULL); + const char *target = SDL_GetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT); + if (!target) { + target = "#window"; + } - emscripten_set_keypress_callback("#window", NULL, 0, NULL); + emscripten_set_keydown_callback(target, NULL, 0, NULL); + emscripten_set_keyup_callback(target, NULL, 0, NULL); + + emscripten_set_keypress_callback(target, NULL, 0, NULL); emscripten_set_fullscreenchange_callback("#document", NULL, 0, NULL); From cf9936654d592945b751142a9416c1d81d070b80 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Fri, 6 Mar 2015 21:29:25 +0100 Subject: [PATCH 064/142] Emscripten: Fixed ignoring return value of internal function. If the function Emscripten_ConvertUTF32toUTF8() failed (should currently not be possible) a not terminated string would have been sent as text input event. --- src/video/emscripten/SDL_emscriptenevents.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index d61ff4fe0..6a04d4cc8 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -447,8 +447,9 @@ EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { char text[5]; - Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text); - SDL_SendKeyboardText(text); + if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { + SDL_SendKeyboardText(text); + } return 1; } From b6737b215df37070369de92db85e564541641189 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Fri, 6 Mar 2015 21:34:10 +0100 Subject: [PATCH 065/142] Windows: Fixed ignoring return value of internal function. If the function WIN_ConvertUTF32toUTF8() failed (should currently not be possible) a not terminated string would have been sent as text input event. This also fixed converting characters more often than needed on key repetition. --- src/video/windows/SDL_windowsevents.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 9f2eff3f7..524e67adf 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -559,10 +559,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) GetKeyboardState(keyboardState); if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) { - WORD repetition; - for (repetition = lParam & 0xffff; repetition > 0; repetition--) { - WIN_ConvertUTF32toUTF8(utf32, text); - SDL_SendKeyboardText(text); + if (WIN_ConvertUTF32toUTF8(utf32, text)) { + WORD repetition; + for (repetition = lParam & 0xffff; repetition > 0; repetition--) { + SDL_SendKeyboardText(text); + } } } } From bde0ce09691a205c0ef99921d26b864b2ba3d93a Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Wed, 11 Mar 2015 21:14:21 +0100 Subject: [PATCH 066/142] Updated internal documentation comments. --- src/joystick/SDL_sysjoystick.h | 4 ++-- src/joystick/android/SDL_sysjoystick.c | 2 +- src/joystick/darwin/SDL_sysjoystick.c | 4 ++-- src/joystick/dummy/SDL_sysjoystick.c | 2 +- src/joystick/emscripten/SDL_sysjoystick.c | 2 +- src/joystick/haiku/SDL_haikujoystick.cc | 2 +- src/joystick/iphoneos/SDL_sysjoystick.m | 2 +- src/joystick/linux/SDL_sysjoystick.c | 2 +- src/joystick/psp/SDL_sysjoystick.c | 4 ++-- src/joystick/windows/SDL_mmjoystick.c | 2 +- src/joystick/windows/SDL_windowsjoystick.c | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index a39869575..819a961af 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -78,14 +78,14 @@ extern const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index); extern SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index); /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ extern int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index); /* Function to query if the joystick is currently attached - * It returns 1 if attached, 0 otherwise. + * It returns SDL_TRUE if attached, SDL_FALSE otherwise. */ extern SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick); diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index cce94b80c..49fa58428 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -467,7 +467,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 8e641d496..45966b72b 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -646,7 +646,7 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - * The joystick to open is specified by the index field of the joystick. + * The joystick to open is specified by the device index. * This should fill the nbuttons and naxes fields of the joystick structure. * It returns 0, or -1 if there is an error. */ @@ -672,7 +672,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) } /* Function to query if the joystick is currently attached - * It returns 1 if attached, 0 otherwise. + * It returns SDL_TRUE if attached, SDL_FALSE otherwise. */ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick) diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 9baa79500..1d1c16a12 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -61,7 +61,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 0fdbcb9de..5b8267750 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -292,7 +292,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 22c046aad..394804e08 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -106,7 +106,7 @@ extern "C" } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index d67cd0c7a..dd626f207 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -69,7 +69,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index a66091298..d4e42e4c4 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -566,7 +566,7 @@ ConfigJoystick(SDL_Joystick * joystick, int fd) /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index 22bd6e9de..9eae4e259 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -164,7 +164,7 @@ const char *SDL_SYS_JoystickName(int index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ @@ -182,12 +182,12 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick) { return SDL_TRUE; } + /* Function to update the state of a joystick - called as a device poll. * This function shouldn't update the joystick structure directly, * but instead should call SDL_PrivateJoystick*() to deliver events * and update joystick device state. */ - void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) { int i; diff --git a/src/joystick/windows/SDL_mmjoystick.c b/src/joystick/windows/SDL_mmjoystick.c index 0ae344246..7fd555d99 100644 --- a/src/joystick/windows/SDL_mmjoystick.c +++ b/src/joystick/windows/SDL_mmjoystick.c @@ -210,7 +210,7 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 0b2f370b5..3404899fb 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -446,7 +446,7 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) } /* Function to open a joystick for use. - The joystick to open is specified by the index field of the joystick. + The joystick to open is specified by the device index. This should fill the nbuttons and naxes fields of the joystick structure. It returns 0, or -1 if there is an error. */ From ad570bffccb4e1e943167c9453940328629f8c38 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 13 Mar 2015 00:48:30 -0400 Subject: [PATCH 067/142] Removed an unnecessary #ifdef. --- src/audio/SDL_audio.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 2f69335be..43ed6ea0e 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -51,9 +51,7 @@ extern AudioBootStrap QSAAUDIO_bootstrap; extern AudioBootStrap SUNAUDIO_bootstrap; extern AudioBootStrap ARTS_bootstrap; extern AudioBootStrap ESD_bootstrap; -#if SDL_AUDIO_DRIVER_NACL extern AudioBootStrap NACLAUD_bootstrap; -#endif extern AudioBootStrap NAS_bootstrap; extern AudioBootStrap XAUDIO2_bootstrap; extern AudioBootStrap DSOUND_bootstrap; From 3b609feebf03405e57f4be82a49267a7e4df08b4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 13 Mar 2015 12:20:17 -0400 Subject: [PATCH 068/142] Cleaning out a silly coding style I used to use. Changed all the "return (x);" lines to "return x;" --- src/audio/SDL_audio.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 43ed6ea0e..1caac1faf 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -726,7 +726,7 @@ SDL_RunAudio(void *devicep) SDL_StreamDeinit(&device->streamer); #endif - return (0); + return 0; } @@ -759,16 +759,16 @@ SDL_ParseAudioFormat(const char *string) int SDL_GetNumAudioDrivers(void) { - return (SDL_arraysize(bootstrap) - 1); + return SDL_arraysize(bootstrap) - 1; } const char * SDL_GetAudioDriver(int index) { if (index >= 0 && index < SDL_GetNumAudioDrivers()) { - return (bootstrap[index]->name); + return bootstrap[index]->name; } - return (NULL); + return NULL; } int @@ -816,12 +816,12 @@ SDL_AudioInit(const char *driver_name) } SDL_memset(¤t_audio, 0, sizeof(current_audio)); - return (-1); /* No driver was available, so fail. */ + return -1; /* No driver was available, so fail. */ } finalize_audio_entry_points(); - return (0); + return 0; } /* @@ -1294,14 +1294,14 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained) /* Start up the audio driver, if necessary. This is legacy behaviour! */ if (!SDL_WasInit(SDL_INIT_AUDIO)) { if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { - return (-1); + return -1; } } /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */ if (open_devices[0] != NULL) { SDL_SetError("Audio device is already opened"); - return (-1); + return -1; } if (obtained) { @@ -1312,7 +1312,7 @@ SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained) } SDL_assert((id == 0) || (id == 1)); - return ((id == 0) ? -1 : 0); + return (id == 0) ? -1 : 0; } SDL_AudioDeviceID @@ -1336,7 +1336,7 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid) status = SDL_AUDIO_PLAYING; } } - return (status); + return status; } @@ -1472,16 +1472,16 @@ SDL_FirstAudioFormat(SDL_AudioFormat format) } } format_idx_sub = 0; - return (SDL_NextAudioFormat()); + return SDL_NextAudioFormat(); } SDL_AudioFormat SDL_NextAudioFormat(void) { if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) { - return (0); + return 0; } - return (format_list[format_idx][format_idx_sub++]); + return format_list[format_idx][format_idx_sub++]; } void From 37895d5fa7b35fc4d64f226cd5578990d9cf0834 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sun, 15 Mar 2015 19:25:10 +0100 Subject: [PATCH 069/142] Updated name of assert type in test program. --- test/testplatform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testplatform.c b/test/testplatform.c index 232bfe653..068be8efc 100644 --- a/test/testplatform.c +++ b/test/testplatform.c @@ -167,7 +167,7 @@ TestAssertions(SDL_bool verbose) #endif { - const SDL_assert_data *item = SDL_GetAssertionReport(); + const SDL_AssertData *item = SDL_GetAssertionReport(); while (item) { SDL_Log("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n", item->condition, item->function, item->filename, From 93fc5ce8a96d71f3b6dd385ae714fc75be652082 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Tue, 17 Mar 2015 10:22:36 -0400 Subject: [PATCH 070/142] WinRT: ANGLE/OpenGLES-initialization, error message improvements --- src/video/winrt/SDL_winrtopengles.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 20a9a0bc9..f16a5173c 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -85,11 +85,11 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) Microsoft::WRL::ComPtr cpp_display = video_data->winrtEglWindow; _this->egl_data->egl_display = ((eglGetDisplay_Old_Function)_this->egl_data->eglGetDisplay)(cpp_display); if (!_this->egl_data->egl_display) { - return SDL_SetError("Could not get EGL display"); + return SDL_SetError("Could not get Windows 8.0 EGL display"); } if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { - return SDL_SetError("Could not initialize EGL"); + return SDL_SetError("Could not initialize Windows 8.0 EGL"); } } else { /* Declare some ANGLE/EGL initialization property-sets, as suggested by @@ -136,7 +136,7 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) */ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); if (!_this->egl_data->egl_display) { - return SDL_SetError("Could not get EGL display"); + return SDL_SetError("Could not get 10_0 EGL display"); } if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) @@ -161,7 +161,7 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) } if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { - return SDL_SetError("Could not initialize EGL"); + return SDL_SetError("Could not initialize WinRT 8.x+ EGL"); } } } From 7be22f39a927fc5c9deab34b6dc8a8ebca6df629 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Tue, 17 Mar 2015 10:25:21 -0400 Subject: [PATCH 071/142] WinRT: another ANGLE/OpenGL-initialization, error messaging tweak --- src/video/winrt/SDL_winrtopengles.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index f16a5173c..48e6cb53d 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -136,7 +136,7 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) */ _this->egl_data->egl_display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); if (!_this->egl_data->egl_display) { - return SDL_SetError("Could not get 10_0 EGL display"); + return SDL_SetError("Could not get 10_0+ EGL display"); } if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) From 0c003b66c44ecb1a0074fb2eb484ed471555ab9b Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Tue, 17 Mar 2015 19:45:47 -0400 Subject: [PATCH 072/142] WinRT: made OpenGL window-init work with latest round of ANGLE/WinRT updates Various constants in ANGLE/WinRT, both in MSOpenTech's ms-master branch, and in Google's branch, were changed again. This change makes SDL/WinRT work with them. To note, the ms-master branch (of ANGLE) was updated via this merge: https://github.com/MSOpenTech/angle/commit/bbd2eb0a9c453a941f2c7abacf616d5a66b6be92#diff-d1377fbe747de154e1bfcf7221d3de67 --- src/video/winrt/SDL_winrtopengles.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/video/winrt/SDL_winrtopengles.cpp b/src/video/winrt/SDL_winrtopengles.cpp index 48e6cb53d..4c7199824 100644 --- a/src/video/winrt/SDL_winrtopengles.cpp +++ b/src/video/winrt/SDL_winrtopengles.cpp @@ -36,13 +36,15 @@ using namespace Windows::UI::Core; /* ANGLE/WinRT constants */ static const int ANGLE_D3D_FEATURE_LEVEL_ANY = 0; -#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 -#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203 -#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204 -#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205 -#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207 -#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209 +#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B +#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F + #define EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER 0x320B @@ -98,7 +100,8 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) const EGLint defaultDisplayAttributes[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -107,15 +110,17 @@ WINRT_GLES_LoadLibrary(_THIS, const char *path) EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, - EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; const EGLint warpDisplayAttributes[] = { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, - EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, - EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, + EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, + EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; From 317ab8a96aae01984ade40eb9f7ff5a1a8d25d87 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 00:56:33 -0400 Subject: [PATCH 073/142] Fixed a compiler warning. --- src/test/SDL_test_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c index 4022d20df..9b1d2914c 100644 --- a/src/test/SDL_test_common.c +++ b/src/test/SDL_test_common.c @@ -1204,10 +1204,10 @@ SDLTest_PrintEvent(SDL_Event * event) event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure); break; case SDL_DOLLARGESTURE: - SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (long long) event->dgesture.gestureId); + SDL_Log("SDL_EVENT: Dollar gesture detect: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId); break; case SDL_DOLLARRECORD: - SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (long long) event->dgesture.gestureId); + SDL_Log("SDL_EVENT: Dollar gesture record: %"SDL_PRIs64, (Sint64) event->dgesture.gestureId); break; case SDL_MULTIGESTURE: SDL_Log("SDL_EVENT: Multi gesture fingers: %d", event->mgesture.numFingers); From f8af9d36b1a1d188eb8d001e998f3ab4d4451608 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 09:59:22 -0400 Subject: [PATCH 074/142] PulseAudio: Added multiple device support, other cleanups. Thanks to Dominik Frizel for most of the effort on this! Fixes Bugzilla #2730. --- src/audio/pulseaudio/SDL_pulseaudio.c | 235 ++++++++++++++++---------- src/audio/pulseaudio/SDL_pulseaudio.h | 1 - 2 files changed, 145 insertions(+), 91 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index c3e1238b4..30bc228bc 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -26,6 +26,7 @@ Stéphan Kochen: stephan .a.t. kochen.nl */ #include "../../SDL_internal.h" +#include "SDL_assert.h" #if SDL_AUDIO_DRIVER_PULSEAUDIO @@ -38,7 +39,6 @@ #include #include #include -#include #include "SDL_timer.h" #include "SDL_audio.h" @@ -66,10 +66,6 @@ static SDL_INLINE int PA_STREAM_IS_GOOD(pa_stream_state_t x) { static const char *(*PULSEAUDIO_pa_get_library_version) (void); -static pa_simple *(*PULSEAUDIO_pa_simple_new) (const char *, const char *, - pa_stream_direction_t, const char *, const char *, const pa_sample_spec *, - const pa_channel_map *, const pa_buffer_attr *, int *); -static void (*PULSEAUDIO_pa_simple_free) (pa_simple *); static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto) ( pa_channel_map *, unsigned, pa_channel_map_def_t); static const char * (*PULSEAUDIO_pa_strerror) (int); @@ -87,6 +83,7 @@ static pa_context * (*PULSEAUDIO_pa_context_new) (pa_mainloop_api *, const char *); static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *, pa_context_flags_t, const pa_spawn_api *); +static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list)(pa_context *, pa_sink_info_cb_t, void *); static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *); static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *); static void (*PULSEAUDIO_pa_context_unref) (pa_context *); @@ -179,8 +176,6 @@ static int load_pulseaudio_syms(void) { SDL_PULSEAUDIO_SYM(pa_get_library_version); - SDL_PULSEAUDIO_SYM(pa_simple_new); - SDL_PULSEAUDIO_SYM(pa_simple_free); SDL_PULSEAUDIO_SYM(pa_mainloop_new); SDL_PULSEAUDIO_SYM(pa_mainloop_get_api); SDL_PULSEAUDIO_SYM(pa_mainloop_iterate); @@ -190,6 +185,7 @@ load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_operation_unref); SDL_PULSEAUDIO_SYM(pa_context_new); SDL_PULSEAUDIO_SYM(pa_context_connect); + SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list); SDL_PULSEAUDIO_SYM(pa_context_get_state); SDL_PULSEAUDIO_SYM(pa_context_disconnect); SDL_PULSEAUDIO_SYM(pa_context_unref); @@ -206,28 +202,96 @@ load_pulseaudio_syms(void) return 0; } - -/* Check to see if we can connect to PulseAudio */ -static SDL_bool -CheckPulseAudioAvailable() +static SDL_INLINE int +squashVersion(const int major, const int minor, const int patch) { - pa_simple *s; - pa_sample_spec ss; + return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF); +} - ss.format = PA_SAMPLE_S16NE; - ss.channels = 1; - ss.rate = 22050; +/* Workaround for older pulse: pa_context_new() must have non-NULL appname */ +static const char * +getAppName(void) +{ + const char *verstr = PULSEAUDIO_pa_get_library_version(); + if (verstr != NULL) { + int maj, min, patch; + if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) { + if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) { + return NULL; /* 0.9.15+ handles NULL correctly. */ + } + } + } + return "SDL Application"; /* oh well. */ +} - s = PULSEAUDIO_pa_simple_new(NULL, "SDL", PA_STREAM_PLAYBACK, NULL, - "Test", &ss, NULL, NULL, NULL); - if (s) { - PULSEAUDIO_pa_simple_free(s); - return SDL_TRUE; - } else { - return SDL_FALSE; +static void +DisconnectFromPulseServer(pa_mainloop *mainloop, pa_context *context) +{ + if (context) { + PULSEAUDIO_pa_context_disconnect(context); + PULSEAUDIO_pa_context_unref(context); + } + if (mainloop != NULL) { + PULSEAUDIO_pa_mainloop_free(mainloop); } } +static int +ConnectToPulseServer_Internal(pa_mainloop **_mainloop, pa_context **_context) +{ + pa_mainloop *mainloop = NULL; + pa_context *context = NULL; + pa_mainloop_api *mainloop_api = NULL; + int state = 0; + + *_mainloop = NULL; + *_context = NULL; + + /* Set up a new main loop */ + if (!(mainloop = PULSEAUDIO_pa_mainloop_new())) { + return SDL_SetError("pa_mainloop_new() failed"); + } + + *_mainloop = mainloop; + + mainloop_api = PULSEAUDIO_pa_mainloop_get_api(mainloop); + SDL_assert(mainloop_api); /* this never fails, right? */ + + context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName()); + if (!context) { + return SDL_SetError("pa_context_new() failed"); + } + *_context = context; + + /* Connect to the PulseAudio server */ + if (PULSEAUDIO_pa_context_connect(context, NULL, 0, NULL) < 0) { + return SDL_SetError("Could not setup connection to PulseAudio"); + } + + do { + if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) { + return SDL_SetError("pa_mainloop_iterate() failed"); + } + state = PULSEAUDIO_pa_context_get_state(context); + if (!PA_CONTEXT_IS_GOOD(state)) { + return SDL_SetError("Could not connect to PulseAudio"); + } + } while (state != PA_CONTEXT_READY); + + return 0; /* connected and ready! */ +} + +static int +ConnectToPulseServer(pa_mainloop **_mainloop, pa_context **_context) +{ + const int retval = ConnectToPulseServer_Internal(_mainloop, _context); + if (retval < 0) { + DisconnectFromPulseServer(*_mainloop, *_context); + } + return retval; +} + + /* This function waits until it is possible to write a full sound buffer */ static void PULSEAUDIO_WaitDevice(_THIS) @@ -307,43 +371,12 @@ PULSEAUDIO_CloseDevice(_THIS) PULSEAUDIO_pa_stream_unref(this->hidden->stream); this->hidden->stream = NULL; } - if (this->hidden->context != NULL) { - PULSEAUDIO_pa_context_disconnect(this->hidden->context); - PULSEAUDIO_pa_context_unref(this->hidden->context); - this->hidden->context = NULL; - } - if (this->hidden->mainloop != NULL) { - PULSEAUDIO_pa_mainloop_free(this->hidden->mainloop); - this->hidden->mainloop = NULL; - } + DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context); SDL_free(this->hidden); this->hidden = NULL; } } - -static SDL_INLINE int -squashVersion(const int major, const int minor, const int patch) -{ - return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF); -} - -/* Workaround for older pulse: pa_context_new() must have non-NULL appname */ -static const char * -getAppName(void) -{ - const char *verstr = PULSEAUDIO_pa_get_library_version(); - if (verstr != NULL) { - int maj, min, patch; - if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) { - if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) { - return NULL; /* 0.9.15+ handles NULL correctly. */ - } - } - } - return "SDL Application"; /* oh well. */ -} - static int PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) { @@ -442,42 +475,16 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) paattr.minreq = h->mixlen; #endif + if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) { + PULSEAUDIO_CloseDevice(this); + return SDL_SetError("Could not connect to PulseAudio server"); + } + /* The SDL ALSA output hints us that we use Windows' channel mapping */ /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels, PA_CHANNEL_MAP_WAVEEX); - /* Set up a new main loop */ - if (!(h->mainloop = PULSEAUDIO_pa_mainloop_new())) { - PULSEAUDIO_CloseDevice(this); - return SDL_SetError("pa_mainloop_new() failed"); - } - - h->mainloop_api = PULSEAUDIO_pa_mainloop_get_api(h->mainloop); - h->context = PULSEAUDIO_pa_context_new(h->mainloop_api, getAppName()); - if (!h->context) { - PULSEAUDIO_CloseDevice(this); - return SDL_SetError("pa_context_new() failed"); - } - - /* Connect to the PulseAudio server */ - if (PULSEAUDIO_pa_context_connect(h->context, NULL, 0, NULL) < 0) { - PULSEAUDIO_CloseDevice(this); - return SDL_SetError("Could not setup connection to PulseAudio"); - } - - do { - if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { - PULSEAUDIO_CloseDevice(this); - return SDL_SetError("pa_mainloop_iterate() failed"); - } - state = PULSEAUDIO_pa_context_get_state(h->context); - if (!PA_CONTEXT_IS_GOOD(state)) { - PULSEAUDIO_CloseDevice(this); - return SDL_SetError("Could not connect to PulseAudio"); - } - } while (state != PA_CONTEXT_READY); - h->stream = PULSEAUDIO_pa_stream_new( h->context, "Simple DirectMedia Layer", /* stream description */ @@ -490,7 +497,7 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) return SDL_SetError("Could not set up PulseAudio stream"); } - if (PULSEAUDIO_pa_stream_connect_playback(h->stream, NULL, &paattr, flags, + if (PULSEAUDIO_pa_stream_connect_playback(h->stream, devname, &paattr, flags, NULL, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not connect PulseAudio stream"); @@ -512,6 +519,50 @@ PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) return 0; } +typedef struct +{ + uint8_t last; + SDL_AddAudioDevice addfn; +} sink_struct; + +static void +get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) +{ + sink_struct *a = (sink_struct *) userdata; + a->last = is_last; + if (i) { + a->addfn(i->name); + } +} + +static void +PULSEAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +{ + pa_mainloop *mainloop = NULL; + pa_context *context = NULL; + + if (ConnectToPulseServer(&mainloop, &context) < 0) { + return; + } + + if (!iscapture) { + sink_struct a; + a.last = 0; + a.addfn = addfn; + pa_operation* o = PULSEAUDIO_pa_context_get_sink_info_list(context, + get_sink_info_callback, &a); + while (!a.last) { + if (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_CANCELLED) { + break; + } + if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) { + break; + } + } + } + + DisconnectFromPulseServer(mainloop, context); +} static void PULSEAUDIO_Deinitialize(void) @@ -522,16 +573,22 @@ PULSEAUDIO_Deinitialize(void) static int PULSEAUDIO_Init(SDL_AudioDriverImpl * impl) { + pa_mainloop *mainloop = NULL; + pa_context *context = NULL; + if (LoadPulseAudioLibrary() < 0) { return 0; } - if (!CheckPulseAudioAvailable()) { + if (ConnectToPulseServer(&mainloop, &context) < 0) { UnloadPulseAudioLibrary(); return 0; } + DisconnectFromPulseServer(mainloop, context); + /* Set the function pointers */ + impl->DetectDevices = PULSEAUDIO_DetectDevices; impl->OpenDevice = PULSEAUDIO_OpenDevice; impl->PlayDevice = PULSEAUDIO_PlayDevice; impl->WaitDevice = PULSEAUDIO_WaitDevice; @@ -539,12 +596,10 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl) impl->CloseDevice = PULSEAUDIO_CloseDevice; impl->WaitDone = PULSEAUDIO_WaitDone; impl->Deinitialize = PULSEAUDIO_Deinitialize; - impl->OnlyHasDefaultOutputDevice = 1; return 1; /* this audio target is available. */ } - AudioBootStrap PULSEAUDIO_bootstrap = { "pulseaudio", "PulseAudio", PULSEAUDIO_Init, 0 }; diff --git a/src/audio/pulseaudio/SDL_pulseaudio.h b/src/audio/pulseaudio/SDL_pulseaudio.h index a75409bc0..d587318d7 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/src/audio/pulseaudio/SDL_pulseaudio.h @@ -34,7 +34,6 @@ struct SDL_PrivateAudioData { /* pulseaudio structures */ pa_mainloop *mainloop; - pa_mainloop_api *mainloop_api; pa_context *context; pa_stream *stream; From 466c8a104be7472ea4b78ccf50070ac17639e3f1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 10:05:36 -0400 Subject: [PATCH 075/142] Patched to compile on C89 compilers. --- src/audio/pulseaudio/SDL_pulseaudio.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 30bc228bc..915d5d6db 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -546,10 +546,8 @@ PULSEAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) } if (!iscapture) { - sink_struct a; - a.last = 0; - a.addfn = addfn; - pa_operation* o = PULSEAUDIO_pa_context_get_sink_info_list(context, + sink_struct a = { 0, addfn }; + pa_operation *o = PULSEAUDIO_pa_context_get_sink_info_list(context, get_sink_info_callback, &a); while (!a.last) { if (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_CANCELLED) { From 6a1d79c7cd9d2dfc1da79f2d6d723ac6d78ad0d0 Mon Sep 17 00:00:00 2001 From: David Ludwig Date: Wed, 18 Mar 2015 12:03:32 -0400 Subject: [PATCH 076/142] WinRT: updated names, and references-to, various ANGLE/WinRT repositories --- docs/README-winrt.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/README-winrt.md b/docs/README-winrt.md index e188d7791..75cd7cd2b 100644 --- a/docs/README-winrt.md +++ b/docs/README-winrt.md @@ -90,10 +90,12 @@ Here is a rough list of what works, and what doens't: * keyboard input. Most of WinRT's documented virtual keys are supported, as well as many keys with documented hardware scancodes. * OpenGL. Experimental support for OpenGL ES 2 is available via the ANGLE - project, using either MS Open Technologies' repository, at - https://github.com/msopentech/angle (both the "winrt" and "future-dev" - branches are supported), or the official ANGLE repository, at - https://chromium.googlesource.com/angle/angle + project, using either: + * MS Open Technologies' "ms-master" repository, at https://github.com/MSOpenTech/angle + (for use with Windows 8.1+ or Windows Phone 8.1+) + * MS Open Technologies' "angle-win8.0" repository, at https://github.com/MSOpenTech/angle-win8.0 + (for Windows 8.0 only!) + * Google's main ANGLE repository, at https://chromium.googlesource.com/angle/angle * SDLmain. WinRT uses a different signature for each app's main() function. SDL-based apps that use this port must compile in SDL_winrt_main_NonXAML.cpp (in `SDL\src\main\winrt\`) directly in order for their C-style main() From 8b4b24c103615fa8d83fcbaf5e60263093e6cafe Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 10:09:23 -0400 Subject: [PATCH 077/142] Tweaked a couple comments, added some FIXMEs. --HG-- extra : rebase_source : 57eb90da4411aba512a3df1af1d60bb6daa72aa6 --- src/audio/SDL_audio.c | 4 +++- src/audio/SDL_sysaudio.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 1caac1faf..a0f96be1d 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -616,6 +616,7 @@ SDL_RunAudio(void *devicep) } /* Read from the callback into the _input_ stream */ + // !!! FIXME: this should be LockDevice. SDL_LockMutex(device->mixer_lock); (*fill) (udata, istream, istream_len); SDL_UnlockMutex(device->mixer_lock); @@ -687,6 +688,7 @@ SDL_RunAudio(void *devicep) } } + /* !!! FIXME: this should be LockDevice. */ SDL_LockMutex(device->mixer_lock); if (device->paused) { SDL_memset(stream, silence, stream_len); @@ -1138,7 +1140,7 @@ open_audio_device(const char *devname, int iscapture, device->paused = 1; device->iscapture = iscapture; - /* Create a semaphore for locking the sound buffers */ + /* Create a mutex for locking the sound buffers */ if (!current_audio.impl.SkipMixerLock) { device->mixer_lock = SDL_CreateMutex(); if (device->mixer_lock == NULL) { diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 4f933205d..972828c28 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -71,6 +71,7 @@ typedef struct SDL_AudioDriverImpl /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */ /* Some flags to push duplicate code into the core and reduce #ifdefs. */ + /* !!! FIXME: these should be SDL_bool */ int ProvidesOwnCallbackThread; int SkipMixerLock; /* !!! FIXME: do we need this anymore? */ int HasCaptureSupport; @@ -125,6 +126,7 @@ struct SDL_AudioDevice SDL_AudioStreamer streamer; /* Current state flags */ + /* !!! FIXME: should be SDL_bool */ int iscapture; int enabled; int paused; @@ -133,7 +135,7 @@ struct SDL_AudioDevice /* Fake audio buffer for when the audio hardware is busy */ Uint8 *fake_stream; - /* A semaphore for locking the mixing buffers */ + /* A mutex for locking the mixing buffers */ SDL_mutex *mixer_lock; /* A thread to feed the audio device */ From 390dd29faa3093f6d15566426918aed4985fd7c7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 10:09:39 -0400 Subject: [PATCH 078/142] Changed some SDL_memset() calls to SDL_zero(). --HG-- extra : rebase_source : b7fa90eeecb5272a753e4d1f395926023266f330 --- src/audio/SDL_audio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index a0f96be1d..4cc2ef546 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -784,8 +784,8 @@ SDL_AudioInit(const char *driver_name) SDL_AudioQuit(); /* shutdown driver if already running. */ } - SDL_memset(¤t_audio, '\0', sizeof(current_audio)); - SDL_memset(open_devices, '\0', sizeof(open_devices)); + SDL_zero(current_audio); + SDL_zero(open_devices); /* Select the proper audio driver */ if (driver_name == NULL) { @@ -801,7 +801,7 @@ SDL_AudioInit(const char *driver_name) } tried_to_init = 1; - SDL_memset(¤t_audio, 0, sizeof(current_audio)); + SDL_zero(current_audio); current_audio.name = backend->name; current_audio.desc = backend->desc; initialized = backend->init(¤t_audio.impl); @@ -817,7 +817,7 @@ SDL_AudioInit(const char *driver_name) } } - SDL_memset(¤t_audio, 0, sizeof(current_audio)); + SDL_zero(current_audio); return -1; /* No driver was available, so fail. */ } From e98dd173b75170ea71d189fc673baba25053f8b9 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Mar 2015 02:11:39 -0400 Subject: [PATCH 079/142] Initial work on audio device hotplug support. This fills in the core pieces and fully implements it for Mac OS X. Most other platforms, at the moment, will report a disconnected device if it fails to write audio, but don't notice if the system's device list changed at all. --HG-- extra : rebase_source : f7e7efbbeecfe58338b0f325340c358c2bdfc402 --- include/SDL_events.h | 19 ++ src/audio/SDL_audio.c | 312 ++++++++++++++++++-------- src/audio/SDL_sysaudio.h | 18 +- src/audio/alsa/SDL_alsa_audio.c | 2 +- src/audio/arts/SDL_artsaudio.c | 4 +- src/audio/bsd/SDL_bsdaudio.c | 4 +- src/audio/coreaudio/SDL_coreaudio.c | 217 ++++++++++++++++-- src/audio/disk/SDL_diskaudio.c | 2 +- src/audio/dsp/SDL_dspaudio.c | 2 +- src/audio/esd/SDL_esdaudio.c | 4 +- src/audio/fusionsound/SDL_fsaudio.c | 2 +- src/audio/paudio/SDL_paudio.c | 4 +- src/audio/pulseaudio/SDL_pulseaudio.c | 4 +- src/audio/qsa/SDL_qsa_audio.c | 2 +- src/audio/sndio/SDL_sndioaudio.c | 2 +- src/audio/sun/SDL_sunaudio.c | 4 +- src/audio/xaudio2/SDL_xaudio2.c | 2 +- test/Makefile.in | 4 + test/testaudiohotplug.c | 182 +++++++++++++++ 19 files changed, 658 insertions(+), 132 deletions(-) create mode 100644 test/testaudiohotplug.c diff --git a/include/SDL_events.h b/include/SDL_events.h index 09ab9c2f2..521b65be1 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -110,6 +110,10 @@ typedef enum SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */ + /* Audio hotplug events */ + SDL_AUDIODEVICEADDED = 0x700, /**< A new audio device is available */ + SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */ + /* Game controller events */ SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */ SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */ @@ -382,6 +386,20 @@ typedef struct SDL_ControllerDeviceEvent Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */ } SDL_ControllerDeviceEvent; +/** + * \brief Audio device event structure (event.adevice.*) + */ +typedef struct SDL_AudioDeviceEvent +{ + Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */ + Uint32 timestamp; + Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */ + Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */ + Uint8 padding1; + Uint8 padding2; + Uint8 padding3; +} SDL_AudioDeviceEvent; + /** * \brief Touch finger event structure (event.tfinger.*) @@ -516,6 +534,7 @@ typedef union SDL_Event SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */ SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */ SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */ + SDL_AudioDeviceEvent adevice; /**< Audio device event data */ SDL_QuitEvent quit; /**< Quit request event data */ SDL_UserEvent user; /**< Custom event data */ SDL_SysWMEvent syswm; /**< System dependent window event data */ diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 4cc2ef546..519e86a22 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -333,6 +333,144 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream) } #endif +/* device hotplug support... */ + +/* this function expects its caller to hold current_audio.detection_lock */ +static int +add_audio_device(const char *_name, char ***_devices, int *_devCount) +{ + char *name = SDL_strdup(_name); + int retval = -1; + + if (name != NULL) { + char **devices = *_devices; + int devCount = *_devCount; + void *ptr = SDL_realloc(devices, (devCount+1) * sizeof(char*)); + if (ptr == NULL) { + SDL_free(name); + } else { + retval = devCount; + devices = (char **) ptr; + devices[devCount++] = name; + *_devices = devices; + *_devCount = devCount; + } + } + + return retval; +} + +static int +add_capture_device(const char *name) +{ + /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/ + return add_audio_device(name, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); +} + +static int +add_output_device(const char *name) +{ + return add_audio_device(name, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); +} + +static void +free_device_list(char ***devices, int *devCount) +{ + int i = *devCount; + if ((i > 0) && (*devices != NULL)) { + while (i--) { + SDL_free((*devices)[i]); + } + } + + SDL_free(*devices); + + *devices = NULL; + *devCount = 0; +} + +static void +perform_full_device_redetect(const int iscapture) +{ + SDL_LockMutex(current_audio.detection_lock); + + if (iscapture) { + if (!current_audio.impl.OnlyHasDefaultOutputDevice) { + free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); + current_audio.impl.DetectDevices(SDL_FALSE, add_output_device); + } + } else { + if ((current_audio.impl.HasCaptureSupport) && (!current_audio.impl.OnlyHasDefaultInputDevice)) { + free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); + current_audio.impl.DetectDevices(SDL_TRUE, add_capture_device); + } + } + + SDL_UnlockMutex(current_audio.detection_lock); +} + +/* The audio backends call this when a new device is plugged in. */ +void +SDL_AudioDeviceConnected(const int iscapture, const char *name) +{ + int device_index = -1; + + SDL_LockMutex(current_audio.detection_lock); + if (iscapture) { + device_index = add_capture_device(name); + } else { + device_index = add_output_device(name); + } + SDL_UnlockMutex(current_audio.detection_lock); + + if (device_index != -1) { + /* Post the event, if desired */ + if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) { + SDL_Event event; + event.adevice.type = SDL_AUDIODEVICEADDED; + event.adevice.which = device_index; + event.adevice.iscapture = iscapture; + SDL_PushEvent(&event); + } + } +} + +/* The audio backends call this when a device is unplugged. */ +void +SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device) +{ + /* device==NULL means an unopened device was lost; do the redetect only. */ + if (device != NULL) { + SDL_assert(get_audio_device(device->id) == device); + SDL_assert(device->enabled); /* called more than once?! */ + + /* Ends the audio callback and mark the device as STOPPED, but the + app still needs to close the device to free resources. */ + current_audio.impl.LockDevice(device); + device->enabled = 0; + current_audio.impl.UnlockDevice(device); + + /* Post the event, if desired */ + if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) { + SDL_Event event; + event.adevice.type = SDL_AUDIODEVICEREMOVED; + event.adevice.which = device->id; + event.adevice.iscapture = device->iscapture ? 1 : 0; + SDL_PushEvent(&event); + } + } + + /* we don't really know which name (if any) was associated with this + device in the device list, so drop the entire list and rebuild it. + (we should probably change the API in 2.1 to make this more clear?) */ + if (iscapture) { + current_audio.need_capture_device_redetect = SDL_TRUE; + } else { + current_audio.need_output_device_redetect = SDL_TRUE; + } +} + + /* buffer queueing support... */ @@ -690,6 +828,13 @@ SDL_RunAudio(void *devicep) /* !!! FIXME: this should be LockDevice. */ SDL_LockMutex(device->mixer_lock); + + /* Check again, in case device was removed while a lock was held. */ + if (!device->enabled) { + SDL_UnlockMutex(device->mixer_lock); + break; + } + if (device->paused) { SDL_memset(stream, silence, stream_len); } else { @@ -821,8 +966,34 @@ SDL_AudioInit(const char *driver_name) return -1; /* No driver was available, so fail. */ } + current_audio.detection_lock = SDL_CreateMutex(); + finalize_audio_entry_points(); + /* Make sure we have a list of devices available at startup. */ + perform_full_device_redetect(SDL_TRUE); + perform_full_device_redetect(SDL_FALSE); + + /* Post an add event for each initial device, if desired */ + if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) { + SDL_Event event; + + SDL_zero(event); + event.adevice.type = SDL_AUDIODEVICEADDED; + + event.adevice.iscapture = 0; + for (i = 0; i < current_audio.outputDeviceCount; i++) { + event.adevice.which = i; + SDL_PushEvent(&event); + } + + event.adevice.iscapture = 1; + for (i = 0; i < current_audio.inputDeviceCount; i++) { + event.adevice.which = i; + SDL_PushEvent(&event); + } + } + return 0; } @@ -835,53 +1006,6 @@ SDL_GetCurrentAudioDriver() return current_audio.name; } -static void -free_device_list(char ***devices, int *devCount) -{ - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); - } - } - - SDL_free(*devices); - - *devices = NULL; - *devCount = 0; -} - -static -void SDL_AddCaptureAudioDevice(const char *_name) -{ - char *name = NULL; - void *ptr = SDL_realloc(current_audio.inputDevices, - (current_audio.inputDeviceCount+1) * sizeof(char*)); - if (ptr == NULL) { - return; /* oh well. */ - } - - current_audio.inputDevices = (char **) ptr; - name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ - current_audio.inputDevices[current_audio.inputDeviceCount++] = name; -} - -static -void SDL_AddOutputAudioDevice(const char *_name) -{ - char *name = NULL; - void *ptr = SDL_realloc(current_audio.outputDevices, - (current_audio.outputDeviceCount+1) * sizeof(char*)); - if (ptr == NULL) { - return; /* oh well. */ - } - - current_audio.outputDevices = (char **) ptr; - name = SDL_strdup(_name); /* if this returns NULL, that's okay. */ - current_audio.outputDevices[current_audio.outputDeviceCount++] = name; -} - - int SDL_GetNumAudioDevices(int iscapture) { @@ -903,18 +1027,20 @@ SDL_GetNumAudioDevices(int iscapture) return 1; } - if (iscapture) { - free_device_list(¤t_audio.inputDevices, - ¤t_audio.inputDeviceCount); - current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice); - retval = current_audio.inputDeviceCount; - } else { - free_device_list(¤t_audio.outputDevices, - ¤t_audio.outputDeviceCount); - current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice); - retval = current_audio.outputDeviceCount; + if (current_audio.need_capture_device_redetect) { + current_audio.need_capture_device_redetect = SDL_FALSE; + perform_full_device_redetect(SDL_TRUE); } + if (current_audio.need_output_device_redetect) { + current_audio.need_output_device_redetect = SDL_FALSE; + perform_full_device_redetect(SDL_FALSE); + } + + SDL_LockMutex(current_audio.detection_lock); + retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount; + SDL_UnlockMutex(current_audio.detection_lock); + return retval; } @@ -922,6 +1048,8 @@ SDL_GetNumAudioDevices(int iscapture) const char * SDL_GetAudioDeviceName(int index, int iscapture) { + const char *retval = NULL; + if (!SDL_WasInit(SDL_INIT_AUDIO)) { SDL_SetError("Audio subsystem is not initialized"); return NULL; @@ -950,16 +1078,18 @@ SDL_GetAudioDeviceName(int index, int iscapture) return DEFAULT_OUTPUT_DEVNAME; } - if (iscapture) { - if (index >= current_audio.inputDeviceCount) { - goto no_such_device; - } - return current_audio.inputDevices[index]; - } else { - if (index >= current_audio.outputDeviceCount) { - goto no_such_device; - } - return current_audio.outputDevices[index]; + SDL_LockMutex(current_audio.detection_lock); + if (iscapture && (index < current_audio.inputDeviceCount)) { + retval = current_audio.inputDevices[index]; + } else if (!iscapture && (index < current_audio.outputDeviceCount)) { + retval = current_audio.outputDevices[index]; + } + SDL_UnlockMutex(current_audio.detection_lock); + + /* !!! FIXME: a device could be removed after being returned here, freeing retval's pointer. */ + + if (retval != NULL) { + return retval; } no_such_device: @@ -1077,6 +1207,18 @@ open_audio_device(const char *devname, int iscapture, return 0; } + /* Find an available device ID... */ + for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) { + if (open_devices[id] == NULL) { + break; + } + } + + if (id == SDL_arraysize(open_devices)) { + SDL_SetError("Too many open audio devices"); + return 0; + } + if (!obtained) { obtained = &_obtained; } @@ -1135,6 +1277,7 @@ open_audio_device(const char *devname, int iscapture, return 0; } SDL_zerop(device); + device->id = id + 1; device->spec = *obtained; device->enabled = 1; device->paused = 1; @@ -1150,12 +1293,6 @@ open_audio_device(const char *devname, int iscapture, } } - /* force a device detection if we haven't done one yet. */ - if ( ((iscapture) && (current_audio.inputDevices == NULL)) || - ((!iscapture) && (current_audio.outputDevices == NULL)) ) { - SDL_GetNumAudioDevices(iscapture); - } - if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) { close_audio_device(device); return 0; @@ -1247,25 +1384,14 @@ open_audio_device(const char *devname, int iscapture, device->spec.userdata = device; } - /* Find an available device ID and store the structure... */ - for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) { - if (open_devices[id] == NULL) { - open_devices[id] = device; - break; - } - } - - if (id == SDL_arraysize(open_devices)) { - SDL_SetError("Too many open audio devices"); - close_audio_device(device); - return 0; - } + /* add it to our list of open devices. */ + open_devices[id] = device; /* Start the audio thread if necessary */ if (!current_audio.impl.ProvidesOwnCallbackThread) { /* Start the audio thread */ char name[64]; - SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1)); + SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id); /* !!! FIXME: this is nasty. */ #if defined(__WIN32__) && !defined(HAVE_LIBC) #undef SDL_CreateThread @@ -1278,13 +1404,13 @@ open_audio_device(const char *devname, int iscapture, device->thread = SDL_CreateThread(SDL_RunAudio, name, device); #endif if (device->thread == NULL) { - SDL_CloseAudioDevice(id + 1); + SDL_CloseAudioDevice(device->id); SDL_SetError("Couldn't create audio thread"); return 0; } } - return id + 1; + return device->id; } @@ -1431,12 +1557,16 @@ SDL_AudioQuit(void) /* Free the driver data */ current_audio.impl.Deinitialize(); + free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); - SDL_memset(¤t_audio, '\0', sizeof(current_audio)); - SDL_memset(open_devices, '\0', sizeof(open_devices)); + + SDL_DestroyMutex(current_audio.detection_lock); + + SDL_zero(current_audio); + SDL_zero(open_devices); } #define NUM_FORMATS 10 diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 972828c28..55cb2ecce 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -31,7 +31,16 @@ typedef struct SDL_AudioDevice SDL_AudioDevice; #define _THIS SDL_AudioDevice *_this /* Used by audio targets during DetectDevices() */ -typedef void (*SDL_AddAudioDevice)(const char *name); +typedef int (*SDL_AddAudioDevice)(const char *name); + +/* Audio targets should call this as devices are hotplugged. Don't call + during DetectDevices(), this is for hotplugging a device later. */ +extern void SDL_AudioDeviceConnected(const int iscapture, const char *name); + +/* Audio targets should call this as devices are unplugged. + (device) can be NULL if an unopened device is lost. */ +extern void SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device); + /* This is the size of a packet when using SDL_QueueAudio(). We allocate these as necessary and pool them, under the assumption that we'll @@ -92,6 +101,12 @@ typedef struct SDL_AudioDriver SDL_AudioDriverImpl impl; + /* A mutex for device detection */ + SDL_mutex *detection_lock; + + SDL_bool need_capture_device_redetect; + SDL_bool need_output_device_redetect; + char **outputDevices; int outputDeviceCount; @@ -114,6 +129,7 @@ struct SDL_AudioDevice { /* * * */ /* Data common to all devices */ + SDL_AudioDeviceID id; /* The current audio specification (shared with audio thread) */ SDL_AudioSpec spec; diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index 1f3def3f6..b600474d2 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -320,7 +320,7 @@ ALSA_PlayDevice(_THIS) /* Hmm, not much we can do - abort */ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", ALSA_snd_strerror(status)); - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); return; } continue; diff --git a/src/audio/arts/SDL_artsaudio.c b/src/audio/arts/SDL_artsaudio.c index 72fba70cc..7a8cf6605 100644 --- a/src/audio/arts/SDL_artsaudio.c +++ b/src/audio/arts/SDL_artsaudio.c @@ -151,7 +151,7 @@ ARTS_WaitDevice(_THIS) /* Check every 10 loops */ if (this->hidden->parent && (((++cnt) % 10) == 0)) { if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } } @@ -179,7 +179,7 @@ ARTS_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); diff --git a/src/audio/bsd/SDL_bsdaudio.c b/src/audio/bsd/SDL_bsdaudio.c index f415fe040..2488bef6c 100644 --- a/src/audio/bsd/SDL_bsdaudio.c +++ b/src/audio/bsd/SDL_bsdaudio.c @@ -150,7 +150,7 @@ BSDAUDIO_WaitDevice(_THIS) the user know what happened. */ fprintf(stderr, "SDL: %s\n", message); - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); /* Don't try to close - may hang */ this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO @@ -195,7 +195,7 @@ BSDAUDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); diff --git a/src/audio/coreaudio/SDL_coreaudio.c b/src/audio/coreaudio/SDL_coreaudio.c index a263ae441..5493d3c59 100644 --- a/src/audio/coreaudio/SDL_coreaudio.c +++ b/src/audio/coreaudio/SDL_coreaudio.c @@ -40,13 +40,50 @@ static void COREAUDIO_CloseDevice(_THIS); } #if MACOSX_COREAUDIO -typedef void (*addDevFn)(const char *name, AudioDeviceID devId, void *data); +static const AudioObjectPropertyAddress devlist_address = { + kAudioHardwarePropertyDevices, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster +}; + +typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data); + +typedef struct AudioDeviceList +{ + AudioDeviceID devid; + SDL_bool alive; + struct AudioDeviceList *next; +} AudioDeviceList; + +static AudioDeviceList *output_devs = NULL; +static AudioDeviceList *capture_devs = NULL; + +static SDL_bool +add_to_internal_dev_list(const int iscapture, AudioDeviceID devId) +{ + AudioDeviceList *item = (AudioDeviceList *) SDL_malloc(sizeof (AudioDeviceList)); + if (item == NULL) { + return SDL_FALSE; + } + item->devid = devId; + item->alive = SDL_TRUE; + item->next = iscapture ? capture_devs : output_devs; + if (iscapture) { + capture_devs = item; + } else { + output_devs = item; + } + + return SDL_TRUE; +} static void -addToDevList(const char *name, AudioDeviceID devId, void *data) +addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data) { SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data; - addfn(name); + if (add_to_internal_dev_list(iscapture, devId)) { + addfn(name); + } } typedef struct @@ -57,7 +94,7 @@ typedef struct } FindDevIdData; static void -findDevId(const char *name, AudioDeviceID devId, void *_data) +findDevId(const char *name, const int iscapture, AudioDeviceID devId, void *_data) { FindDevIdData *data = (FindDevIdData *) _data; if (!data->found) { @@ -77,14 +114,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata) UInt32 i = 0; UInt32 max = 0; - AudioObjectPropertyAddress addr = { - kAudioHardwarePropertyDevices, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - - result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &addr, - 0, NULL, &size); + result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, + &devlist_address, 0, NULL, &size); if (result != kAudioHardwareNoError) return; @@ -92,8 +123,8 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata) if (devs == NULL) return; - result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, - 0, NULL, &size, devs); + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, + &devlist_address, 0, NULL, &size, devs); if (result != kAudioHardwareNoError) return; @@ -105,10 +136,17 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata) AudioBufferList *buflist = NULL; int usable = 0; CFIndex len = 0; + const AudioObjectPropertyAddress addr = { + kAudioDevicePropertyStreamConfiguration, + iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyElementMaster + }; - addr.mScope = iscapture ? kAudioDevicePropertyScopeInput : - kAudioDevicePropertyScopeOutput; - addr.mSelector = kAudioDevicePropertyStreamConfiguration; + const AudioObjectPropertyAddress nameaddr = { + kAudioObjectPropertyName, + iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + kAudioObjectPropertyElementMaster + }; result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size); if (result != noErr) @@ -136,9 +174,9 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata) if (!usable) continue; - addr.mSelector = kAudioObjectPropertyName; + size = sizeof (CFStringRef); - result = AudioObjectGetPropertyData(dev, &addr, 0, NULL, &size, &cfstr); + result = AudioObjectGetPropertyData(dev, &nameaddr, 0, NULL, &size, &cfstr); if (result != kAudioHardwareNoError) continue; @@ -169,18 +207,96 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata) ((iscapture) ? "capture" : "output"), (int) *devCount, ptr, (int) dev); #endif - addfn(ptr, dev, addfndata); + addfn(ptr, iscapture, dev, addfndata); } SDL_free(ptr); /* addfn() would have copied the string. */ } } +static void +free_audio_device_list(AudioDeviceList **list) +{ + AudioDeviceList *item = *list; + while (item) { + AudioDeviceList *next = item->next; + SDL_free(item); + item = next; + } + *list = NULL; +} + static void COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) { + free_audio_device_list(iscapture ? &capture_devs : &output_devs); build_device_list(iscapture, addToDevList, addfn); } +static void +build_device_change_list(const char *name, const int iscapture, AudioDeviceID devId, void *data) +{ + AudioDeviceList **list = (AudioDeviceList **) data; + AudioDeviceList *item; + for (item = *list; item != NULL; item = item->next) { + if (item->devid == devId) { + item->alive = SDL_TRUE; + return; + } + } + + add_to_internal_dev_list(iscapture, devId); /* new device, add it. */ + SDL_AudioDeviceConnected(iscapture, name); +} + +static SDL_bool +reprocess_device_list(const int iscapture, AudioDeviceList **list) +{ + SDL_bool was_disconnect = SDL_FALSE; + AudioDeviceList *item; + AudioDeviceList *prev = NULL; + for (item = *list; item != NULL; item = item->next) { + item->alive = SDL_FALSE; + } + + build_device_list(iscapture, build_device_change_list, list); + + /* free items in the list that aren't still alive. */ + item = *list; + while (item != NULL) { + AudioDeviceList *next = item->next; + if (item->alive) { + prev = item; + } else { + was_disconnect = SDL_TRUE; + if (prev) { + prev->next = item->next; + } else { + *list = item->next; + } + SDL_free(item); + } + item = next; + } + + return was_disconnect; +} + + +/* this is called when the system's list of available audio devices changes. */ +static OSStatus +device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data) +{ + if (reprocess_device_list(SDL_TRUE, &capture_devs)) { + SDL_AudioDeviceDisconnected(SDL_TRUE, NULL); + } + + if (reprocess_device_list(SDL_FALSE, &output_devs)) { + SDL_AudioDeviceDisconnected(SDL_FALSE, NULL); + } + + return 0; +} + static int find_device_by_name(_THIS, const char *devname, int iscapture) { @@ -317,11 +433,54 @@ inputCallback(void *inRefCon, } +#if MACOSX_COREAUDIO +static const AudioObjectPropertyAddress alive_address = +{ + kAudioDevicePropertyDeviceIsAlive, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster +}; + +static OSStatus +device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data) +{ + SDL_AudioDevice *this = (SDL_AudioDevice *) data; + SDL_bool dead = SDL_FALSE; + UInt32 isAlive = 1; + UInt32 size = sizeof (isAlive); + OSStatus error; + + if (!this->enabled) { + return 0; /* already known to be dead. */ + } + + error = AudioObjectGetPropertyData(this->hidden->deviceID, &alive_address, + 0, NULL, &size, &isAlive); + + if (error == kAudioHardwareBadDeviceError) { + dead = SDL_TRUE; /* device was unplugged. */ + } else if ((error == kAudioHardwareNoError) && (!isAlive)) { + dead = SDL_TRUE; /* device died in some other way. */ + } + + if (dead) { + SDL_AudioDeviceDisconnected(this->iscapture, this); + } + + return 0; +} +#endif + static void COREAUDIO_CloseDevice(_THIS) { if (this->hidden != NULL) { if (this->hidden->audioUnitOpened) { + #if MACOSX_COREAUDIO + /* Unregister our disconnect callback. */ + AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this); + #endif + AURenderCallbackStruct callback; const AudioUnitElement output_bus = 0; const AudioUnitElement input_bus = 1; @@ -355,7 +514,6 @@ COREAUDIO_CloseDevice(_THIS) } } - static int prepare_audiounit(_THIS, const char *devname, int iscapture, const AudioStreamBasicDescription * strdesc) @@ -454,6 +612,11 @@ prepare_audiounit(_THIS, const char *devname, int iscapture, result = AudioOutputUnitStart(this->hidden->audioUnit); CHECK_RESULT("AudioOutputUnitStart"); +#if MACOSX_COREAUDIO + /* Fire a callback if the device stops being "alive" (disconnected, etc). */ + AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this); +#endif + /* We're running! */ return 1; } @@ -527,15 +690,27 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) return 0; /* good to go. */ } +static void +COREAUDIO_Deinitialize(void) +{ +#if MACOSX_COREAUDIO + AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL); + free_audio_device_list(&capture_devs); + free_audio_device_list(&output_devs); +#endif +} + static int COREAUDIO_Init(SDL_AudioDriverImpl * impl) { /* Set the function pointers */ impl->OpenDevice = COREAUDIO_OpenDevice; impl->CloseDevice = COREAUDIO_CloseDevice; + impl->Deinitialize = COREAUDIO_Deinitialize; #if MACOSX_COREAUDIO impl->DetectDevices = COREAUDIO_DetectDevices; + AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL); #else impl->OnlyHasDefaultOutputDevice = 1; diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index cc4e3efc6..4b9214819 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -71,7 +71,7 @@ DISKAUD_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written != this->hidden->mixlen) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index eea5a5f86..5807a571c 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -270,7 +270,7 @@ DSP_PlayDevice(_THIS) const int mixlen = this->hidden->mixlen; if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) { perror("Audio write"); - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); diff --git a/src/audio/esd/SDL_esdaudio.c b/src/audio/esd/SDL_esdaudio.c index e675272dc..69c672a70 100644 --- a/src/audio/esd/SDL_esdaudio.c +++ b/src/audio/esd/SDL_esdaudio.c @@ -129,7 +129,7 @@ ESD_WaitDevice(_THIS) /* Check every 10 loops */ if (this->hidden->parent && (((++cnt) % 10) == 0)) { if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } } @@ -161,7 +161,7 @@ ESD_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } diff --git a/src/audio/fusionsound/SDL_fsaudio.c b/src/audio/fusionsound/SDL_fsaudio.c index b8367715f..643002dc6 100644 --- a/src/audio/fusionsound/SDL_fsaudio.c +++ b/src/audio/fusionsound/SDL_fsaudio.c @@ -143,7 +143,7 @@ SDL_FS_PlayDevice(_THIS) this->hidden->mixsamples); /* If we couldn't write, assume fatal error for now */ if (ret) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); diff --git a/src/audio/paudio/SDL_paudio.c b/src/audio/paudio/SDL_paudio.c index 032d8d2cd..d3c2d82b1 100644 --- a/src/audio/paudio/SDL_paudio.c +++ b/src/audio/paudio/SDL_paudio.c @@ -176,7 +176,7 @@ PAUDIO_WaitDevice(_THIS) * the user know what happened. */ fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); /* Don't try to close - may hang */ this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO @@ -212,7 +212,7 @@ PAUDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 915d5d6db..e108280b9 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -302,7 +302,7 @@ PULSEAUDIO_WaitDevice(_THIS) if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY || PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY || PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); return; } if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) { @@ -318,7 +318,7 @@ PULSEAUDIO_PlayDevice(_THIS) struct SDL_PrivateAudioData *h = this->hidden; if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } diff --git a/src/audio/qsa/SDL_qsa_audio.c b/src/audio/qsa/SDL_qsa_audio.c index d6b8a6800..4121204ab 100644 --- a/src/audio/qsa/SDL_qsa_audio.c +++ b/src/audio/qsa/SDL_qsa_audio.c @@ -300,7 +300,7 @@ QSA_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (towrite != 0) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index 5c0636500..e4a85a73b 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -158,7 +158,7 @@ SNDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if ( written == 0 ) { - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); diff --git a/src/audio/sun/SDL_sunaudio.c b/src/audio/sun/SDL_sunaudio.c index 7efe30ece..569f9ba1d 100644 --- a/src/audio/sun/SDL_sunaudio.c +++ b/src/audio/sun/SDL_sunaudio.c @@ -158,7 +158,7 @@ SUNAUDIO_PlayDevice(_THIS) if (write(this->hidden->audio_fd, this->hidden->ulaw_buf, this->hidden->fragsize) < 0) { /* Assume fatal error, for now */ - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } this->hidden->written += this->hidden->fragsize; } else { @@ -168,7 +168,7 @@ SUNAUDIO_PlayDevice(_THIS) if (write(this->hidden->audio_fd, this->hidden->mixbuf, this->spec.size) < 0) { /* Assume fatal error, for now */ - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } this->hidden->written += this->hidden->fragsize; } diff --git a/src/audio/xaudio2/SDL_xaudio2.c b/src/audio/xaudio2/SDL_xaudio2.c index 85ac14602..37fdf593b 100644 --- a/src/audio/xaudio2/SDL_xaudio2.c +++ b/src/audio/xaudio2/SDL_xaudio2.c @@ -221,7 +221,7 @@ XAUDIO2_PlayDevice(_THIS) if (result != S_OK) { /* uhoh, panic! */ IXAudio2SourceVoice_FlushSourceBuffers(source); - this->enabled = 0; + SDL_AudioDeviceDisconnected(SDL_FALSE, this); } } diff --git a/test/Makefile.in b/test/Makefile.in index 078e4eb99..1a8cec614 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -38,6 +38,7 @@ TARGETS = \ testloadso$(EXE) \ testlock$(EXE) \ testmultiaudio$(EXE) \ + testaudiohotplug$(EXE) \ testnative$(EXE) \ testoverlay2$(EXE) \ testplatform$(EXE) \ @@ -105,6 +106,9 @@ testautomation$(EXE): $(srcdir)/testautomation.c \ testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +testaudiohotplug$(EXE): $(srcdir)/testaudiohotplug.c + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + testatomic$(EXE): $(srcdir)/testatomic.c $(CC) -o $@ $^ $(CFLAGS) $(LIBS) diff --git a/test/testaudiohotplug.c b/test/testaudiohotplug.c new file mode 100644 index 000000000..08bfa74de --- /dev/null +++ b/test/testaudiohotplug.c @@ -0,0 +1,182 @@ +/* + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ + +/* Program to test hotplugging of audio devices */ + +#include "SDL_config.h" + +#include +#include + +#if HAVE_SIGNAL_H +#include +#endif + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include "SDL.h" + +static SDL_AudioSpec spec; +static Uint8 *sound = NULL; /* Pointer to wave data */ +static Uint32 soundlen = 0; /* Length of wave data */ + +static int posindex = 0; +static Uint32 positions[64]; + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void +quit(int rc) +{ + SDL_Quit(); + exit(rc); +} + +void SDLCALL +fillerup(void *_pos, Uint8 * stream, int len) +{ + Uint32 pos = *((Uint32 *) _pos); + Uint8 *waveptr; + int waveleft; + + /* Set up the pointers */ + waveptr = sound + pos; + waveleft = soundlen - pos; + + /* Go! */ + while (waveleft <= len) { + SDL_memcpy(stream, waveptr, waveleft); + stream += waveleft; + len -= waveleft; + waveptr = sound; + waveleft = soundlen; + pos = 0; + } + SDL_memcpy(stream, waveptr, len); + pos += len; + *((Uint32 *) _pos) = pos; +} + +static int done = 0; +void +poked(int sig) +{ + done = 1; +} + +static void +iteration() +{ + SDL_Event e; + SDL_AudioDeviceID dev; + while (SDL_PollEvent(&e)) { + if (e.type == SDL_QUIT) { + done = 1; + } else if (e.type == SDL_AUDIODEVICEADDED) { + const char *name = SDL_GetAudioDeviceName(e.adevice.which, 0); + SDL_Log("New %s audio device: %s\n", e.adevice.iscapture ? "capture" : "output", name); + if (!e.adevice.iscapture) { + positions[posindex] = 0; + spec.userdata = &positions[posindex++]; + spec.callback = fillerup; + dev = SDL_OpenAudioDevice(name, 0, &spec, NULL, 0); + if (!dev) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open '%s': %s\n", name, SDL_GetError()); + } else { + SDL_Log("Opened '%s' as %u\n", name, (unsigned int) dev); + SDL_PauseAudioDevice(dev, 0); + } + } + } else if (e.type == SDL_AUDIODEVICEREMOVED) { + dev = (SDL_AudioDeviceID) e.adevice.which; + SDL_Log("%s device %u removed.\n", e.adevice.iscapture ? "capture" : "output", (unsigned int) dev); + SDL_CloseAudioDevice(dev); + } + } +} + +#ifdef __EMSCRIPTEN__ +void +loop() +{ + if(done) + emscripten_cancel_main_loop(); + else + iteration(); +} +#endif + +int +main(int argc, char *argv[]) +{ + int i; + char filename[4096]; + + /* Enable standard application logging */ + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + /* Load the SDL library */ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); + + if (argc > 1) { + SDL_strlcpy(filename, argv[1], sizeof(filename)); + } else { + SDL_strlcpy(filename, "sample.wav", sizeof(filename)); + } + /* Load the wave file into memory */ + if (SDL_LoadWAV(filename, &spec, &sound, &soundlen) == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", filename, SDL_GetError()); + quit(1); + } + +#if HAVE_SIGNAL_H + /* Set the signals */ +#ifdef SIGHUP + signal(SIGHUP, poked); +#endif + signal(SIGINT, poked); +#ifdef SIGQUIT + signal(SIGQUIT, poked); +#endif + signal(SIGTERM, poked); +#endif /* HAVE_SIGNAL_H */ + + /* Show the list of available drivers */ + SDL_Log("Available audio drivers:"); + for (i = 0; i < SDL_GetNumAudioDrivers(); ++i) { + SDL_Log("%i: %s", i, SDL_GetAudioDriver(i)); + } + + SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); + +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(loop, 0, 1); +#else + while (!done) { + SDL_Delay(100); + iteration(); + } +#endif + + /* Clean up on signal */ + SDL_Quit(); + SDL_FreeWAV(sound); + return (0); +} + +/* vi: set ts=4 sw=4 expandtab: */ From 9fd7d232465c28ff8e8f4442c203e526e5e064da Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 02:01:17 -0400 Subject: [PATCH 080/142] Bunch of reworking to how we manage audio devices. Device enumeration now happens at startup and then is managed exclusively through hotplugging instead of full redetection. The device name list now has a unique "handle" associated with each item and SDL will pass this to the backend so they don't have to figure out how a human readable name maps to real hardware for a second time. Other cleanups, fixes, improvements, plus all the audio backends updated to the new interface...largely untested at this point, though. --HG-- extra : rebase_source : c9a4272788a67deb7a787304ef008188bb40184d --- src/audio/SDL_audio.c | 348 ++++++++++----------- src/audio/SDL_audiodev.c | 34 +- src/audio/SDL_audiodev_c.h | 3 +- src/audio/SDL_sysaudio.h | 47 +-- src/audio/alsa/SDL_alsa_audio.c | 4 +- src/audio/android/SDL_androidaudio.c | 2 +- src/audio/arts/SDL_artsaudio.c | 6 +- src/audio/bsd/SDL_bsdaudio.c | 12 +- src/audio/coreaudio/SDL_coreaudio.c | 177 ++++------- src/audio/directsound/SDL_directsound.c | 65 +--- src/audio/disk/SDL_diskaudio.c | 6 +- src/audio/dsp/SDL_dspaudio.c | 10 +- src/audio/dummy/SDL_dummyaudio.c | 2 +- src/audio/emscripten/SDL_emscriptenaudio.c | 2 +- src/audio/esd/SDL_esdaudio.c | 6 +- src/audio/fusionsound/SDL_fsaudio.c | 4 +- src/audio/haiku/SDL_haikuaudio.cc | 2 +- src/audio/nacl/SDL_naclaudio.c | 6 +- src/audio/nas/SDL_nasaudio.c | 2 +- src/audio/paudio/SDL_paudio.c | 6 +- src/audio/psp/SDL_pspaudio.c | 2 +- src/audio/pulseaudio/SDL_pulseaudio.c | 6 +- src/audio/qsa/SDL_qsa_audio.c | 112 ++----- src/audio/sndio/SDL_sndioaudio.c | 4 +- src/audio/sun/SDL_sunaudio.c | 12 +- src/audio/winmm/SDL_winmm.c | 59 +--- src/audio/xaudio2/SDL_xaudio2.c | 66 ++-- 27 files changed, 430 insertions(+), 575 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 519e86a22..af88bb0e8 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -161,8 +161,16 @@ get_audio_device(SDL_AudioDeviceID id) /* stubs for audio drivers that don't need a specific entry point... */ static void -SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn) -{ /* no-op. */ +SDL_AudioDetectDevices_Default(void) +{ + /* you have to write your own implementation if these assertions fail. */ + SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice); + SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport); + + SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1)); + if (current_audio.impl.HasCaptureSupport) { + SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2)); + } } static void @@ -207,10 +215,16 @@ SDL_AudioDeinitialize_Default(void) { /* no-op. */ } +static void +SDL_AudioFreeDeviceHandle_Default(void *handle) +{ /* no-op. */ +} + + static int -SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture) +SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture) { - return -1; + return SDL_Unsupported(); } static SDL_INLINE SDL_bool @@ -267,6 +281,7 @@ finalize_audio_entry_points(void) FILL_STUB(CloseDevice); FILL_STUB(LockDevice); FILL_STUB(UnlockDevice); + FILL_STUB(FreeDeviceHandle); FILL_STUB(Deinitialize); #undef FILL_STUB } @@ -335,94 +350,64 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream) /* device hotplug support... */ -/* this function expects its caller to hold current_audio.detection_lock */ static int -add_audio_device(const char *_name, char ***_devices, int *_devCount) +add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount) { - char *name = SDL_strdup(_name); int retval = -1; - - if (name != NULL) { - char **devices = *_devices; - int devCount = *_devCount; - void *ptr = SDL_realloc(devices, (devCount+1) * sizeof(char*)); - if (ptr == NULL) { - SDL_free(name); - } else { - retval = devCount; - devices = (char **) ptr; - devices[devCount++] = name; - *_devices = devices; - *_devCount = devCount; - } + const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1; + SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size); + if (item == NULL) { + return -1; } + SDL_assert(handle != NULL); + + item->handle = handle; + SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem)); + + SDL_LockMutex(current_audio.detectionLock); + item->next = *devices; + *devices = item; + retval = (*devCount)++; + SDL_UnlockMutex(current_audio.detectionLock); + return retval; } -static int -add_capture_device(const char *name) +static SDL_INLINE int +add_capture_device(const char *name, void *handle) { /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/ - return add_audio_device(name, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); + return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); } -static int -add_output_device(const char *name) +static SDL_INLINE int +add_output_device(const char *name, void *handle) { - return add_audio_device(name, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); + return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); } static void -free_device_list(char ***devices, int *devCount) +free_device_list(SDL_AudioDeviceItem **devices, int *devCount) { - int i = *devCount; - if ((i > 0) && (*devices != NULL)) { - while (i--) { - SDL_free((*devices)[i]); + SDL_AudioDeviceItem *item, *next; + for (item = *devices; item != NULL; item = next) { + next = item->next; + if (item->handle != NULL) { + current_audio.impl.FreeDeviceHandle(item->handle); } + SDL_free(item); } - - SDL_free(*devices); - *devices = NULL; *devCount = 0; } -static void -perform_full_device_redetect(const int iscapture) -{ - SDL_LockMutex(current_audio.detection_lock); - - if (iscapture) { - if (!current_audio.impl.OnlyHasDefaultOutputDevice) { - free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); - current_audio.impl.DetectDevices(SDL_FALSE, add_output_device); - } - } else { - if ((current_audio.impl.HasCaptureSupport) && (!current_audio.impl.OnlyHasDefaultInputDevice)) { - free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); - current_audio.impl.DetectDevices(SDL_TRUE, add_capture_device); - } - } - - SDL_UnlockMutex(current_audio.detection_lock); -} /* The audio backends call this when a new device is plugged in. */ void -SDL_AudioDeviceConnected(const int iscapture, const char *name) +SDL_AddAudioDevice(const int iscapture, const char *name, void *handle) { - int device_index = -1; - - SDL_LockMutex(current_audio.detection_lock); - if (iscapture) { - device_index = add_capture_device(name); - } else { - device_index = add_output_device(name); - } - SDL_UnlockMutex(current_audio.detection_lock); - + const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle); if (device_index != -1) { /* Post the event, if desired */ if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) { @@ -435,39 +420,51 @@ SDL_AudioDeviceConnected(const int iscapture, const char *name) } } -/* The audio backends call this when a device is unplugged. */ -void -SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device) +/* The audio backends call this when a currently-opened device is lost. */ +void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device) { - /* device==NULL means an unopened device was lost; do the redetect only. */ - if (device != NULL) { - SDL_assert(get_audio_device(device->id) == device); - SDL_assert(device->enabled); /* called more than once?! */ + SDL_assert(get_audio_device(device->id) == device); + SDL_assert(device->enabled); /* called more than once?! */ - /* Ends the audio callback and mark the device as STOPPED, but the - app still needs to close the device to free resources. */ - current_audio.impl.LockDevice(device); - device->enabled = 0; - current_audio.impl.UnlockDevice(device); + /* Ends the audio callback and mark the device as STOPPED, but the + app still needs to close the device to free resources. */ + current_audio.impl.LockDevice(device); + device->enabled = 0; + current_audio.impl.UnlockDevice(device); - /* Post the event, if desired */ - if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) { - SDL_Event event; - event.adevice.type = SDL_AUDIODEVICEREMOVED; - event.adevice.which = device->id; - event.adevice.iscapture = device->iscapture ? 1 : 0; - SDL_PushEvent(&event); + /* Post the event, if desired */ + if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) { + SDL_Event event; + event.adevice.type = SDL_AUDIODEVICEREMOVED; + event.adevice.which = device->id; + event.adevice.iscapture = device->iscapture ? 1 : 0; + SDL_PushEvent(&event); + } +} + +static void +mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag) +{ + SDL_AudioDeviceItem *item; + SDL_assert(handle != NULL); + for (item = devices; item != NULL; item = item->next) { + if (item->handle == handle) { + item->handle = NULL; + *removedFlag = SDL_TRUE; + return; } } +} - /* we don't really know which name (if any) was associated with this - device in the device list, so drop the entire list and rebuild it. - (we should probably change the API in 2.1 to make this more clear?) */ - if (iscapture) { - current_audio.need_capture_device_redetect = SDL_TRUE; - } else { - current_audio.need_output_device_redetect = SDL_TRUE; - } +/* The audio backends call this when a device is removed from the system. */ +void +SDL_RemoveAudioDevice(void *handle) +{ + SDL_LockMutex(current_audio.detectionLock); + mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved); + mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved); + SDL_UnlockMutex(current_audio.detectionLock); + current_audio.impl.FreeDeviceHandle(handle); } @@ -966,33 +963,12 @@ SDL_AudioInit(const char *driver_name) return -1; /* No driver was available, so fail. */ } - current_audio.detection_lock = SDL_CreateMutex(); + current_audio.detectionLock = SDL_CreateMutex(); finalize_audio_entry_points(); /* Make sure we have a list of devices available at startup. */ - perform_full_device_redetect(SDL_TRUE); - perform_full_device_redetect(SDL_FALSE); - - /* Post an add event for each initial device, if desired */ - if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) { - SDL_Event event; - - SDL_zero(event); - event.adevice.type = SDL_AUDIODEVICEADDED; - - event.adevice.iscapture = 0; - for (i = 0; i < current_audio.outputDeviceCount; i++) { - event.adevice.which = i; - SDL_PushEvent(&event); - } - - event.adevice.iscapture = 1; - for (i = 0; i < current_audio.inputDeviceCount; i++) { - event.adevice.which = i; - SDL_PushEvent(&event); - } - } + current_audio.impl.DetectDevices(); return 0; } @@ -1006,6 +982,35 @@ SDL_GetCurrentAudioDriver() return current_audio.name; } +/* Clean out devices that we've removed but had to keep around for stability. */ +static void +clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag) +{ + SDL_AudioDeviceItem *item = *devices; + SDL_AudioDeviceItem *prev = NULL; + int total = 0; + + while (item) { + SDL_AudioDeviceItem *next = item->next; + if (item->handle != NULL) { + total++; + prev = item; + } else { + if (prev) { + prev->next = next; + } else { + *devices = next; + } + SDL_free(item); + } + item = next; + } + + *devCount = total; + *removedFlag = SDL_FALSE; +} + + int SDL_GetNumAudioDevices(int iscapture) { @@ -1015,31 +1020,18 @@ SDL_GetNumAudioDevices(int iscapture) return -1; } - if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) { - return 0; + SDL_LockMutex(current_audio.detectionLock); + if (iscapture && current_audio.captureDevicesRemoved) { + clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved); } - if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { - return 1; + if (!iscapture && current_audio.outputDevicesRemoved) { + clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved); + current_audio.outputDevicesRemoved = SDL_FALSE; } - if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { - return 1; - } - - if (current_audio.need_capture_device_redetect) { - current_audio.need_capture_device_redetect = SDL_FALSE; - perform_full_device_redetect(SDL_TRUE); - } - - if (current_audio.need_output_device_redetect) { - current_audio.need_output_device_redetect = SDL_FALSE; - perform_full_device_redetect(SDL_FALSE); - } - - SDL_LockMutex(current_audio.detection_lock); retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount; - SDL_UnlockMutex(current_audio.detection_lock); + SDL_UnlockMutex(current_audio.detectionLock); return retval; } @@ -1060,41 +1052,28 @@ SDL_GetAudioDeviceName(int index, int iscapture) return NULL; } - if (index < 0) { - goto no_such_device; - } + if (index >= 0) { + SDL_AudioDeviceItem *item; + int i; - if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) { - if (index > 0) { - goto no_such_device; + SDL_LockMutex(current_audio.detectionLock); + item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; + i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount; + if (index < i) { + for (i--; i > index; i--, item = item->next) { + SDL_assert(item != NULL); + } + SDL_assert(item != NULL); + retval = item->name; } - return DEFAULT_INPUT_DEVNAME; + SDL_UnlockMutex(current_audio.detectionLock); } - if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { - if (index > 0) { - goto no_such_device; - } - return DEFAULT_OUTPUT_DEVNAME; + if (retval == NULL) { + SDL_SetError("No such device"); } - SDL_LockMutex(current_audio.detection_lock); - if (iscapture && (index < current_audio.inputDeviceCount)) { - retval = current_audio.inputDevices[index]; - } else if (!iscapture && (index < current_audio.outputDeviceCount)) { - retval = current_audio.outputDevices[index]; - } - SDL_UnlockMutex(current_audio.detection_lock); - - /* !!! FIXME: a device could be removed after being returned here, freeing retval's pointer. */ - - if (retval != NULL) { - return retval; - } - -no_such_device: - SDL_SetError("No such device"); - return NULL; + return retval; } @@ -1195,6 +1174,7 @@ open_audio_device(const char *devname, int iscapture, SDL_AudioSpec _obtained; SDL_AudioDevice *device; SDL_bool build_cvt; + void *handle = NULL; int i = 0; if (!SDL_WasInit(SDL_INIT_AUDIO)) { @@ -1254,9 +1234,7 @@ open_audio_device(const char *devname, int iscapture, return 0; } } - } - - if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { + } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) { if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) { SDL_SetError("No such device"); return 0; @@ -1269,6 +1247,30 @@ open_audio_device(const char *devname, int iscapture, return 0; } } + } else if (devname != NULL) { + /* if the app specifies an exact string, we can pass the backend + an actual device handle thingey, which saves them the effort of + figuring out what device this was (such as, reenumerating + everything again to find the matching human-readable name). + It might still need to open a device based on the string for, + say, a network audio server, but this optimizes some cases. */ + SDL_AudioDeviceItem *item; + SDL_LockMutex(current_audio.detectionLock); + for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) { + if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) { + handle = item->handle; + break; + } + } + SDL_UnlockMutex(current_audio.detectionLock); + } + + if (!current_audio.impl.AllowsArbitraryDeviceNames) { + /* has to be in our device list, or the default device. */ + if ((handle == NULL) && (devname != NULL)) { + SDL_SetError("No such device."); + return 0; + } } device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice)); @@ -1293,7 +1295,7 @@ open_audio_device(const char *devname, int iscapture, } } - if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) { + if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) { close_audio_device(device); return 0; } @@ -1555,15 +1557,13 @@ SDL_AudioQuit(void) } } + free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount); + free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount); + /* Free the driver data */ current_audio.impl.Deinitialize(); - free_device_list(¤t_audio.outputDevices, - ¤t_audio.outputDeviceCount); - free_device_list(¤t_audio.inputDevices, - ¤t_audio.inputDeviceCount); - - SDL_DestroyMutex(current_audio.detection_lock); + SDL_DestroyMutex(current_audio.detectionLock); SDL_zero(current_audio); SDL_zero(open_devices); diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c index e9af62119..4a50c097d 100644 --- a/src/audio/SDL_audiodev.c +++ b/src/audio/SDL_audiodev.c @@ -46,18 +46,21 @@ #define _PATH_DEV_AUDIO "/dev/audio" #endif -static SDL_INLINE void -test_device(const char *fname, int flags, int (*test) (int fd), - SDL_AddAudioDevice addfn) +static void +test_device(const int iscapture, const char *fname, int flags, int (*test) (int fd)) { struct stat sb; if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) { const int audio_fd = open(fname, flags, 0); if (audio_fd >= 0) { - if (test(audio_fd)) { - addfn(fname); - } + const int okay = test(audio_fd); close(audio_fd); + if (okay) { + static size_t dummyhandle = 0; + dummyhandle++; + SDL_assert(dummyhandle != 0); + SDL_AddAudioDevice(iscapture, fname, (void *) dummyhandle); + } } } } @@ -68,11 +71,10 @@ test_stub(int fd) return 1; } -void -SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd), - SDL_AddAudioDevice addfn) +static void +SDL_EnumUnixAudioDevices_Internal(const int iscapture, const int classic, int (*test)(int)) { - const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; const char *audiodev; char audiopath[1024]; @@ -97,17 +99,25 @@ SDL_EnumUnixAudioDevices(int iscapture, int classic, int (*test)(int fd), } } } - test_device(audiodev, flags, test, addfn); + test_device(iscapture, audiodev, flags, test); if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) { int instance = 0; while (instance++ <= 64) { SDL_snprintf(audiopath, SDL_arraysize(audiopath), "%s%d", audiodev, instance); - test_device(audiopath, flags, test, addfn); + test_device(iscapture, audiopath, flags, test); } } } +void +SDL_EnumUnixAudioDevices(const int classic, int (*test)(int)) +{ + SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test); + SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test); +} + #endif /* Audio driver selection */ + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_audiodev_c.h b/src/audio/SDL_audiodev_c.h index 1ad0dc101..3544bfab8 100644 --- a/src/audio/SDL_audiodev_c.h +++ b/src/audio/SDL_audiodev_c.h @@ -33,7 +33,6 @@ #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) #endif -void SDL_EnumUnixAudioDevices(int iscapture, int classic, - int (*test) (int fd), SDL_AddAudioDevice addfn); +extern void SDL_EnumUnixAudioDevices(const int classic, int (*test)(int)); /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 55cb2ecce..fd8e68708 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -30,16 +30,20 @@ typedef struct SDL_AudioDevice SDL_AudioDevice; #define _THIS SDL_AudioDevice *_this -/* Used by audio targets during DetectDevices() */ -typedef int (*SDL_AddAudioDevice)(const char *name); +/* Audio targets should call this as devices are added to the system (such as + a USB headset being plugged in), and should also be called for + for every device found during DetectDevices(). */ +extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle); -/* Audio targets should call this as devices are hotplugged. Don't call - during DetectDevices(), this is for hotplugging a device later. */ -extern void SDL_AudioDeviceConnected(const int iscapture, const char *name); +/* Audio targets should call this as devices are removed, so SDL can update + its list of available devices. */ +extern void SDL_RemoveAudioDevice(void *handle); -/* Audio targets should call this as devices are unplugged. - (device) can be NULL if an unopened device is lost. */ -extern void SDL_AudioDeviceDisconnected(const int iscapture, SDL_AudioDevice *device); +/* Audio targets should call this if an opened audio device is lost while + being used. This can happen due to i/o errors, or a device being unplugged, + etc. If the device is totally gone, please also call SDL_RemoveAudioDevice() + as appropriate so SDL's list of devices is accurate. */ +extern void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device); /* This is the size of a packet when using SDL_QueueAudio(). We allocate @@ -64,8 +68,8 @@ typedef struct SDL_AudioBufferQueue typedef struct SDL_AudioDriverImpl { - void (*DetectDevices) (int iscapture, SDL_AddAudioDevice addfn); - int (*OpenDevice) (_THIS, const char *devname, int iscapture); + void (*DetectDevices) (void); + int (*OpenDevice) (_THIS, void *handle, const char *devname, int iscapture); void (*ThreadInit) (_THIS); /* Called by audio thread at start */ void (*WaitDevice) (_THIS); void (*PlayDevice) (_THIS); @@ -75,6 +79,7 @@ typedef struct SDL_AudioDriverImpl void (*CloseDevice) (_THIS); void (*LockDevice) (_THIS); void (*UnlockDevice) (_THIS); + void (*FreeDeviceHandle) (void *handle); /**< SDL is done with handle from SDL_AddAudioDevice() */ void (*Deinitialize) (void); /* !!! FIXME: add pause(), so we can optimize instead of mixing silence. */ @@ -86,9 +91,18 @@ typedef struct SDL_AudioDriverImpl int HasCaptureSupport; int OnlyHasDefaultOutputDevice; int OnlyHasDefaultInputDevice; + int AllowsArbitraryDeviceNames; } SDL_AudioDriverImpl; +typedef struct SDL_AudioDeviceItem +{ + void *handle; + struct SDL_AudioDeviceItem *next; + char name[]; +} SDL_AudioDeviceItem; + + typedef struct SDL_AudioDriver { /* * * */ @@ -102,16 +116,13 @@ typedef struct SDL_AudioDriver SDL_AudioDriverImpl impl; /* A mutex for device detection */ - SDL_mutex *detection_lock; - - SDL_bool need_capture_device_redetect; - SDL_bool need_output_device_redetect; - - char **outputDevices; + SDL_mutex *detectionLock; + SDL_bool captureDevicesRemoved; + SDL_bool outputDevicesRemoved; int outputDeviceCount; - - char **inputDevices; int inputDeviceCount; + SDL_AudioDeviceItem *outputDevices; + SDL_AudioDeviceItem *inputDevices; } SDL_AudioDriver; diff --git a/src/audio/alsa/SDL_alsa_audio.c b/src/audio/alsa/SDL_alsa_audio.c index b600474d2..216383cae 100644 --- a/src/audio/alsa/SDL_alsa_audio.c +++ b/src/audio/alsa/SDL_alsa_audio.c @@ -320,7 +320,7 @@ ALSA_PlayDevice(_THIS) /* Hmm, not much we can do - abort */ fprintf(stderr, "ALSA write failed (unrecoverable): %s\n", ALSA_snd_strerror(status)); - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); return; } continue; @@ -465,7 +465,7 @@ ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override) } static int -ALSA_OpenDevice(_THIS, const char *devname, int iscapture) +ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { int status = 0; snd_pcm_t *pcm_handle = NULL; diff --git a/src/audio/android/SDL_androidaudio.c b/src/audio/android/SDL_androidaudio.c index fe66763b8..00537baa3 100644 --- a/src/audio/android/SDL_androidaudio.c +++ b/src/audio/android/SDL_androidaudio.c @@ -35,7 +35,7 @@ static SDL_AudioDevice* audioDevice = NULL; static int -AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture) +AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { SDL_AudioFormat test_format; diff --git a/src/audio/arts/SDL_artsaudio.c b/src/audio/arts/SDL_artsaudio.c index 7a8cf6605..628d6e6ec 100644 --- a/src/audio/arts/SDL_artsaudio.c +++ b/src/audio/arts/SDL_artsaudio.c @@ -151,7 +151,7 @@ ARTS_WaitDevice(_THIS) /* Check every 10 loops */ if (this->hidden->parent && (((++cnt) % 10) == 0)) { if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } } @@ -179,7 +179,7 @@ ARTS_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); @@ -229,7 +229,7 @@ ARTS_Suspend(void) } static int -ARTS_OpenDevice(_THIS, const char *devname, int iscapture) +ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { int rc = 0; int bits = 0, frag_spec = 0; diff --git a/src/audio/bsd/SDL_bsdaudio.c b/src/audio/bsd/SDL_bsdaudio.c index 2488bef6c..d1159e995 100644 --- a/src/audio/bsd/SDL_bsdaudio.c +++ b/src/audio/bsd/SDL_bsdaudio.c @@ -51,9 +51,9 @@ static void -BSDAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +BSDAUDIO_DetectDevices(void) { - SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn); + SDL_EnumUnixAudioDevices(0, NULL); } @@ -150,7 +150,7 @@ BSDAUDIO_WaitDevice(_THIS) the user know what happened. */ fprintf(stderr, "SDL: %s\n", message); - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); /* Don't try to close - may hang */ this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO @@ -195,7 +195,7 @@ BSDAUDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); @@ -224,7 +224,7 @@ BSDAUDIO_CloseDevice(_THIS) } static int -BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); SDL_AudioFormat format = 0; @@ -348,6 +348,8 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf; impl->CloseDevice = BSDAUDIO_CloseDevice; + impl->AllowsArbitraryDeviceNames = 1; + return 1; /* this audio target is available. */ } diff --git a/src/audio/coreaudio/SDL_coreaudio.c b/src/audio/coreaudio/SDL_coreaudio.c index 5493d3c59..afd2565dd 100644 --- a/src/audio/coreaudio/SDL_coreaudio.c +++ b/src/audio/coreaudio/SDL_coreaudio.c @@ -80,28 +80,8 @@ add_to_internal_dev_list(const int iscapture, AudioDeviceID devId) static void addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data) { - SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data; if (add_to_internal_dev_list(iscapture, devId)) { - addfn(name); - } -} - -typedef struct -{ - const char *findname; - AudioDeviceID devId; - int found; -} FindDevIdData; - -static void -findDevId(const char *name, const int iscapture, AudioDeviceID devId, void *_data) -{ - FindDevIdData *data = (FindDevIdData *) _data; - if (!data->found) { - if (SDL_strcmp(name, data->findname) == 0) { - data->found = 1; - data->devId = devId; - } + SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId)); } } @@ -226,10 +206,10 @@ free_audio_device_list(AudioDeviceList **list) } static void -COREAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +COREAUDIO_DetectDevices(void) { - free_audio_device_list(iscapture ? &capture_devs : &output_devs); - build_device_list(iscapture, addToDevList, addfn); + build_device_list(SDL_TRUE, addToDevList, NULL); + build_device_list(SDL_FALSE, addToDevList, NULL); } static void @@ -245,13 +225,12 @@ build_device_change_list(const char *name, const int iscapture, AudioDeviceID de } add_to_internal_dev_list(iscapture, devId); /* new device, add it. */ - SDL_AudioDeviceConnected(iscapture, name); + SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId)); } -static SDL_bool +static void reprocess_device_list(const int iscapture, AudioDeviceList **list) { - SDL_bool was_disconnect = SDL_FALSE; AudioDeviceList *item; AudioDeviceList *prev = NULL; for (item = *list; item != NULL; item = item->next) { @@ -267,7 +246,7 @@ reprocess_device_list(const int iscapture, AudioDeviceList **list) if (item->alive) { prev = item; } else { - was_disconnect = SDL_TRUE; + SDL_RemoveAudioDevice((void *) ((size_t) item->devid)); if (prev) { prev->next = item->next; } else { @@ -277,88 +256,16 @@ reprocess_device_list(const int iscapture, AudioDeviceList **list) } item = next; } - - return was_disconnect; } - /* this is called when the system's list of available audio devices changes. */ static OSStatus device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data) { - if (reprocess_device_list(SDL_TRUE, &capture_devs)) { - SDL_AudioDeviceDisconnected(SDL_TRUE, NULL); - } - - if (reprocess_device_list(SDL_FALSE, &output_devs)) { - SDL_AudioDeviceDisconnected(SDL_FALSE, NULL); - } - + reprocess_device_list(SDL_TRUE, &capture_devs); + reprocess_device_list(SDL_FALSE, &output_devs); return 0; } - -static int -find_device_by_name(_THIS, const char *devname, int iscapture) -{ - AudioDeviceID devid = 0; - OSStatus result = noErr; - UInt32 size = 0; - UInt32 alive = 0; - pid_t pid = 0; - - AudioObjectPropertyAddress addr = { - 0, - kAudioObjectPropertyScopeGlobal, - kAudioObjectPropertyElementMaster - }; - - if (devname == NULL) { - size = sizeof (AudioDeviceID); - addr.mSelector = - ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice : - kAudioHardwarePropertyDefaultOutputDevice); - result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, - 0, NULL, &size, &devid); - CHECK_RESULT("AudioHardwareGetProperty (default device)"); - } else { - FindDevIdData data; - SDL_zero(data); - data.findname = devname; - build_device_list(iscapture, findDevId, &data); - if (!data.found) { - SDL_SetError("CoreAudio: No such audio device."); - return 0; - } - devid = data.devId; - } - - addr.mSelector = kAudioDevicePropertyDeviceIsAlive; - addr.mScope = iscapture ? kAudioDevicePropertyScopeInput : - kAudioDevicePropertyScopeOutput; - - size = sizeof (alive); - result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive); - CHECK_RESULT - ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); - - if (!alive) { - SDL_SetError("CoreAudio: requested device exists, but isn't alive."); - return 0; - } - - addr.mSelector = kAudioDevicePropertyHogMode; - size = sizeof (pid); - result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid); - - /* some devices don't support this property, so errors are fine here. */ - if ((result == noErr) && (pid != -1)) { - SDL_SetError("CoreAudio: requested device is being hogged."); - return 0; - } - - this->hidden->deviceID = devid; - return 1; -} #endif /* The CoreAudio callback */ @@ -464,7 +371,7 @@ device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectProperty } if (dead) { - SDL_AudioDeviceDisconnected(this->iscapture, this); + SDL_OpenedAudioDeviceDisconnected(this); } return 0; @@ -514,8 +421,63 @@ COREAUDIO_CloseDevice(_THIS) } } +#if MACOSX_COREAUDIO static int -prepare_audiounit(_THIS, const char *devname, int iscapture, +prepare_device(_THIS, void *handle, int iscapture) +{ + AudioDeviceID devid = (AudioDeviceID) ((size_t) handle); + OSStatus result = noErr; + UInt32 size = 0; + UInt32 alive = 0; + pid_t pid = 0; + + AudioObjectPropertyAddress addr = { + 0, + kAudioObjectPropertyScopeGlobal, + kAudioObjectPropertyElementMaster + }; + + if (handle == NULL) { + size = sizeof (AudioDeviceID); + addr.mSelector = + ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice : + kAudioHardwarePropertyDefaultOutputDevice); + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, + 0, NULL, &size, &devid); + CHECK_RESULT("AudioHardwareGetProperty (default device)"); + } + + addr.mSelector = kAudioDevicePropertyDeviceIsAlive; + addr.mScope = iscapture ? kAudioDevicePropertyScopeInput : + kAudioDevicePropertyScopeOutput; + + size = sizeof (alive); + result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive); + CHECK_RESULT + ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); + + if (!alive) { + SDL_SetError("CoreAudio: requested device exists, but isn't alive."); + return 0; + } + + addr.mSelector = kAudioDevicePropertyHogMode; + size = sizeof (pid); + result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid); + + /* some devices don't support this property, so errors are fine here. */ + if ((result == noErr) && (pid != -1)) { + SDL_SetError("CoreAudio: requested device is being hogged."); + return 0; + } + + this->hidden->deviceID = devid; + return 1; +} +#endif + +static int +prepare_audiounit(_THIS, void *handle, int iscapture, const AudioStreamBasicDescription * strdesc) { OSStatus result = noErr; @@ -534,8 +496,7 @@ prepare_audiounit(_THIS, const char *devname, int iscapture, kAudioUnitScope_Input); #if MACOSX_COREAUDIO - if (!find_device_by_name(this, devname, iscapture)) { - SDL_SetError("Couldn't find requested CoreAudio device"); + if (!prepare_device(this, handle, iscapture)) { return 0; } #endif @@ -623,7 +584,7 @@ prepare_audiounit(_THIS, const char *devname, int iscapture, static int -COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { AudioStreamBasicDescription strdesc; SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); @@ -682,7 +643,7 @@ COREAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; - if (!prepare_audiounit(this, devname, iscapture, &strdesc)) { + if (!prepare_audiounit(this, handle, iscapture, &strdesc)) { COREAUDIO_CloseDevice(this); return -1; /* prepare_audiounit() will call SDL_SetError()... */ } diff --git a/src/audio/directsound/SDL_directsound.c b/src/audio/directsound/SDL_directsound.c index 067683ccc..99e34521f 100644 --- a/src/audio/directsound/SDL_directsound.c +++ b/src/audio/directsound/SDL_directsound.c @@ -144,15 +144,22 @@ SetDSerror(const char *function, int code) return SDL_SetError("%s", errbuf); } +static void +DSOUND_FreeDeviceHandle(void *handle) +{ + SDL_free(handle); +} static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data) { - SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data; + const int iscapture = (int) ((size_t) data); if (guid != NULL) { /* skip default device */ char *str = WIN_StringToUTF8(desc); if (str != NULL) { - addfn(str); + LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID)); + SDL_memcpy(cpyguid, guid, sizeof (GUID)); + SDL_AddAudioDevice(iscapture, str, cpyguid); SDL_free(str); /* addfn() makes a copy of this string. */ } } @@ -160,13 +167,10 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data) } static void -DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +DSOUND_DetectDevices(void) { - if (iscapture) { - pDirectSoundCaptureEnumerateW(FindAllDevs, addfn); - } else { - pDirectSoundEnumerateW(FindAllDevs, addfn); - } + pDirectSoundCaptureEnumerateW(FindAllDevs, (void *) ((size_t) 1)); + pDirectSoundEnumerateW(FindAllDevs, (void *) ((size_t) 0)); } @@ -419,53 +423,14 @@ CreateSecondary(_THIS, HWND focus) return (numchunks); } -typedef struct FindDevGUIDData -{ - const char *devname; - GUID guid; - int found; -} FindDevGUIDData; - -static BOOL CALLBACK -FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data) -{ - if (guid != NULL) { /* skip the default device. */ - FindDevGUIDData *data = (FindDevGUIDData *) _data; - char *str = WIN_StringToUTF8(desc); - const int match = (SDL_strcmp(str, data->devname) == 0); - SDL_free(str); - if (match) { - data->found = 1; - SDL_memcpy(&data->guid, guid, sizeof (data->guid)); - return FALSE; /* found it! stop enumerating. */ - } - } - return TRUE; /* keep enumerating. */ -} - static int -DSOUND_OpenDevice(_THIS, const char *devname, int iscapture) +DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { HRESULT result; SDL_bool valid_format = SDL_FALSE; SDL_bool tried_format = SDL_FALSE; SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); - FindDevGUIDData devguid; - LPGUID guid = NULL; - - if (devname != NULL) { - devguid.found = 0; - devguid.devname = devname; - if (iscapture) - pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid); - else - pDirectSoundEnumerateW(FindDevGUID, &devguid); - - if (!devguid.found) { - return SDL_SetError("DirectSound: Requested device not found"); - } - guid = &devguid.guid; - } + LPGUID guid = (LPGUID) handle; /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) @@ -536,6 +501,8 @@ DSOUND_Init(SDL_AudioDriverImpl * impl) impl->WaitDone = DSOUND_WaitDone; impl->GetDeviceBuf = DSOUND_GetDeviceBuf; impl->CloseDevice = DSOUND_CloseDevice; + impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle; + impl->Deinitialize = DSOUND_Deinitialize; return 1; /* this audio target is available. */ diff --git a/src/audio/disk/SDL_diskaudio.c b/src/audio/disk/SDL_diskaudio.c index 4b9214819..1577b6f23 100644 --- a/src/audio/disk/SDL_diskaudio.c +++ b/src/audio/disk/SDL_diskaudio.c @@ -71,7 +71,7 @@ DISKAUD_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written != this->hidden->mixlen) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); @@ -100,7 +100,7 @@ DISKAUD_CloseDevice(_THIS) } static int -DISKAUD_OpenDevice(_THIS, const char *devname, int iscapture) +DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const char *envr = SDL_getenv(DISKENVR_WRITEDELAY); const char *fname = DISKAUD_GetOutputFilename(devname); @@ -151,6 +151,8 @@ DISKAUD_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = DISKAUD_GetDeviceBuf; impl->CloseDevice = DISKAUD_CloseDevice; + impl->AllowsArbitraryDeviceNames = 1; + return 1; /* this audio target is available. */ } diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c index 5807a571c..0d34e9512 100644 --- a/src/audio/dsp/SDL_dspaudio.c +++ b/src/audio/dsp/SDL_dspaudio.c @@ -51,9 +51,9 @@ static void -DSP_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +DSP_DetectDevices(void) { - SDL_EnumUnixAudioDevices(iscapture, 0, NULL, addfn); + SDL_EnumUnixAudioDevices(0, NULL); } @@ -74,7 +74,7 @@ DSP_CloseDevice(_THIS) static int -DSP_OpenDevice(_THIS, const char *devname, int iscapture) +DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); int format; @@ -270,7 +270,7 @@ DSP_PlayDevice(_THIS) const int mixlen = this->hidden->mixlen; if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) { perror("Audio write"); - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen); @@ -293,6 +293,8 @@ DSP_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = DSP_GetDeviceBuf; impl->CloseDevice = DSP_CloseDevice; + impl->AllowsArbitraryDeviceNames = 1; + return 1; /* this audio target is available. */ } diff --git a/src/audio/dummy/SDL_dummyaudio.c b/src/audio/dummy/SDL_dummyaudio.c index 671e222cf..965b4ce56 100644 --- a/src/audio/dummy/SDL_dummyaudio.c +++ b/src/audio/dummy/SDL_dummyaudio.c @@ -27,7 +27,7 @@ #include "SDL_dummyaudio.h" static int -DUMMYAUD_OpenDevice(_THIS, const char *devname, int iscapture) +DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { return 0; /* always succeeds. */ } diff --git a/src/audio/emscripten/SDL_emscriptenaudio.c b/src/audio/emscripten/SDL_emscriptenaudio.c index f1ae929f3..2147baedb 100644 --- a/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/src/audio/emscripten/SDL_emscriptenaudio.c @@ -151,7 +151,7 @@ Emscripten_CloseDevice(_THIS) } static int -Emscripten_OpenDevice(_THIS, const char *devname, int iscapture) +Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { SDL_bool valid_format = SDL_FALSE; SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); diff --git a/src/audio/esd/SDL_esdaudio.c b/src/audio/esd/SDL_esdaudio.c index 69c672a70..7f18337d9 100644 --- a/src/audio/esd/SDL_esdaudio.c +++ b/src/audio/esd/SDL_esdaudio.c @@ -129,7 +129,7 @@ ESD_WaitDevice(_THIS) /* Check every 10 loops */ if (this->hidden->parent && (((++cnt) % 10) == 0)) { if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } } @@ -161,7 +161,7 @@ ESD_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } @@ -215,7 +215,7 @@ get_progname(void) static int -ESD_OpenDevice(_THIS, const char *devname, int iscapture) +ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { esd_format_t format = (ESD_STREAM | ESD_PLAY); SDL_AudioFormat test_format = 0; diff --git a/src/audio/fusionsound/SDL_fsaudio.c b/src/audio/fusionsound/SDL_fsaudio.c index 643002dc6..dae4f4afa 100644 --- a/src/audio/fusionsound/SDL_fsaudio.c +++ b/src/audio/fusionsound/SDL_fsaudio.c @@ -143,7 +143,7 @@ SDL_FS_PlayDevice(_THIS) this->hidden->mixsamples); /* If we couldn't write, assume fatal error for now */ if (ret) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen); @@ -186,7 +186,7 @@ SDL_FS_CloseDevice(_THIS) static int -SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture) +SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { int bytes; SDL_AudioFormat test_format = 0, format = 0; diff --git a/src/audio/haiku/SDL_haikuaudio.cc b/src/audio/haiku/SDL_haikuaudio.cc index dddb77922..648987a14 100644 --- a/src/audio/haiku/SDL_haikuaudio.cc +++ b/src/audio/haiku/SDL_haikuaudio.cc @@ -111,7 +111,7 @@ UnmaskSignals(sigset_t * omask) static int -HAIKUAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { int valid_datatype = 0; media_raw_audio_format format; diff --git a/src/audio/nacl/SDL_naclaudio.c b/src/audio/nacl/SDL_naclaudio.c index 741cb1392..643666d6a 100644 --- a/src/audio/nacl/SDL_naclaudio.c +++ b/src/audio/nacl/SDL_naclaudio.c @@ -43,7 +43,7 @@ #define SAMPLE_FRAME_COUNT 4096 /* Audio driver functions */ -static int NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture); +static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture); static void NACLAUD_CloseDevice(_THIS); static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data); @@ -85,7 +85,7 @@ static void NACLAUD_CloseDevice(SDL_AudioDevice *device) { } static int -NACLAUD_OpenDevice(_THIS, const char *devname, int iscapture) { +NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { PP_Instance instance = PSGetInstanceId(); const PPB_Audio *ppb_audio = PSInterfaceAudio(); const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig(); @@ -130,9 +130,7 @@ NACLAUD_Init(SDL_AudioDriverImpl * impl) /* Set the function pointers */ impl->OpenDevice = NACLAUD_OpenDevice; impl->CloseDevice = NACLAUD_CloseDevice; - impl->HasCaptureSupport = 0; impl->OnlyHasDefaultOutputDevice = 1; - impl->OnlyHasDefaultInputDevice = 1; impl->ProvidesOwnCallbackThread = 1; /* * impl->WaitDevice = NACLAUD_WaitDevice; diff --git a/src/audio/nas/SDL_nasaudio.c b/src/audio/nas/SDL_nasaudio.c index a41a480f2..fe5bd8eda 100644 --- a/src/audio/nas/SDL_nasaudio.c +++ b/src/audio/nas/SDL_nasaudio.c @@ -276,7 +276,7 @@ find_device(_THIS, int nch) } static int -NAS_OpenDevice(_THIS, const char *devname, int iscapture) +NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { AuElement elms[3]; int buffer_size; diff --git a/src/audio/paudio/SDL_paudio.c b/src/audio/paudio/SDL_paudio.c index d3c2d82b1..5f7d26c92 100644 --- a/src/audio/paudio/SDL_paudio.c +++ b/src/audio/paudio/SDL_paudio.c @@ -176,7 +176,7 @@ PAUDIO_WaitDevice(_THIS) * the user know what happened. */ fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); /* Don't try to close - may hang */ this->hidden->audio_fd = -1; #ifdef DEBUG_AUDIO @@ -212,7 +212,7 @@ PAUDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (written < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); @@ -241,7 +241,7 @@ PAUDIO_CloseDevice(_THIS) } static int -PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const char *workaround = SDL_getenv("SDL_DSP_NOSELECT"); char audiodev[1024]; diff --git a/src/audio/psp/SDL_pspaudio.c b/src/audio/psp/SDL_pspaudio.c index 360391164..59cbeb41c 100644 --- a/src/audio/psp/SDL_pspaudio.c +++ b/src/audio/psp/SDL_pspaudio.c @@ -43,7 +43,7 @@ #define PSPAUD_DRIVER_NAME "psp" static int -PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture) +PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { int format, mixlen, i; this->hidden = (struct SDL_PrivateAudioData *) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index e108280b9..b5ac00eb1 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -302,7 +302,7 @@ PULSEAUDIO_WaitDevice(_THIS) if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY || PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY || PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); return; } if (PULSEAUDIO_pa_stream_writable_size(h->stream) >= h->mixlen) { @@ -318,7 +318,7 @@ PULSEAUDIO_PlayDevice(_THIS) struct SDL_PrivateAudioData *h = this->hidden; if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } @@ -378,7 +378,7 @@ PULSEAUDIO_CloseDevice(_THIS) } static int -PULSEAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { struct SDL_PrivateAudioData *h = NULL; Uint16 test_format = 0; diff --git a/src/audio/qsa/SDL_qsa_audio.c b/src/audio/qsa/SDL_qsa_audio.c index 4121204ab..dcb7d38da 100644 --- a/src/audio/qsa/SDL_qsa_audio.c +++ b/src/audio/qsa/SDL_qsa_audio.c @@ -19,6 +19,15 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* + * !!! FIXME: streamline this a little by removing all the + * !!! FIXME: if (capture) {} else {} sections that are identical + * !!! FIXME: except for one flag. + */ + +/* !!! FIXME: can this target support hotplugging? */ +/* !!! FIXME: ...does SDL2 even support QNX? */ + #include "../../SDL_internal.h" #if SDL_AUDIO_DRIVER_QSA @@ -300,7 +309,7 @@ QSA_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if (towrite != 0) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } @@ -337,8 +346,9 @@ QSA_CloseDevice(_THIS) } static int -QSA_OpenDevice(_THIS, const char *devname, int iscapture) +QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { + const QSA_Device *device = (const QSA_Device *) handle; int status = 0; int format = 0; SDL_AudioFormat test_format = 0; @@ -363,80 +373,19 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture) /* Initialize channel direction: capture or playback */ this->hidden->iscapture = iscapture; - /* Find deviceid and cardid by device name for playback */ - if ((!this->hidden->iscapture) && (devname != NULL)) { - uint32_t device; - int32_t status; - - /* Search in the playback devices */ - device = 0; - do { - status = SDL_strcmp(qsa_playback_device[device].name, devname); - if (status == 0) { - /* Found requested device */ - this->hidden->deviceno = qsa_playback_device[device].deviceno; - this->hidden->cardno = qsa_playback_device[device].cardno; - break; - } - device++; - if (device >= qsa_playback_devices) { - QSA_CloseDevice(this); - return SDL_SetError("No such playback device"); - } - } while (1); - } - - /* Find deviceid and cardid by device name for capture */ - if ((this->hidden->iscapture) && (devname != NULL)) { - /* Search in the capture devices */ - uint32_t device; - int32_t status; - - /* Searching in the playback devices */ - device = 0; - do { - status = SDL_strcmp(qsa_capture_device[device].name, devname); - if (status == 0) { - /* Found requested device */ - this->hidden->deviceno = qsa_capture_device[device].deviceno; - this->hidden->cardno = qsa_capture_device[device].cardno; - break; - } - device++; - if (device >= qsa_capture_devices) { - QSA_CloseDevice(this); - return SDL_SetError("No such capture device"); - } - } while (1); - } - - /* Check if SDL requested default audio device */ - if (devname == NULL) { - /* Open system default audio device */ - if (!this->hidden->iscapture) { - status = snd_pcm_open_preferred(&this->hidden->audio_handle, - &this->hidden->cardno, - &this->hidden->deviceno, - SND_PCM_OPEN_PLAYBACK); - } else { - status = snd_pcm_open_preferred(&this->hidden->audio_handle, - &this->hidden->cardno, - &this->hidden->deviceno, - SND_PCM_OPEN_CAPTURE); - } - } else { + if (device != NULL) { /* Open requested audio device */ - if (!this->hidden->iscapture) { - status = - snd_pcm_open(&this->hidden->audio_handle, - this->hidden->cardno, this->hidden->deviceno, - SND_PCM_OPEN_PLAYBACK); - } else { - status = - snd_pcm_open(&this->hidden->audio_handle, - this->hidden->cardno, this->hidden->deviceno, - SND_PCM_OPEN_CAPTURE); - } + this->hidden->deviceno = device->deviceno; + this->hidden->cardno = device->cardno; + status = snd_pcm_open(&this->hidden->audio_handle, + device->cardno, device->deviceno, + iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE); + } else { + /* Open system default audio device */ + status = snd_pcm_open_preferred(&this->hidden->audio_handle, + &this->hidden->cardno, + &this->hidden->deviceno, + iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE); } /* Check if requested device is opened */ @@ -638,7 +587,7 @@ QSA_OpenDevice(_THIS, const char *devname, int iscapture) } static void -QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +QSA_DetectDevices(void) { uint32_t it; uint32_t cards; @@ -656,8 +605,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) return; } + /* !!! FIXME: code duplication */ /* Find requested devices by type */ - if (!iscapture) { + { /* output devices */ /* Playback devices enumeration requested */ for (it = 0; it < cards; it++) { devices = 0; @@ -688,7 +638,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) devices; status = snd_pcm_close(handle); if (status == EOK) { - addfn(qsa_playback_device[qsa_playback_devices].name); + SDL_AddAudioDevice(SDL_FALSE, qsa_playback_device[qsa_playback_devices].name, &qsa_playback_device[qsa_playback_devices]); qsa_playback_devices++; } } else { @@ -713,7 +663,9 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) break; } } - } else { + } + + { /* capture devices */ /* Capture devices enumeration requested */ for (it = 0; it < cards; it++) { devices = 0; @@ -744,7 +696,7 @@ QSA_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) devices; status = snd_pcm_close(handle); if (status == EOK) { - addfn(qsa_capture_device[qsa_capture_devices].name); + SDL_AddAudioDevice(SDL_TRUE, qsa_capture_device[qsa_capture_devices].name, &qsa_capture_device[qsa_capture_devices]); qsa_capture_devices++; } } else { diff --git a/src/audio/sndio/SDL_sndioaudio.c b/src/audio/sndio/SDL_sndioaudio.c index e4a85a73b..f8757d127 100644 --- a/src/audio/sndio/SDL_sndioaudio.c +++ b/src/audio/sndio/SDL_sndioaudio.c @@ -158,7 +158,7 @@ SNDIO_PlayDevice(_THIS) /* If we couldn't write, assume fatal error for now */ if ( written == 0 ) { - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); @@ -193,7 +193,7 @@ SNDIO_CloseDevice(_THIS) } static int -SNDIO_OpenDevice(_THIS, const char *devname, int iscapture) +SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); struct sio_par par; diff --git a/src/audio/sun/SDL_sunaudio.c b/src/audio/sun/SDL_sunaudio.c index 569f9ba1d..ff35b6b1c 100644 --- a/src/audio/sun/SDL_sunaudio.c +++ b/src/audio/sun/SDL_sunaudio.c @@ -56,9 +56,9 @@ static Uint8 snd2au(int sample); /* Audio driver bootstrap functions */ static void -SUNAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +SUNAUDIO_DetectDevices(void) { - SDL_EnumUnixAudioDevices(iscapture, 1, (int (*)(int fd)) NULL, addfn); + SDL_EnumUnixAudioDevices(1, (int (*)(int)) NULL); } #ifdef DEBUG_AUDIO @@ -158,7 +158,7 @@ SUNAUDIO_PlayDevice(_THIS) if (write(this->hidden->audio_fd, this->hidden->ulaw_buf, this->hidden->fragsize) < 0) { /* Assume fatal error, for now */ - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } this->hidden->written += this->hidden->fragsize; } else { @@ -168,7 +168,7 @@ SUNAUDIO_PlayDevice(_THIS) if (write(this->hidden->audio_fd, this->hidden->mixbuf, this->spec.size) < 0) { /* Assume fatal error, for now */ - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } this->hidden->written += this->hidden->fragsize; } @@ -198,7 +198,7 @@ SUNAUDIO_CloseDevice(_THIS) } static int -SUNAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) +SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); SDL_AudioFormat format = 0; @@ -414,6 +414,8 @@ SUNAUDIO_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = SUNAUDIO_GetDeviceBuf; impl->CloseDevice = SUNAUDIO_CloseDevice; + impl->AllowsArbitraryDeviceNames = 1; + return 1; /* this audio target is available. */ } diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index 88a8154ec..bd795cf34 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -36,8 +36,10 @@ #define WAVE_FORMAT_IEEE_FLOAT 0x0003 #endif -#define DETECT_DEV_IMPL(typ, capstyp) \ -static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \ +#define DETECT_DEV_IMPL(iscap, typ, capstyp) \ +static void DetectWave##typ##Devs(void) { \ + const UINT iscapture = iscap ? 1 : 0; \ + UINT devcount = wave##typ##GetNumDevs(); \ const UINT devcount = wave##typ##GetNumDevs(); \ capstyp caps; \ UINT i; \ @@ -45,24 +47,21 @@ static void DetectWave##typ##Devs(SDL_AddAudioDevice addfn) { \ if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ char *name = WIN_StringToUTF8(caps.szPname); \ if (name != NULL) { \ - addfn(name); \ + SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i|(iscap<<31))); \ SDL_free(name); \ } \ } \ } \ } -DETECT_DEV_IMPL(Out, WAVEOUTCAPS) -DETECT_DEV_IMPL(In, WAVEINCAPS) +DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS) +DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS) static void -WINMM_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +WINMM_DetectDevices() { - if (iscapture) { - DetectWaveInDevs(addfn); - } else { - DetectWaveOutDevs(addfn); - } + DetectWaveInDevs(); + DetectWaveOutDevs(); } static void CALLBACK @@ -220,7 +219,7 @@ PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture) } static int -WINMM_OpenDevice(_THIS, const char *devname, int iscapture) +WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format); int valid_datatype = 0; @@ -230,37 +229,13 @@ WINMM_OpenDevice(_THIS, const char *devname, int iscapture) char *utf8 = NULL; UINT i; - if (devname != NULL) { /* specific device requested? */ + if (handle != NULL) { /* specific device requested? */ + const size_t val = (size_t) handle; + devId = (UINT) val; if (iscapture) { - const UINT devcount = waveInGetNumDevs(); - WAVEINCAPS caps; - for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) { - result = waveInGetDevCaps(i, &caps, sizeof (caps)); - if (result != MMSYSERR_NOERROR) - continue; - else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL) - continue; - else if (SDL_strcmp(devname, utf8) == 0) - devId = i; - SDL_free(utf8); - } - } else { - const UINT devcount = waveOutGetNumDevs(); - WAVEOUTCAPS caps; - for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) { - result = waveOutGetDevCaps(i, &caps, sizeof (caps)); - if (result != MMSYSERR_NOERROR) - continue; - else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL) - continue; - else if (SDL_strcmp(devname, utf8) == 0) - devId = i; - SDL_free(utf8); - } - } - - if (devId == WAVE_MAPPER) { - return SDL_SetError("Requested device not found"); + /* we use the top bit to make value unique vs output indices. */ + SDL_assert((devId & (1<<31)) != 0); + devId &= ~(1<<31); } } diff --git a/src/audio/xaudio2/SDL_xaudio2.c b/src/audio/xaudio2/SDL_xaudio2.c index 37fdf593b..8aebabf6e 100644 --- a/src/audio/xaudio2/SDL_xaudio2.c +++ b/src/audio/xaudio2/SDL_xaudio2.c @@ -126,16 +126,13 @@ struct SDL_PrivateAudioData static void -XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +XAUDIO2_DetectDevices(void) { IXAudio2 *ixa2 = NULL; UINT32 devcount = 0; UINT32 i = 0; - if (iscapture) { - SDL_SetError("XAudio2: capture devices unsupported."); - return; - } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { + if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { SDL_SetError("XAudio2: XAudio2Create() failed at detection."); return; } else if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) { @@ -149,8 +146,8 @@ XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { char *str = WIN_StringToUTF8(details.DisplayName); if (str != NULL) { - addfn(str); - SDL_free(str); /* addfn() made a copy of the string. */ + SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i)); + SDL_free(str); /* SDL_AddAudioDevice made a copy of the string. */ } } } @@ -169,8 +166,8 @@ VoiceCBOnBufferEnd(THIS_ void *data) static void STDMETHODCALLTYPE VoiceCBOnVoiceError(THIS_ void *data, HRESULT Error) { - /* !!! FIXME: attempt to recover, or mark device disconnected. */ - SDL_assert(0 && "write me!"); + SDL_AudioDevice *this = (SDL_AudioDevice *) data; + SDL_OpenedAudioDeviceDisconnected(this); } /* no-op callbacks... */ @@ -221,7 +218,7 @@ XAUDIO2_PlayDevice(_THIS) if (result != S_OK) { /* uhoh, panic! */ IXAudio2SourceVoice_FlushSourceBuffers(source); - SDL_AudioDeviceDisconnected(SDL_FALSE, this); + SDL_OpenedAudioDeviceDisconnected(this); } } @@ -289,7 +286,7 @@ XAUDIO2_CloseDevice(_THIS) } static int -XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) +XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { HRESULT result = S_OK; WAVEFORMATEX waveformat; @@ -300,7 +297,7 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) #if defined(SDL_XAUDIO2_WIN8) LPCWSTR devId = NULL; #else - UINT32 devId = 0; /* 0 == system default device. */ + UINT32 devId = (UINT32) ((size_t) handle); /* 0 == system default device. */ #endif static IXAudio2VoiceCallbackVtbl callbacks_vtable = { @@ -315,9 +312,7 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) static IXAudio2VoiceCallback callbacks = { &callbacks_vtable }; - if (iscapture) { - return SDL_SetError("XAudio2: capture devices unsupported."); - } else if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { + if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { return SDL_SetError("XAudio2: XAudio2Create() failed at open."); } @@ -332,37 +327,6 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture) ixa2->SetDebugConfiguration(&debugConfig); */ -#if ! defined(__WINRT__) - if (devname != NULL) { - UINT32 devcount = 0; - UINT32 i = 0; - - if (IXAudio2_GetDeviceCount(ixa2, &devcount) != S_OK) { - IXAudio2_Release(ixa2); - return SDL_SetError("XAudio2: IXAudio2_GetDeviceCount() failed."); - } - for (i = 0; i < devcount; i++) { - XAUDIO2_DEVICE_DETAILS details; - if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { - char *str = WIN_StringToUTF8(details.DisplayName); - if (str != NULL) { - const int match = (SDL_strcmp(str, devname) == 0); - SDL_free(str); - if (match) { - devId = i; - break; - } - } - } - } - - if (i == devcount) { - IXAudio2_Release(ixa2); - return SDL_SetError("XAudio2: Requested device not found."); - } - } -#endif - /* Initialize all variables that we clean on shutdown */ this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc((sizeof *this->hidden)); @@ -529,6 +493,16 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl) impl->CloseDevice = XAUDIO2_CloseDevice; impl->Deinitialize = XAUDIO2_Deinitialize; + /* !!! FIXME: We can apparently use a C++ interface on Windows 8 + * !!! FIXME: (Windows::Devices::Enumeration::DeviceInformation) for device + * !!! FIXME: detection, but it's not implemented here yet. + * !!! FIXME: see http://blogs.msdn.com/b/chuckw/archive/2012/04/02/xaudio2-and-windows-8-consumer-preview.aspx + * !!! FIXME: for now, force the default device. + */ +#if defined(SDL_XAUDIO2_WIN8) || defined(__WINRT__) + impl->OnlyHasDefaultOutputDevice = 1; +#endif + return 1; /* this audio target is available. */ #endif } From 0152738d862324878db763714d3705ef7856731c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 18 Mar 2015 10:29:04 -0400 Subject: [PATCH 081/142] PulseAudio: Improved multidevice support. Added capture device enumeration, report human-readable device name, other cleanups. --HG-- extra : rebase_source : bb33f6fa05c47251e952a7b308998d2684f3f907 --- src/audio/pulseaudio/SDL_pulseaudio.c | 77 ++++++++++++++++++--------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index b5ac00eb1..33b4c6e83 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -84,6 +84,7 @@ static pa_context * (*PULSEAUDIO_pa_context_new) (pa_mainloop_api *, static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *, pa_context_flags_t, const pa_spawn_api *); static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list)(pa_context *, pa_sink_info_cb_t, void *); +static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list)(pa_context *, pa_source_info_cb_t, void *); static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *); static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *); static void (*PULSEAUDIO_pa_context_unref) (pa_context *); @@ -186,6 +187,7 @@ load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_context_new); SDL_PULSEAUDIO_SYM(pa_context_connect); SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list); + SDL_PULSEAUDIO_SYM(pa_context_get_source_info_list); SDL_PULSEAUDIO_SYM(pa_context_get_state); SDL_PULSEAUDIO_SYM(pa_context_disconnect); SDL_PULSEAUDIO_SYM(pa_context_unref); @@ -380,6 +382,7 @@ PULSEAUDIO_CloseDevice(_THIS) static int PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { + const char *devstr = (const char *) handle; /* NULL==default in Pulse. */ struct SDL_PrivateAudioData *h = NULL; Uint16 test_format = 0; pa_sample_spec paspec; @@ -497,7 +500,7 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) return SDL_SetError("Could not set up PulseAudio stream"); } - if (PULSEAUDIO_pa_stream_connect_playback(h->stream, devname, &paattr, flags, + if (PULSEAUDIO_pa_stream_connect_playback(h->stream, devstr, &paattr, flags, NULL, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not connect PulseAudio stream"); @@ -519,49 +522,72 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) return 0; } -typedef struct -{ - uint8_t last; - SDL_AddAudioDevice addfn; -} sink_struct; - static void -get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) +get_sinks_cb(pa_context *c, const pa_sink_info *i, int is_last, void *data) { - sink_struct *a = (sink_struct *) userdata; - a->last = is_last; + SDL_bool *done = (SDL_bool *) data; + + *done = (is_list != 0); if (i) { - a->addfn(i->name); + char *handle = SDL_strdup(i->name); + if (handle != NULL) { + SDL_AddAudioDevice(SDL_FALSE, i->description, handle); + } } } static void -PULSEAUDIO_DetectDevices(int iscapture, SDL_AddAudioDevice addfn) +get_sources_cb(pa_context *c, const pa_sink_info *i, int is_last, void *data) +{ + SDL_bool *done = (SDL_bool *) data; + + *done = (is_list != 0); + if (i) { + char *handle = SDL_strdup(i->name); + if (handle != NULL) { + SDL_AddAudioDevice(SDL_TRUE, i->description, handle); + } + } +} + +static void +RunPulseDetectCallback(pa_mainloop *mainloop, pa_operation *o, SDL_bool *done) +{ + do { + if (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_CANCELLED) { + break; + } else if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) { + break; + } + } while (*done == SDL_FALSE); +} + +static void +PULSEAUDIO_DetectDevices() { pa_mainloop *mainloop = NULL; pa_context *context = NULL; + pa_operation *o = NULL; + SDL_bool done; if (ConnectToPulseServer(&mainloop, &context) < 0) { return; } - if (!iscapture) { - sink_struct a = { 0, addfn }; - pa_operation *o = PULSEAUDIO_pa_context_get_sink_info_list(context, - get_sink_info_callback, &a); - while (!a.last) { - if (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_CANCELLED) { - break; - } - if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) { - break; - } - } - } + done = SDL_FALSE; + RunPulseDetectCallback(mainloop, PULSEAUDIO_pa_context_get_sink_info_list(context, get_sinks_cb, &done), &done); + done = SDL_FALSE; + RunPulseDetectCallback(mainloop, PULSEAUDIO_pa_context_get_source_info_list(context, get_sources_cb, &done), &done); DisconnectFromPulseServer(mainloop, context); } +static void +PULSEAUDIO_FreeDeviceHandle(void *handle) +{ + SDL_free(handle); /* just a string we copied. */ +} + static void PULSEAUDIO_Deinitialize(void) { @@ -593,6 +619,7 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf; impl->CloseDevice = PULSEAUDIO_CloseDevice; impl->WaitDone = PULSEAUDIO_WaitDone; + impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle; impl->Deinitialize = PULSEAUDIO_Deinitialize; return 1; /* this audio target is available. */ From 2586087fca7a22c7c179870b695efe6466de1293 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 13:15:28 -0400 Subject: [PATCH 082/142] Don't assert if an audio backend reports the same device disconnected twice. --- src/audio/SDL_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index af88bb0e8..e00500b73 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -424,7 +424,10 @@ SDL_AddAudioDevice(const int iscapture, const char *name, void *handle) void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device) { SDL_assert(get_audio_device(device->id) == device); - SDL_assert(device->enabled); /* called more than once?! */ + + if (!device->enabled) { + return; + } /* Ends the audio callback and mark the device as STOPPED, but the app still needs to close the device to free resources. */ From d0a775e968fb40b740fee46447f745ed2194717b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 13:27:10 -0400 Subject: [PATCH 083/142] Disconnected/broken/lost audio devices now continue to fire their callback. The data produced by the callback is just thrown away and the audio thread delays as if it's waiting for the hardware to drain. This lets apps that rely on their audio callback firing regularly continue to make progress to function as properly as possible in the face of disaster. Apps that want to know that the device is really gone and deal with that scenario can use the new hotplug functionality. --- src/audio/SDL_audio.c | 63 +++++++++++++++++++++------------------- src/audio/SDL_sysaudio.h | 3 +- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index e00500b73..5e6eb709c 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -727,7 +727,7 @@ SDL_RunAudio(void *devicep) resampling process can be any number. We will have to see what a good size for the stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. */ - while (device->enabled) { + while (!device->shutdown) { if (device->paused) { SDL_Delay(delay); @@ -810,31 +810,27 @@ SDL_RunAudio(void *devicep) const int silence = (int) device->spec.silence; /* Loop, filling the audio buffers */ - while (device->enabled) { - + while (!device->shutdown) { /* Fill the current buffer with sound */ if (device->convert.needed) { - if (device->convert.buf) { - stream = device->convert.buf; - } else { - continue; - } - } else { + stream = device->convert.buf; + } else if (device->enabled) { stream = current_audio.impl.GetDeviceBuf(device); - if (stream == NULL) { - stream = device->fake_stream; - } + } else { + /* if the device isn't enabled, we still write to the + fake_stream, so the app's callback will fire with + a regular frequency, in case they depend on that + for timing or progress. They can use hotplug + now to know if the device failed. */ + stream = NULL; + } + + if (stream == NULL) { + stream = device->fake_stream; } /* !!! FIXME: this should be LockDevice. */ SDL_LockMutex(device->mixer_lock); - - /* Check again, in case device was removed while a lock was held. */ - if (!device->enabled) { - SDL_UnlockMutex(device->mixer_lock); - break; - } - if (device->paused) { SDL_memset(stream, silence, stream_len); } else { @@ -843,14 +839,15 @@ SDL_RunAudio(void *devicep) SDL_UnlockMutex(device->mixer_lock); /* Convert the audio if necessary */ - if (device->convert.needed) { + if (device->enabled && device->convert.needed) { SDL_ConvertAudio(&device->convert); stream = current_audio.impl.GetDeviceBuf(device); if (stream == NULL) { stream = device->fake_stream; + } else { + SDL_memcpy(stream, device->convert.buf, + device->convert.len_cvt); } - SDL_memcpy(stream, device->convert.buf, - device->convert.len_cvt); } /* Ready current buffer for play and change current buffer */ @@ -1084,6 +1081,7 @@ static void close_audio_device(SDL_AudioDevice * device) { device->enabled = 0; + device->shutdown = 1; if (device->thread != NULL) { SDL_WaitThread(device->thread, NULL); } @@ -1178,6 +1176,7 @@ open_audio_device(const char *devname, int iscapture, SDL_AudioDevice *device; SDL_bool build_cvt; void *handle = NULL; + int stream_len; int i = 0; if (!SDL_WasInit(SDL_INIT_AUDIO)) { @@ -1304,14 +1303,6 @@ open_audio_device(const char *devname, int iscapture, } device->opened = 1; - /* Allocate a fake audio memory buffer */ - device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size); - if (device->fake_stream == NULL) { - close_audio_device(device); - SDL_OutOfMemory(); - return 0; - } - /* See if we need to do any conversion */ build_cvt = SDL_FALSE; if (obtained->freq != device->spec.freq) { @@ -1370,6 +1361,18 @@ open_audio_device(const char *devname, int iscapture, } } + /* Allocate a fake audio memory buffer */ + stream_len = (device->convert.needed) ? device->convert.len_cvt : 0; + if (device->spec.size > stream_len) { + stream_len = device->spec.size; + } + device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len); + if (device->fake_stream == NULL) { + close_audio_device(device); + SDL_OutOfMemory(); + return 0; + } + if (device->spec.callback == NULL) { /* use buffer queueing? */ /* pool a few packets to start. Enough for two callbacks. */ const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN; diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index fd8e68708..a339f8166 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -155,7 +155,8 @@ struct SDL_AudioDevice /* Current state flags */ /* !!! FIXME: should be SDL_bool */ int iscapture; - int enabled; + int enabled; /* true if device is functioning and connected. */ + int shutdown; /* true if we are signaling the play thread to end. */ int paused; int opened; From 8f923a1c3329bc97e066bc8691989958ffa298d2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 13:34:17 -0400 Subject: [PATCH 084/142] Removed the broken audio streaming code, other small cleanups. --- src/audio/SDL_audio.c | 295 ++++++------------------------------------ 1 file changed, 43 insertions(+), 252 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 5e6eb709c..af9175333 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -286,67 +286,6 @@ finalize_audio_entry_points(void) #undef FILL_STUB } -#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ -/* Streaming functions (for when the input and output buffer sizes are different) */ -/* Write [length] bytes from buf into the streamer */ -static void -SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length) -{ - int i; - - for (i = 0; i < length; ++i) { - stream->buffer[stream->write_pos] = buf[i]; - ++stream->write_pos; - } -} - -/* Read [length] bytes out of the streamer into buf */ -static void -SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length) -{ - int i; - - for (i = 0; i < length; ++i) { - buf[i] = stream->buffer[stream->read_pos]; - ++stream->read_pos; - } -} - -static int -SDL_StreamLength(SDL_AudioStreamer * stream) -{ - return (stream->write_pos - stream->read_pos) % stream->max_len; -} - -/* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */ -#if 0 -static int -SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence) -{ - /* First try to allocate the buffer */ - stream->buffer = (Uint8 *) SDL_malloc(max_len); - if (stream->buffer == NULL) { - return -1; - } - - stream->max_len = max_len; - stream->read_pos = 0; - stream->write_pos = 0; - - /* Zero out the buffer */ - SDL_memset(stream->buffer, silence, max_len); - - return 0; -} -#endif - -/* Deinitialize the stream simply by freeing the buffer */ -static void -SDL_StreamDeinit(SDL_AudioStreamer * stream) -{ - SDL_free(stream->buffer); -} -#endif /* device hotplug support... */ @@ -655,17 +594,12 @@ int SDLCALL SDL_RunAudio(void *devicep) { SDL_AudioDevice *device = (SDL_AudioDevice *) devicep; + const int silence = (int) device->spec.silence; + const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq); + const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size; Uint8 *stream; - int stream_len; - void *udata; - void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len); - Uint32 delay; - -#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ - /* For streaming when the buffer sizes don't match up */ - Uint8 *istream; - int istream_len = 0; -#endif + void *udata = device->spec.userdata; + void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback; /* The audio mixing is always a high priority thread */ SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); @@ -674,202 +608,59 @@ SDL_RunAudio(void *devicep) device->threadid = SDL_ThreadID(); current_audio.impl.ThreadInit(device); - /* Set up the mixing function */ - fill = device->spec.callback; - udata = device->spec.userdata; - - /* By default do not stream */ - device->use_streamer = 0; - - if (device->convert.needed) { -#if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */ - /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */ - if (device->convert.len_mult != 1 || device->convert.len_div != 1) { - /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */ - stream_max_len = 2 * device->spec.size; - if (device->convert.len_mult > device->convert.len_div) { - stream_max_len *= device->convert.len_mult; - stream_max_len /= device->convert.len_div; - } - if (SDL_StreamInit(&device->streamer, stream_max_len, silence) < - 0) - return -1; - device->use_streamer = 1; - - /* istream_len should be the length of what we grab from the callback and feed to conversion, - so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d - */ - istream_len = - device->spec.size * device->convert.len_div / - device->convert.len_mult; + /* Loop, filling the audio buffers */ + while (!device->shutdown) { + /* Fill the current buffer with sound */ + if (device->convert.needed) { + stream = device->convert.buf; + } else if (device->enabled) { + stream = current_audio.impl.GetDeviceBuf(device); + } else { + /* if the device isn't enabled, we still write to the + fake_stream, so the app's callback will fire with + a regular frequency, in case they depend on that + for timing or progress. They can use hotplug + now to know if the device failed. */ + stream = NULL; } -#endif - stream_len = device->convert.len; - } else { - stream_len = device->spec.size; - } - - /* Calculate the delay while paused */ - delay = ((device->spec.samples * 1000) / device->spec.freq); - - /* Determine if the streamer is necessary here */ -#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ - if (device->use_streamer == 1) { - /* This code is almost the same as the old code. The difference is, instead of reading - directly from the callback into "stream", then converting and sending the audio off, - we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device. - However, reading and writing with streamer are done separately: - - We only call the callback and write to the streamer when the streamer does not - contain enough samples to output to the device. - - We only read from the streamer and tell the device to play when the streamer - does have enough samples to output. - This allows us to perform resampling in the conversion step, where the output of the - resampling process can be any number. We will have to see what a good size for the - stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure. - */ - while (!device->shutdown) { - - if (device->paused) { - SDL_Delay(delay); - continue; - } - - /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */ - if (SDL_StreamLength(&device->streamer) < stream_len) { - /* Set up istream */ - if (device->convert.needed) { - if (device->convert.buf) { - istream = device->convert.buf; - } else { - continue; - } - } else { -/* FIXME: Ryan, this is probably wrong. I imagine we don't want to get - * a device buffer both here and below in the stream output. - */ - istream = current_audio.impl.GetDeviceBuf(device); - if (istream == NULL) { - istream = device->fake_stream; - } - } - - /* Read from the callback into the _input_ stream */ - // !!! FIXME: this should be LockDevice. - SDL_LockMutex(device->mixer_lock); - (*fill) (udata, istream, istream_len); - SDL_UnlockMutex(device->mixer_lock); - - /* Convert the audio if necessary and write to the streamer */ - if (device->convert.needed) { - SDL_ConvertAudio(&device->convert); - if (istream == NULL) { - istream = device->fake_stream; - } - /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */ - SDL_StreamWrite(&device->streamer, device->convert.buf, - device->convert.len_cvt); - } else { - SDL_StreamWrite(&device->streamer, istream, istream_len); - } - } - - /* Only output audio if the streamer has enough to output */ - if (SDL_StreamLength(&device->streamer) >= stream_len) { - /* Set up the output stream */ - if (device->convert.needed) { - if (device->convert.buf) { - stream = device->convert.buf; - } else { - continue; - } - } else { - stream = current_audio.impl.GetDeviceBuf(device); - if (stream == NULL) { - stream = device->fake_stream; - } - } - - /* Now read from the streamer */ - SDL_StreamRead(&device->streamer, stream, stream_len); - - /* Ready current buffer for play and change current buffer */ - if (stream != device->fake_stream) { - current_audio.impl.PlayDevice(device); - /* Wait for an audio buffer to become available */ - current_audio.impl.WaitDevice(device); - } else { - SDL_Delay(delay); - } - } + if (stream == NULL) { + stream = device->fake_stream; } - } else -#endif - { - /* Otherwise, do not use the streamer. This is the old code. */ - const int silence = (int) device->spec.silence; - /* Loop, filling the audio buffers */ - while (!device->shutdown) { - /* Fill the current buffer with sound */ - if (device->convert.needed) { - stream = device->convert.buf; - } else if (device->enabled) { - stream = current_audio.impl.GetDeviceBuf(device); - } else { - /* if the device isn't enabled, we still write to the - fake_stream, so the app's callback will fire with - a regular frequency, in case they depend on that - for timing or progress. They can use hotplug - now to know if the device failed. */ - stream = NULL; - } + /* !!! FIXME: this should be LockDevice. */ + SDL_LockMutex(device->mixer_lock); + if (device->paused) { + SDL_memset(stream, silence, stream_len); + } else { + (*fill) (udata, stream, stream_len); + } + SDL_UnlockMutex(device->mixer_lock); + /* Convert the audio if necessary */ + if (device->enabled && device->convert.needed) { + SDL_ConvertAudio(&device->convert); + stream = current_audio.impl.GetDeviceBuf(device); if (stream == NULL) { stream = device->fake_stream; - } - - /* !!! FIXME: this should be LockDevice. */ - SDL_LockMutex(device->mixer_lock); - if (device->paused) { - SDL_memset(stream, silence, stream_len); } else { - (*fill) (udata, stream, stream_len); + SDL_memcpy(stream, device->convert.buf, + device->convert.len_cvt); } - SDL_UnlockMutex(device->mixer_lock); + } - /* Convert the audio if necessary */ - if (device->enabled && device->convert.needed) { - SDL_ConvertAudio(&device->convert); - stream = current_audio.impl.GetDeviceBuf(device); - if (stream == NULL) { - stream = device->fake_stream; - } else { - SDL_memcpy(stream, device->convert.buf, - device->convert.len_cvt); - } - } - - /* Ready current buffer for play and change current buffer */ - if (stream != device->fake_stream) { - current_audio.impl.PlayDevice(device); - /* Wait for an audio buffer to become available */ - current_audio.impl.WaitDevice(device); - } else { - SDL_Delay(delay); - } + /* Ready current buffer for play and change current buffer */ + if (stream == device->fake_stream) { + SDL_Delay(delay); + } else { + current_audio.impl.PlayDevice(device); + current_audio.impl.WaitDevice(device); } } - /* Wait for the audio to drain.. */ + /* Wait for the audio to drain. */ current_audio.impl.WaitDone(device); - /* If necessary, deinit the streamer */ -#if 0 /* !!! FIXME: rewrite/remove this streamer code. */ - if (device->use_streamer == 1) - SDL_StreamDeinit(&device->streamer); -#endif - return 0; } From 3883c8c40c747660278488ad0f3edd461c50ab78 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 15:43:00 -0400 Subject: [PATCH 085/142] SDL_RemoveAudioDevice() should specify capture vs output. This lets us reuse values between the two categories without conflicting, etc. --HG-- extra : amend_source : a48f3e0a0274d02f31a1832fbc82d581a6fd12b9 --- src/audio/SDL_audio.c | 9 ++++++--- src/audio/SDL_sysaudio.h | 2 +- src/audio/coreaudio/SDL_coreaudio.c | 2 +- src/audio/winmm/SDL_winmm.c | 7 +------ 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index af9175333..eafeb337a 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -400,11 +400,14 @@ mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *remove /* The audio backends call this when a device is removed from the system. */ void -SDL_RemoveAudioDevice(void *handle) +SDL_RemoveAudioDevice(const int iscapture, void *handle) { SDL_LockMutex(current_audio.detectionLock); - mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved); - mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved); + if (iscapture) { + mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved); + } else { + mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved); + } SDL_UnlockMutex(current_audio.detectionLock); current_audio.impl.FreeDeviceHandle(handle); } diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index a339f8166..2b4e95688 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -37,7 +37,7 @@ extern void SDL_AddAudioDevice(const int iscapture, const char *name, void *hand /* Audio targets should call this as devices are removed, so SDL can update its list of available devices. */ -extern void SDL_RemoveAudioDevice(void *handle); +extern void SDL_RemoveAudioDevice(const int iscapture, void *handle); /* Audio targets should call this if an opened audio device is lost while being used. This can happen due to i/o errors, or a device being unplugged, diff --git a/src/audio/coreaudio/SDL_coreaudio.c b/src/audio/coreaudio/SDL_coreaudio.c index afd2565dd..22210b050 100644 --- a/src/audio/coreaudio/SDL_coreaudio.c +++ b/src/audio/coreaudio/SDL_coreaudio.c @@ -246,7 +246,7 @@ reprocess_device_list(const int iscapture, AudioDeviceList **list) if (item->alive) { prev = item; } else { - SDL_RemoveAudioDevice((void *) ((size_t) item->devid)); + SDL_RemoveAudioDevice(iscapture, (void *) ((size_t) item->devid)); if (prev) { prev->next = item->next; } else { diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index bd795cf34..8bc86b8fc 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -47,7 +47,7 @@ static void DetectWave##typ##Devs(void) { \ if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ char *name = WIN_StringToUTF8(caps.szPname); \ if (name != NULL) { \ - SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i|(iscap<<31))); \ + SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i)); \ SDL_free(name); \ } \ } \ @@ -232,11 +232,6 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) if (handle != NULL) { /* specific device requested? */ const size_t val = (size_t) handle; devId = (UINT) val; - if (iscapture) { - /* we use the top bit to make value unique vs output indices. */ - SDL_assert((devId & (1<<31)) != 0); - devId &= ~(1<<31); - } } /* Initialize all variables that we clean on shutdown */ From cd3f491efbcb069814c118104b3d2cf3f9f4e9a7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 22:08:12 -0400 Subject: [PATCH 086/142] PulseAudio: Hotplug support! --- src/audio/pulseaudio/SDL_pulseaudio.c | 221 +++++++++++++++++--------- src/audio/pulseaudio/SDL_pulseaudio.h | 2 + 2 files changed, 145 insertions(+), 78 deletions(-) diff --git a/src/audio/pulseaudio/SDL_pulseaudio.c b/src/audio/pulseaudio/SDL_pulseaudio.c index 33b4c6e83..adcbdee2d 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/src/audio/pulseaudio/SDL_pulseaudio.c @@ -72,6 +72,8 @@ static const char * (*PULSEAUDIO_pa_strerror) (int); static pa_mainloop * (*PULSEAUDIO_pa_mainloop_new) (void); static pa_mainloop_api * (*PULSEAUDIO_pa_mainloop_get_api) (pa_mainloop *); static int (*PULSEAUDIO_pa_mainloop_iterate) (pa_mainloop *, int, int *); +static int (*PULSEAUDIO_pa_mainloop_run) (pa_mainloop *, int *); +static void (*PULSEAUDIO_pa_mainloop_quit) (pa_mainloop *, int); static void (*PULSEAUDIO_pa_mainloop_free) (pa_mainloop *); static pa_operation_state_t (*PULSEAUDIO_pa_operation_get_state) ( @@ -83,9 +85,13 @@ static pa_context * (*PULSEAUDIO_pa_context_new) (pa_mainloop_api *, const char *); static int (*PULSEAUDIO_pa_context_connect) (pa_context *, const char *, pa_context_flags_t, const pa_spawn_api *); -static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list)(pa_context *, pa_sink_info_cb_t, void *); -static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list)(pa_context *, pa_source_info_cb_t, void *); +static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_list) (pa_context *, pa_sink_info_cb_t, void *); +static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_list) (pa_context *, pa_source_info_cb_t, void *); +static pa_operation * (*PULSEAUDIO_pa_context_get_sink_info_by_index) (pa_context *, uint32_t, pa_sink_info_cb_t, void *); +static pa_operation * (*PULSEAUDIO_pa_context_get_source_info_by_index) (pa_context *, uint32_t, pa_source_info_cb_t, void *); static pa_context_state_t (*PULSEAUDIO_pa_context_get_state) (pa_context *); +static pa_operation * (*PULSEAUDIO_pa_context_subscribe) (pa_context *, pa_subscription_mask_t, pa_context_success_cb_t, void *); +static void (*PULSEAUDIO_pa_context_set_subscribe_callback) (pa_context *, pa_context_subscribe_cb_t, void *); static void (*PULSEAUDIO_pa_context_disconnect) (pa_context *); static void (*PULSEAUDIO_pa_context_unref) (pa_context *); @@ -180,6 +186,8 @@ load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_mainloop_new); SDL_PULSEAUDIO_SYM(pa_mainloop_get_api); SDL_PULSEAUDIO_SYM(pa_mainloop_iterate); + SDL_PULSEAUDIO_SYM(pa_mainloop_run); + SDL_PULSEAUDIO_SYM(pa_mainloop_quit); SDL_PULSEAUDIO_SYM(pa_mainloop_free); SDL_PULSEAUDIO_SYM(pa_operation_get_state); SDL_PULSEAUDIO_SYM(pa_operation_cancel); @@ -188,7 +196,11 @@ load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_context_connect); SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list); SDL_PULSEAUDIO_SYM(pa_context_get_source_info_list); + SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_by_index); + SDL_PULSEAUDIO_SYM(pa_context_get_source_info_by_index); SDL_PULSEAUDIO_SYM(pa_context_get_state); + SDL_PULSEAUDIO_SYM(pa_context_subscribe); + SDL_PULSEAUDIO_SYM(pa_context_set_subscribe_callback); SDL_PULSEAUDIO_SYM(pa_context_disconnect); SDL_PULSEAUDIO_SYM(pa_context_unref); SDL_PULSEAUDIO_SYM(pa_stream_new); @@ -226,6 +238,19 @@ getAppName(void) return "SDL Application"; /* oh well. */ } +static void +WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o) +{ + /* This checks for NO errors currently. Either fix that, check results elsewhere, or do things you don't care about. */ + if (mainloop && o) { + SDL_bool okay = SDL_TRUE; + while (okay && (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_RUNNING)) { + okay = (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) >= 0); + } + PULSEAUDIO_pa_operation_unref(o); + } +} + static void DisconnectFromPulseServer(pa_mainloop *mainloop, pa_context *context) { @@ -300,7 +325,7 @@ PULSEAUDIO_WaitDevice(_THIS) { struct SDL_PrivateAudioData *h = this->hidden; - while(1) { + while (this->enabled) { if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY || PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY || PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { @@ -318,9 +343,10 @@ PULSEAUDIO_PlayDevice(_THIS) { /* Write the audio data */ struct SDL_PrivateAudioData *h = this->hidden; - if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, - PA_SEEK_RELATIVE) < 0) { - SDL_OpenedAudioDeviceDisconnected(this); + if (this->enabled) { + if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) { + SDL_OpenedAudioDeviceDisconnected(this); + } } } @@ -333,24 +359,21 @@ stream_drain_complete(pa_stream *s, int success, void *userdata) static void PULSEAUDIO_WaitDone(_THIS) { - struct SDL_PrivateAudioData *h = this->hidden; - pa_operation *o; - - o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL); - if (!o) { - return; - } - - while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) { - if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY || - PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY || - PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { - PULSEAUDIO_pa_operation_cancel(o); - break; + if (this->enabled) { + struct SDL_PrivateAudioData *h = this->hidden; + pa_operation *o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL); + if (o) { + while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) { + if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY || + PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY || + PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) { + PULSEAUDIO_pa_operation_cancel(o); + break; + } + } + PULSEAUDIO_pa_operation_unref(o); } } - - PULSEAUDIO_pa_operation_unref(o); } @@ -367,11 +390,10 @@ PULSEAUDIO_CloseDevice(_THIS) { if (this->hidden != NULL) { SDL_FreeAudioMem(this->hidden->mixbuf); - this->hidden->mixbuf = NULL; + SDL_free(this->hidden->device_name); if (this->hidden->stream) { PULSEAUDIO_pa_stream_disconnect(this->hidden->stream); PULSEAUDIO_pa_stream_unref(this->hidden->stream); - this->hidden->stream = NULL; } DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context); SDL_free(this->hidden); @@ -379,10 +401,31 @@ PULSEAUDIO_CloseDevice(_THIS) } } +static void +DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) +{ + if (i) { + char **devname = (char **) data; + *devname = SDL_strdup(i->name); + } +} + +static SDL_bool +FindDeviceName(struct SDL_PrivateAudioData *h, void *handle) +{ + const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1; + + if (handle == NULL) { /* NULL == default device. */ + return SDL_TRUE; + } + + WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name)); + return (h->device_name != NULL); +} + static int PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) { - const char *devstr = (const char *) handle; /* NULL==default in Pulse. */ struct SDL_PrivateAudioData *h = NULL; Uint16 test_format = 0; pa_sample_spec paspec; @@ -483,6 +526,11 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) return SDL_SetError("Could not connect to PulseAudio server"); } + if (!FindDeviceName(h, handle)) { + PULSEAUDIO_CloseDevice(this); + return SDL_SetError("Requested PulseAudio sink missing?"); + } + /* The SDL ALSA output hints us that we use Windows' channel mapping */ /* http://bugzilla.libsdl.org/show_bug.cgi?id=110 */ PULSEAUDIO_pa_channel_map_init_auto(&pacmap, this->spec.channels, @@ -500,7 +548,13 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) return SDL_SetError("Could not set up PulseAudio stream"); } - if (PULSEAUDIO_pa_stream_connect_playback(h->stream, devstr, &paattr, flags, + /* now that we have multi-device support, don't move a stream from + a device that was unplugged to something else, unless we're default. */ + if (h->device_name != NULL) { + flags |= PA_STREAM_DONT_MOVE; + } + + if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL) < 0) { PULSEAUDIO_CloseDevice(this); return SDL_SetError("Could not connect PulseAudio stream"); @@ -514,7 +568,7 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) state = PULSEAUDIO_pa_stream_get_state(h->stream); if (!PA_STREAM_IS_GOOD(state)) { PULSEAUDIO_CloseDevice(this); - return SDL_SetError("Could not create to PulseAudio stream"); + return SDL_SetError("Could not connect PulseAudio stream"); } } while (state != PA_STREAM_READY); @@ -522,95 +576,107 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) return 0; } -static void -get_sinks_cb(pa_context *c, const pa_sink_info *i, int is_last, void *data) -{ - SDL_bool *done = (SDL_bool *) data; +static pa_mainloop *hotplug_mainloop = NULL; +static pa_context *hotplug_context = NULL; +static SDL_Thread *hotplug_thread = NULL; - *done = (is_list != 0); +/* device handles are device index + 1, cast to void*, so we never pass a NULL. */ + +/* This is called when PulseAudio adds an output ("sink") device. */ +static void +SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) +{ if (i) { - char *handle = SDL_strdup(i->name); - if (handle != NULL) { - SDL_AddAudioDevice(SDL_FALSE, i->description, handle); + SDL_AddAudioDevice(SDL_FALSE, i->description, (void *) ((size_t) i->index+1)); + } +} + +/* This is called when PulseAudio adds a capture ("source") device. */ +static void +SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) +{ + if (i) { + /* Skip "monitor" sources. These are just output from other sinks. */ + if (i->monitor_of_sink == PA_INVALID_INDEX) { + SDL_AddAudioDevice(SDL_TRUE, i->description, (void *) ((size_t) i->index+1)); } } } +/* This is called when PulseAudio has a device connected/removed/changed. */ static void -get_sources_cb(pa_context *c, const pa_sink_info *i, int is_last, void *data) +HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data) { - SDL_bool *done = (SDL_bool *) data; + const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW); + const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE); - *done = (is_list != 0); - if (i) { - char *handle = SDL_strdup(i->name); - if (handle != NULL) { - SDL_AddAudioDevice(SDL_TRUE, i->description, handle); + if (added || removed) { /* we only care about add/remove events. */ + const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK); + const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE); + + /* adds need sink details from the PulseAudio server. Another callback... */ + if (added && sink) { + PULSEAUDIO_pa_context_get_sink_info_by_index(hotplug_context, idx, SinkInfoCallback, NULL); + } else if (added && source) { + PULSEAUDIO_pa_context_get_source_info_by_index(hotplug_context, idx, SourceInfoCallback, NULL); + } else if (removed && (sink || source)) { + /* removes we can handle just with the device index. */ + SDL_RemoveAudioDevice(source != 0, (void *) ((size_t) idx+1)); } } } -static void -RunPulseDetectCallback(pa_mainloop *mainloop, pa_operation *o, SDL_bool *done) +/* this runs as a thread while the Pulse target is initialized to catch hotplug events. */ +static int SDLCALL +HotplugThread(void *data) { - do { - if (PULSEAUDIO_pa_operation_get_state(o) == PA_OPERATION_CANCELLED) { - break; - } else if (PULSEAUDIO_pa_mainloop_iterate(mainloop, 1, NULL) < 0) { - break; - } - } while (*done == SDL_FALSE); + pa_operation *o; + SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); + PULSEAUDIO_pa_context_set_subscribe_callback(hotplug_context, HotplugCallback, NULL); + o = PULSEAUDIO_pa_context_subscribe(hotplug_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, NULL, NULL); + PULSEAUDIO_pa_operation_unref(o); /* don't wait for it, just do our thing. */ + PULSEAUDIO_pa_mainloop_run(hotplug_mainloop, NULL); + return 0; } static void PULSEAUDIO_DetectDevices() { - pa_mainloop *mainloop = NULL; - pa_context *context = NULL; - pa_operation *o = NULL; - SDL_bool done; + WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_sink_info_list(hotplug_context, SinkInfoCallback, NULL)); + WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL)); - if (ConnectToPulseServer(&mainloop, &context) < 0) { - return; - } - - done = SDL_FALSE; - RunPulseDetectCallback(mainloop, PULSEAUDIO_pa_context_get_sink_info_list(context, get_sinks_cb, &done), &done); - done = SDL_FALSE; - RunPulseDetectCallback(mainloop, PULSEAUDIO_pa_context_get_source_info_list(context, get_sources_cb, &done), &done); - - DisconnectFromPulseServer(mainloop, context); -} - -static void -PULSEAUDIO_FreeDeviceHandle(void *handle) -{ - SDL_free(handle); /* just a string we copied. */ + /* ok, we have a sane list, let's set up hotplug notifications now... */ + hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL); } static void PULSEAUDIO_Deinitialize(void) { + if (hotplug_thread) { + PULSEAUDIO_pa_mainloop_quit(hotplug_mainloop, 0); + SDL_WaitThread(hotplug_thread, NULL); + hotplug_thread = NULL; + } + + DisconnectFromPulseServer(hotplug_mainloop, hotplug_context); + hotplug_mainloop = NULL; + hotplug_context = NULL; + UnloadPulseAudioLibrary(); } static int PULSEAUDIO_Init(SDL_AudioDriverImpl * impl) { - pa_mainloop *mainloop = NULL; - pa_context *context = NULL; - if (LoadPulseAudioLibrary() < 0) { return 0; } - if (ConnectToPulseServer(&mainloop, &context) < 0) { + if (ConnectToPulseServer(&hotplug_mainloop, &hotplug_context) < 0) { UnloadPulseAudioLibrary(); return 0; } - DisconnectFromPulseServer(mainloop, context); - /* Set the function pointers */ impl->DetectDevices = PULSEAUDIO_DetectDevices; impl->OpenDevice = PULSEAUDIO_OpenDevice; @@ -619,7 +685,6 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl) impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf; impl->CloseDevice = PULSEAUDIO_CloseDevice; impl->WaitDone = PULSEAUDIO_WaitDone; - impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle; impl->Deinitialize = PULSEAUDIO_Deinitialize; return 1; /* this audio target is available. */ diff --git a/src/audio/pulseaudio/SDL_pulseaudio.h b/src/audio/pulseaudio/SDL_pulseaudio.h index d587318d7..10568ffb9 100644 --- a/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/src/audio/pulseaudio/SDL_pulseaudio.h @@ -32,6 +32,8 @@ struct SDL_PrivateAudioData { + char *device_name; + /* pulseaudio structures */ pa_mainloop *mainloop; pa_context *context; From fc1b620b3d32680f9031038edc08627369bafc18 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 22:11:20 -0400 Subject: [PATCH 087/142] Zero out the audio hotplug event structure, so the "padded" fields are sane. Just in case we ever need those bits in the future. --- src/audio/SDL_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index eafeb337a..e5680299f 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -351,6 +351,7 @@ SDL_AddAudioDevice(const int iscapture, const char *name, void *handle) /* Post the event, if desired */ if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) { SDL_Event event; + SDL_zero(event); event.adevice.type = SDL_AUDIODEVICEADDED; event.adevice.which = device_index; event.adevice.iscapture = iscapture; @@ -377,6 +378,7 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device) /* Post the event, if desired */ if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) { SDL_Event event; + SDL_zero(event); event.adevice.type = SDL_AUDIODEVICEREMOVED; event.adevice.which = device->id; event.adevice.iscapture = device->iscapture ? 1 : 0; From 90bd9250a43d9410542e8406fc81350ef451b9b6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 22:20:12 -0400 Subject: [PATCH 088/142] Immediately minimize the goofy window in testaudiohotplug. --- test/testaudiohotplug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/testaudiohotplug.c b/test/testaudiohotplug.c index 08bfa74de..6c3d88cd1 100644 --- a/test/testaudiohotplug.c +++ b/test/testaudiohotplug.c @@ -131,7 +131,8 @@ main(int argc, char *argv[]) return (1); } - SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0); + /* Some targets (Mac CoreAudio) need an event queue for audio hotplug, so make and immediately hide a window. */ + SDL_MinimizeWindow(SDL_CreateWindow("testaudiohotplug", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0)); if (argc > 1) { SDL_strlcpy(filename, argv[1], sizeof(filename)); From 9c567d5e937f48a3cfcf5c601193fbd01590ea0c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 23:35:43 -0400 Subject: [PATCH 089/142] Patched to compile on Windows. --- src/audio/winmm/SDL_winmm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index 8bc86b8fc..ede404952 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -39,7 +39,6 @@ #define DETECT_DEV_IMPL(iscap, typ, capstyp) \ static void DetectWave##typ##Devs(void) { \ const UINT iscapture = iscap ? 1 : 0; \ - UINT devcount = wave##typ##GetNumDevs(); \ const UINT devcount = wave##typ##GetNumDevs(); \ capstyp caps; \ UINT i; \ From cb00e52aeb654c942e02a899cc0ab54d7de019b7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 23:39:53 -0400 Subject: [PATCH 090/142] Fixed a compiler warning on Visual Studio. --HG-- extra : amend_source : e9bf68163b3496c4fd7126a2a91cd2469579f901 --- src/audio/SDL_audio.c | 2 +- src/audio/winmm/SDL_winmm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index e5680299f..60eb48134 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -972,7 +972,7 @@ open_audio_device(const char *devname, int iscapture, SDL_AudioDevice *device; SDL_bool build_cvt; void *handle = NULL; - int stream_len; + Uint32 stream_len; int i = 0; if (!SDL_WasInit(SDL_INIT_AUDIO)) { diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index ede404952..83f5cec44 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -57,7 +57,7 @@ DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS) DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS) static void -WINMM_DetectDevices() +WINMM_DetectDevices(void) { DetectWaveInDevs(); DetectWaveOutDevs(); From af94711fb1d26d3ce73290aa587605adb996c157 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 23:44:47 -0400 Subject: [PATCH 091/142] Make static analysis happy. --- src/audio/SDL_audio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 60eb48134..d937c5af4 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -1162,6 +1162,7 @@ open_audio_device(const char *devname, int iscapture, if (device->spec.size > stream_len) { stream_len = device->spec.size; } + SDL_assert(stream_len > 0); device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len); if (device->fake_stream == NULL) { close_audio_device(device); From 84753c68f7b025437ad7b11c9be55c492c3b35f7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 23:45:34 -0400 Subject: [PATCH 092/142] Removed unused variable. --- src/audio/winmm/SDL_winmm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index 83f5cec44..b442e882b 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -225,7 +225,6 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) MMRESULT result; WAVEFORMATEX waveformat; UINT devId = WAVE_MAPPER; /* WAVE_MAPPER == choose system's default */ - char *utf8 = NULL; UINT i; if (handle != NULL) { /* specific device requested? */ From 6c6bc81974a787745eaf0c12dcd76257dc0595bb Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 19 Mar 2015 23:54:35 -0400 Subject: [PATCH 093/142] Patched to compile on gcc2. --- src/audio/SDL_sysaudio.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 2b4e95688..502a0d317 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -99,7 +99,11 @@ typedef struct SDL_AudioDeviceItem { void *handle; struct SDL_AudioDeviceItem *next; + #if (defined(__GNUC__) && (__GNUC__ <= 2)) + char name[1]; /* actually variable length. */ + #else char name[]; + #endif } SDL_AudioDeviceItem; From ae08aea51781e009d3787bd06116c54b327cb1cc Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 10:02:45 -0400 Subject: [PATCH 094/142] Fixed some defaults in CMake project file. Fixes not finding dlopen(), etc. --- CMakeLists.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6baff8a0a..23c270fe3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,14 @@ if(EMSCRIPTEN) set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF) set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF) set(DLOPEN_ENABLED_BY_DEFAULT OFF) +else() + set(OPT_DEF_ASM TRUE) + set(SDL_SHARED_ENABLED_BY_DEFAULT ON) + set(SDL_ATOMIC_ENABLED_BY_DEFAULT ON) + set(SDL_THREADS_ENABLED_BY_DEFAULT ON) + set(SDL_LOADSO_ENABLED_BY_DEFAULT ON) + set(SDL_CPUINFO_ENABLED_BY_DEFAULT ON) + set(DLOPEN_ENABLED_BY_DEFAULT ON) endif() set(SDL_SUBSYSTEMS From 2eecc49426f1615d4ac1a0c7d280ab9d92143d82 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 10:35:42 -0400 Subject: [PATCH 095/142] CMake project files no longer force you to link against Wayland or Mir libs. --- CMakeLists.txt | 3 +++ cmake/sdlchecks.cmake | 53 ++++++++++++++++++++++++++++++++++---- include/SDL_config.h.cmake | 13 ++++------ 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23c270fe3..bb69a8410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -274,7 +274,10 @@ set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" O set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS}) set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS}) set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS}) +dep_option(WAYLAND_SHARED "Dynamically load Wayland support" ON "VIDEO_WAYLAND" OFF) +dep_option(VIDEO_WAYLAND_QT_TOUCH "QtWayland server support for Wayland video driver" ON "VIDEO_WAYLAND" OFF) set_option(VIDEO_MIR "Use Mir video driver" ${UNIX_SYS}) +dep_option(MIR_SHARED "Dynamically load Mir support" ON "VIDEO_MIR" OFF) set_option(VIDEO_RPI "Use Raspberry Pi video driver" ${UNIX_SYS}) dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF) set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index e8d746f96..e568dea89 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -505,8 +505,13 @@ macro(CheckX11) endif() endmacro() +# Requires: +# - EGL +# - PkgCheckModules +# Optional: +# - MIR_SHARED opt +# - HAVE_DLOPEN opt macro(CheckMir) -# !!! FIXME: hook up dynamic loading here. if(VIDEO_MIR) find_library(MIR_LIB mirclient mircommon egl) pkg_check_modules(MIR_TOOLKIT mirclient mircommon) @@ -522,15 +527,31 @@ macro(CheckMir) set(SDL_VIDEO_DRIVER_MIR 1) list(APPEND EXTRA_CFLAGS ${MIR_TOOLKIT_CFLAGS} ${EGL_CLFAGS} ${XKB_CLFLAGS}) - list(APPEND EXTRA_LDFLAGS ${MIR_TOOLKIT_LDFLAGS} ${EGL_LDLAGS} ${XKB_LDLAGS}) - endif (MIR_LIB AND MIR_TOOLKIT_FOUND AND EGL_FOUND AND XKB_FOUND) + + if(MIR_SHARED) + if(NOT HAVE_DLOPEN) + message_warn("You must have SDL_LoadObject() support for dynamic Mir loading") + else() + FindLibraryAndSONAME(mirclient) + FindLibraryAndSONAME(xkbcommon) + set(SDL_VIDEO_DRIVER_MIR_DYNAMIC "\"${MIRCLIENT_LIB_SONAME}\"") + set(SDL_VIDEO_DRIVER_MIR_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"") + set(HAVE_MIR_SHARED TRUE) + endif() + else() + set(EXTRA_LIBS ${MIR_TOOLKIT_LIBRARIES} ${EXTRA_LIBS}) + endif() + endif() endif() endmacro() # Requires: # - EGL +# - PkgCheckModules +# Optional: +# - WAYLAND_SHARED opt +# - HAVE_DLOPEN opt macro(CheckWayland) -# !!! FIXME: hook up dynamic loading here. if(VIDEO_WAYLAND) pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon) if(WAYLAND_FOUND) @@ -540,12 +561,34 @@ macro(CheckWayland) include_directories( ${WAYLAND_INCLUDE_DIRS} ) - set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS}) set(HAVE_VIDEO_WAYLAND TRUE) set(HAVE_SDL_VIDEO TRUE) file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c) set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES}) + + if(VIDEO_WAYLAND_QT_TOUCH) + set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1) + endif() + + if(WAYLAND_SHARED) + if(NOT HAVE_DLOPEN) + message_warn("You must have SDL_LoadObject() support for dynamic Wayland loading") + else() + FindLibraryAndSONAME(wayland-client) + FindLibraryAndSONAME(wayland-egl) + FindLibraryAndSONAME(wayland-cursor) + FindLibraryAndSONAME(xkbcommon) + set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC "\"${WAYLAND_CLIENT_LIB_SONAME}\"") + set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL "\"${WAYLAND_EGL_LIB_SONAME}\"") + set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR "\"${WAYLAND_CURSOR_LIB_SONAME}\"") + set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON "\"${XKBCOMMON_LIB_SONAME}\"") + set(HAVE_WAYLAND_SHARED TRUE) + endif() + else() + set(EXTRA_LIBS ${WAYLAND_LIBRARIES} ${EXTRA_LIBS}) + endif() + set(SDL_VIDEO_DRIVER_WAYLAND 1) endif() endif() diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index b12ea524b..db245aa49 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -269,14 +269,11 @@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE @SDL_VIDEO_DRIVER_VIVANTE@ #cmakedefine SDL_VIDEO_DRIVER_VIVANTE_VDK @SDL_VIDEO_DRIVER_VIVANTE_VDK@ -#if 0 -/* !!! FIXME: in configure script version, missing here: */ -#undef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR -#undef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON -#endif +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH @SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_CURSOR@ +#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@ #cmakedefine SDL_VIDEO_DRIVER_MIR @SDL_VIDEO_DRIVER_MIR@ #cmakedefine SDL_VIDEO_DRIVER_MIR_DYNAMIC @SDL_VIDEO_DRIVER_MIR_DYNAMIC@ From 8d0b48cef1fc9ad4c980a80817323dd651492412 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 11:11:44 -0400 Subject: [PATCH 096/142] Audio hotplug fixes for winmm and XAudio2 backends. --- src/audio/SDL_audio.c | 2 +- src/audio/winmm/SDL_winmm.c | 5 +++-- src/audio/xaudio2/SDL_xaudio2.c | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index d937c5af4..603a2adec 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -299,7 +299,7 @@ add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, return -1; } - SDL_assert(handle != NULL); + SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */ item->handle = handle; SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem)); diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index b442e882b..5600ec3a9 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -46,7 +46,7 @@ static void DetectWave##typ##Devs(void) { \ if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \ char *name = WIN_StringToUTF8(caps.szPname); \ if (name != NULL) { \ - SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i)); \ + SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \ SDL_free(name); \ } \ } \ @@ -228,7 +228,8 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) UINT i; if (handle != NULL) { /* specific device requested? */ - const size_t val = (size_t) handle; + /* -1 because we increment the original value to avoid NULL. */ + const size_t val = ((size_t) handle) - 1; devId = (UINT) val; } diff --git a/src/audio/xaudio2/SDL_xaudio2.c b/src/audio/xaudio2/SDL_xaudio2.c index 8aebabf6e..15fce4a8d 100644 --- a/src/audio/xaudio2/SDL_xaudio2.c +++ b/src/audio/xaudio2/SDL_xaudio2.c @@ -146,7 +146,7 @@ XAUDIO2_DetectDevices(void) if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) { char *str = WIN_StringToUTF8(details.DisplayName); if (str != NULL) { - SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i)); + SDL_AddAudioDevice(SDL_FALSE, str, (void *) ((size_t) i+1)); SDL_free(str); /* SDL_AddAudioDevice made a copy of the string. */ } } @@ -297,7 +297,7 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) #if defined(SDL_XAUDIO2_WIN8) LPCWSTR devId = NULL; #else - UINT32 devId = (UINT32) ((size_t) handle); /* 0 == system default device. */ + UINT32 devId = 0; /* 0 == system default device. */ #endif static IXAudio2VoiceCallbackVtbl callbacks_vtable = { @@ -312,6 +312,16 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) static IXAudio2VoiceCallback callbacks = { &callbacks_vtable }; +#if defined(SDL_XAUDIO2_WIN8) + /* !!! FIXME: hook up hotplugging. */ +#else + if (handle != NULL) { /* specific device requested? */ + /* -1 because we increment the original value to avoid NULL. */ + const size_t val = ((size_t) handle) - 1; + devId = (UINT32) val; + } +#endif + if (XAudio2Create(&ixa2, 0, XAUDIO2_DEFAULT_PROCESSOR) != S_OK) { return SDL_SetError("XAudio2: XAudio2Create() failed at open."); } From 2de05b5d5cf59f902ec70e7a67e282ce17ae2ed1 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 11:51:03 -0400 Subject: [PATCH 097/142] CMake: Don't search for the OpenGL library on Mac OS X. It's always there. --- CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bb69a8410..43d1609f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1151,10 +1151,6 @@ elseif(APPLE) set(SDL_VIDEO_OPENGL 1) set(SDL_VIDEO_OPENGL_CGL 1) set(SDL_VIDEO_RENDER_OGL 1) - if(DARWIN) - find_library(OpenGL_LIBRARY OpenGL) - list(APPEND EXTRA_LIBRARIES ${OpenGL_LIBRARY}) - endif() set(HAVE_VIDEO_OPENGL TRUE) endif() endif() From ec0e5f1a7350142f673a8438cbdb02df24c95ba7 Mon Sep 17 00:00:00 2001 From: Marc Di Luzio Date: Fri, 6 Mar 2015 16:03:40 +0000 Subject: [PATCH 098/142] Allow setting of GL_CONTEXT_RELEASE_BEHAVIOR when creating the GL context when GLX_ARB_context_flush_control is available. This extension allows the user to specify whether a full flush is performed when making a context not current. The only way to set this currently is at context creation, so this patch provides that functionality. Defualt behaviour is set at FLUSH, as per the spec. This patch does not contain the changes to WGL, appleGL or other platforms as I do not have access to GL 4.5 hardware on those platforms. Full details on the use of KHR_context_flush_control can be found here: https://www.opengl.org/registry/specs/KHR/context_flush_control.txt --- include/SDL_opengl_glext.h | 5 +++++ include/SDL_video.h | 9 ++++++++- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 11 +++++++++++ src/video/x11/SDL_x11opengl.c | 25 +++++++++++++++++++++++-- src/video/x11/SDL_x11opengl.h | 1 + 6 files changed, 49 insertions(+), 3 deletions(-) diff --git a/include/SDL_opengl_glext.h b/include/SDL_opengl_glext.h index 7e840f72a..cd3869fe7 100644 --- a/include/SDL_opengl_glext.h +++ b/include/SDL_opengl_glext.h @@ -2988,6 +2988,11 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program); #define GL_ARB_framebuffer_sRGB 1 #endif /* GL_ARB_framebuffer_sRGB */ +#ifndef GL_KHR_context_flush_control +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +#endif /* GL_KHR_context_flush_control */ + #ifndef GL_ARB_geometry_shader4 #define GL_ARB_geometry_shader4 1 #define GL_LINES_ADJACENCY_ARB 0x000A diff --git a/include/SDL_video.h b/include/SDL_video.h index 4a2fb0458..782fcb0fb 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -189,7 +189,8 @@ typedef enum SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_SHARE_WITH_CURRENT_CONTEXT, - SDL_GL_FRAMEBUFFER_SRGB_CAPABLE + SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, + SDL_GL_CONTEXT_RELEASE_BEHAVIOR } SDL_GLattr; typedef enum @@ -207,6 +208,12 @@ typedef enum SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008 } SDL_GLcontextFlag; +typedef enum +{ + SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000, + SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001 +} SDL_GLcontextReleaseFlag; + /* Function prototypes */ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 2f0725550..6966f2bd3 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -303,6 +303,7 @@ struct SDL_VideoDevice int flags; int profile_mask; int share_with_current_context; + int release_behavior; int framebuffer_srgb_capable; int retained_backing; int driver_loaded; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 1dcfabf08..ebe102c3d 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2637,6 +2637,7 @@ SDL_GL_ResetAttributes() #endif _this->gl_config.flags = 0; _this->gl_config.framebuffer_srgb_capable = 0; + _this->gl_config.release_behavior = SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH; _this->gl_config.share_with_current_context = 0; } @@ -2743,6 +2744,9 @@ SDL_GL_SetAttribute(SDL_GLattr attr, int value) case SDL_GL_FRAMEBUFFER_SRGB_CAPABLE: _this->gl_config.framebuffer_srgb_capable = value; break; + case SDL_GL_CONTEXT_RELEASE_BEHAVIOR: + _this->gl_config.release_behavior = value; + break; default: retval = SDL_SetError("Unknown OpenGL attribute"); break; @@ -2843,6 +2847,13 @@ SDL_GL_GetAttribute(SDL_GLattr attr, int *value) attrib = GL_SAMPLES_ARB; #else attrib = GL_SAMPLES; +#endif + break; + case SDL_GL_CONTEXT_RELEASE_BEHAVIOR: +#if SDL_VIDEO_OPENGL + attrib = GL_CONTEXT_RELEASE_BEHAVIOR; +#else + attrib = GL_CONTEXT_RELEASE_BEHAVIOR_KHR; #endif break; case SDL_GL_BUFFER_SIZE: diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index f89a9cc0a..df6008ccd 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -122,6 +122,13 @@ typedef GLXContext(*PFNGLXCREATECONTEXTATTRIBSARBPROC) (Display * dpy, #define GLX_LATE_SWAPS_TEAR_EXT 0x20F3 #endif +#ifndef GLX_ARB_context_flush_control +#define GLX_ARB_context_flush_control +#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000 +#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 +#endif + #define OPENGL_REQUIRES_DLOPEN #if defined(OPENGL_REQUIRES_DLOPEN) && defined(SDL_LOADSO_DLOPEN) #include @@ -375,6 +382,11 @@ X11_GL_InitExtensions(_THIS) if (HasExtension("GLX_EXT_create_context_es2_profile", extensions)) { _this->gl_data->HAS_GLX_EXT_create_context_es2_profile = SDL_TRUE; } + + /* Check for GLX_ARB_context_flush_control */ + if (HasExtension("GLX_ARB_context_flush_control", extensions)) { + _this->gl_data->HAS_GLX_ARB_context_flush_control = SDL_TRUE; + } } /* glXChooseVisual and glXChooseFBConfig have some small differences in @@ -581,8 +593,8 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) context = _this->gl_data->glXCreateContext(display, vinfo, share_context, True); } else { - /* max 8 attributes plus terminator */ - int attribs[9] = { + /* max 10 attributes plus terminator */ + int attribs[11] = { GLX_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, GLX_CONTEXT_MINOR_VERSION_ARB, @@ -603,6 +615,15 @@ X11_GL_CreateContext(_THIS, SDL_Window * window) attribs[iattr++] = _this->gl_config.flags; } + /* only set if glx extension is available */ + if( _this->gl_data->HAS_GLX_ARB_context_flush_control ) { + attribs[iattr++] = GLX_CONTEXT_RELEASE_BEHAVIOR_ARB; + attribs[iattr++] = + _this->gl_config.release_behavior ? + GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : + GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; + } + attribs[iattr++] = 0; /* Get a pointer to the context creation function for GL 3.0 */ diff --git a/src/video/x11/SDL_x11opengl.h b/src/video/x11/SDL_x11opengl.h index b3410fd46..5856c9b79 100644 --- a/src/video/x11/SDL_x11opengl.h +++ b/src/video/x11/SDL_x11opengl.h @@ -35,6 +35,7 @@ struct SDL_GLDriverData SDL_bool HAS_GLX_EXT_visual_info; SDL_bool HAS_GLX_EXT_swap_control_tear; SDL_bool HAS_GLX_EXT_create_context_es2_profile; + SDL_bool HAS_GLX_ARB_context_flush_control; Bool (*glXQueryExtension) (Display*,int*,int*); void *(*glXGetProcAddress) (const GLubyte*); From 4abae0105fc1e1902e79704b0ae51d8eeb908f64 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 12:23:53 -0400 Subject: [PATCH 099/142] Windows: support for OpenGL extension WGL_ARB_context_flush_control. --- src/video/windows/SDL_windowsopengl.c | 24 ++++++++++++++++++++++-- src/video/windows/SDL_windowsopengl.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/video/windows/SDL_windowsopengl.c b/src/video/windows/SDL_windowsopengl.c index 71855c874..bab97fae0 100644 --- a/src/video/windows/SDL_windowsopengl.c +++ b/src/video/windows/SDL_windowsopengl.c @@ -74,6 +74,13 @@ #define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9 #endif +#ifndef WGL_ARB_context_flush_control +#define WGL_ARB_context_flush_control +#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000 +#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 +#endif + typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, @@ -405,6 +412,11 @@ WIN_GL_InitExtensions(_THIS) _this->gl_data->HAS_WGL_EXT_create_context_es2_profile = SDL_TRUE; } + /* Check for GLX_ARB_context_flush_control */ + if (HasExtension("WGL_ARB_context_flush_control", extensions)) { + _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE; + } + _this->gl_data->wglMakeCurrent(hdc, NULL); _this->gl_data->wglDeleteContext(hglrc); ReleaseDC(hwnd, hdc); @@ -648,8 +660,8 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window) SDL_SetError("GL 3.x is not supported"); context = temp_context; } else { - /* max 8 attributes plus terminator */ - int attribs[9] = { + /* max 10 attributes plus terminator */ + int attribs[11] = { WGL_CONTEXT_MAJOR_VERSION_ARB, _this->gl_config.major_version, WGL_CONTEXT_MINOR_VERSION_ARB, _this->gl_config.minor_version, 0 @@ -668,6 +680,14 @@ WIN_GL_CreateContext(_THIS, SDL_Window * window) attribs[iattr++] = _this->gl_config.flags; } + /* only set if wgl extension is available */ + if( _this->gl_data->HAS_WGL_ARB_context_flush_control ) { + attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB; + attribs[iattr++] = _this->gl_config.release_behavior ? + WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB : + WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB; + } + attribs[iattr++] = 0; /* Create the GL 3.x context */ diff --git a/src/video/windows/SDL_windowsopengl.h b/src/video/windows/SDL_windowsopengl.h index b96e0ac1e..b95b90f74 100644 --- a/src/video/windows/SDL_windowsopengl.h +++ b/src/video/windows/SDL_windowsopengl.h @@ -30,6 +30,7 @@ struct SDL_GLDriverData SDL_bool HAS_WGL_ARB_pixel_format; SDL_bool HAS_WGL_EXT_swap_control_tear; SDL_bool HAS_WGL_EXT_create_context_es2_profile; + SDL_bool HAS_WGL_ARB_context_flush_control; void *(WINAPI * wglGetProcAddress) (const char *proc); HGLRC(WINAPI * wglCreateContext) (HDC hdc); From 5e4b3fca008382c0db22fc002df02a9fb3079f73 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 21:57:15 -0400 Subject: [PATCH 100/142] Several corrections to the CMake project files (thanks, Ozkan!). Fixes Bugzilla #2732. --- CMakeLists.txt | 11 ++++++++++- cmake/sdlchecks.cmake | 13 ++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 43d1609f1..1b07a2b93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -596,7 +596,7 @@ if(LIBC) set(CMAKE_REQUIRED_LIBRARIES m) foreach(_FN atan atan2 ceil copysign cos cosf fabs floor log pow scalbn sin - sinf sqrt sqrtf tan tanf) + sinf sqrt sqrtf tan tanf acos asin) string(TOUPPER ${_FN} _UPPER) set(_HAVEVAR "HAVE_${_UPPER}") check_function_exists("${_FN}" ${_HAVEVAR}) @@ -608,6 +608,15 @@ if(LIBC) check_library_exists(iconv iconv_open "" HAVE_LIBICONV) if(HAVE_LIBICONV) list(APPEND EXTRA_LIBS iconv) + set(HAVE_ICONV 1) + endif() + + if(NOT APPLE) + check_include_file(alloca.h HAVE_ALLOCA_H) + check_function_exists(alloca HAVE_ALLOCA) + else() + set(HAVE_ALLOCA_H 1) + set(HAVE_ALLOCA 1) endif() check_struct_has_member("struct sigaction" "sa_sigaction" "signal.h" HAVE_SA_SIGACTION) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index e568dea89..fd54ed29e 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -725,7 +725,7 @@ macro(CheckOpenGLESX11) endif() endmacro() -# Rquires: +# Requires: # - nada # Optional: # - THREADS opt @@ -776,13 +776,17 @@ macro(CheckPTHREAD) # Run some tests set(CMAKE_REQUIRED_FLAGS "${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}") - check_c_source_runs(" + if(CMAKE_CROSSCOMPILING) + set(HAVE_PTHREADS 1) + else() + check_c_source_runs(" #include int main(int argc, char** argv) { pthread_attr_t type; pthread_attr_init(&type); return 0; }" HAVE_PTHREADS) + endif() if(HAVE_PTHREADS) set(SDL_THREAD_PTHREAD 1) list(APPEND EXTRA_CFLAGS ${PTHREAD_CFLAGS}) @@ -831,9 +835,8 @@ macro(CheckPTHREAD) #include #include int main(int argc, char** argv) { return 0; }" HAVE_PTHREAD_NP_H) - check_function_exists(pthread_setname_np HAVE_PTHREAD_setNAME_NP) - check_function_exists(pthread_set_name_np HAVE_PTHREAD_set_NAME_NP) - set(CMAKE_REQUIRED_FLAGS) + check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP) + check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP) set(CMAKE_REQUIRED_FLAGS) set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c From a8024d0dec29aa3e54b53bfc3706bb9fc73966b5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 20 Mar 2015 23:29:09 -0400 Subject: [PATCH 101/142] Whoops, lost a newline in here. --- cmake/sdlchecks.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index fd54ed29e..f390fcbd0 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -836,7 +836,8 @@ macro(CheckPTHREAD) #include int main(int argc, char** argv) { return 0; }" HAVE_PTHREAD_NP_H) check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP) - check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP) set(CMAKE_REQUIRED_FLAGS) + check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP) + set(CMAKE_REQUIRED_FLAGS) set(SOURCE_FILES ${SOURCE_FILES} ${SDL2_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c From ee9303f84507307c9ef75051a7163ad59c74ae8c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 21 Mar 2015 00:09:22 -0400 Subject: [PATCH 102/142] Patched to compile on OpenGL ES-based platforms. --- src/video/SDL_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index ebe102c3d..b93c11e76 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -46,6 +46,10 @@ #include "SDL_opengles2.h" #endif /* SDL_VIDEO_OPENGL_ES2 && !SDL_VIDEO_OPENGL */ +#ifndef GL_CONTEXT_RELEASE_BEHAVIOR_KHR +#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB +#endif + /* On Windows, windows.h defines CreateWindow */ #ifdef CreateWindow #undef CreateWindow From 1abb012ae57044ad74531c104d17bc4599c6d8b4 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 21 Mar 2015 08:01:43 +0100 Subject: [PATCH 103/142] Fixed confusing audio and touch events because of shared enumeration values. --- include/SDL_events.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index 521b65be1..65818af95 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -110,10 +110,6 @@ typedef enum SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */ - /* Audio hotplug events */ - SDL_AUDIODEVICEADDED = 0x700, /**< A new audio device is available */ - SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */ - /* Game controller events */ SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */ SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */ @@ -138,6 +134,10 @@ typedef enum /* Drag and drop events */ SDL_DROPFILE = 0x1000, /**< The system requests a file open */ + /* Audio hotplug events */ + SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */ + SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */ + /* Render events */ SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */ SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */ From 4c9b75b83929b7bcc6f6ff58b08b1437a552a718 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Sat, 21 Mar 2015 22:42:53 +0100 Subject: [PATCH 104/142] Added missing SDL_DOLLARRECORD event type documentation in header. --- include/SDL_events.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index 65818af95..ee61421f6 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -440,7 +440,7 @@ typedef struct SDL_MultiGestureEvent */ typedef struct SDL_DollarGestureEvent { - Uint32 type; /**< ::SDL_DOLLARGESTURE */ + Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */ Uint32 timestamp; SDL_TouchID touchId; /**< The touch device id */ SDL_GestureID gestureId; From 7e2f6f1519f545c0d7d4b60ca8288ed40eba447c Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 22 Mar 2015 01:25:12 -0400 Subject: [PATCH 105/142] Cocoa: Handle more cases of lost focus when Key window closes (thanks, Alex!). Sort of fixes Bugzilla #1825 a little more. It's an ongoing effort. :) --HG-- extra : rebase_source : 38d5f2acbb118274e69d72205c747350c3e23a9c --- src/video/cocoa/SDL_cocoaevents.m | 69 ++++++++++++++++++++++++++++--- src/video/cocoa/SDL_cocoawindow.m | 20 --------- 2 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index 51020347e..925f05b8e 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -66,11 +66,19 @@ { self = [super init]; if (self) { + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + seenFirstActivate = NO; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(focusSomeWindow:) - name:NSApplicationDidBecomeActiveNotification - object:nil]; + + [center addObserver:self + selector:@selector(windowWillClose:) + name:NSWindowWillCloseNotification + object:nil]; + + [center addObserver:self + selector:@selector(focusSomeWindow:) + name:NSApplicationDidBecomeActiveNotification + object:nil]; } return self; @@ -78,16 +86,65 @@ - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + + [center removeObserver:self name:NSWindowWillCloseNotification object:nil]; + [center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil]; + [super dealloc]; } +- (void)windowWillClose:(NSNotification *)notification; +{ + NSWindow *win = (NSWindow*)[notification object]; + + if (![win isKeyWindow]) { + return; + } + + /* HACK: Make the next window in the z-order key when the key window is + * closed. The custom event loop and/or windowing code we have seems to + * prevent the normal behavior: https://bugzilla.libsdl.org/show_bug.cgi?id=1825 + */ + + /* +[NSApp orderedWindows] never includes the 'About' window, but we still + * want to try its list first since the behavior in other apps is to only + * make the 'About' window key if no other windows are on-screen. + */ + for (NSWindow *window in [NSApp orderedWindows]) { + if (window != win && [window canBecomeKeyWindow]) { + if ([window respondsToSelector:@selector(isOnActiveSpace)]) { + if (![window isOnActiveSpace]) { + continue; + } + } + [window makeKeyAndOrderFront:self]; + return; + } + } + + /* If a window wasn't found above, iterate through all visible windows + * (including the 'About' window, if it's shown) and make the first one key. + * Note that +[NSWindow windowNumbersWithOptions:] was added in 10.6. + */ + if ([NSWindow respondsToSelector:@selector(windowNumbersWithOptions:)]) { + /* Get all visible windows in the active Space, in z-order. */ + for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) { + NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]]; + if (window && window != win && [window canBecomeKeyWindow]) { + [window makeKeyAndOrderFront:self]; + return; + } + } + } +} + - (void)focusSomeWindow:(NSNotification *)aNotification { /* HACK: Ignore the first call. The application gets a * applicationDidBecomeActive: a little bit after the first window is * created, and if we don't ignore it, a window that has been created with - * SDL_WINDOW_MINIZED will ~immediately be restored. + * SDL_WINDOW_MINIMIZED will ~immediately be restored. */ if (!seenFirstActivate) { seenFirstActivate = YES; diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m index d5455290a..068c59e02 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -374,7 +374,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) NSNotificationCenter *center; NSWindow *window = _data->nswindow; NSView *view = [window contentView]; - NSArray *windows = nil; center = [NSNotificationCenter defaultCenter]; @@ -402,25 +401,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) if ([view nextResponder] == self) { [view setNextResponder:nil]; } - - /* Make the next window in the z-order Key. If we weren't the foreground - when closed, this is a no-op. - !!! FIXME: Note that this is a hack, and there are corner cases where - !!! FIXME: this fails (such as the About box). The typical nib+RunLoop - !!! FIXME: handles this for Cocoa apps, but we bypass all that in SDL. - !!! FIXME: We should remove this code when we find a better way to - !!! FIXME: have the system do this for us. See discussion in - !!! FIXME: http://bugzilla.libsdl.org/show_bug.cgi?id=1825 - */ - windows = [NSApp orderedWindows]; - for (NSWindow *win in windows) { - if (win == window) { - continue; - } - - [win makeKeyAndOrderFront:self]; - break; - } } - (BOOL)isMoving From 940b699079c310af81bd706ab97c9ddf5ec4ab4b Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 23 Mar 2015 20:21:45 +0100 Subject: [PATCH 106/142] Updated test program for Emscripten. --- test/loopwavequeue.c | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/test/loopwavequeue.c b/test/loopwavequeue.c index 6d7128575..babff3b3f 100644 --- a/test/loopwavequeue.c +++ b/test/loopwavequeue.c @@ -15,6 +15,10 @@ #include #include +#ifdef __EMSCRIPTEN__ +#include +#endif + #include "SDL.h" #if HAVE_SIGNAL_H @@ -45,6 +49,29 @@ poked(int sig) done = 1; } +void +loop() +{ +#ifdef __EMSCRIPTEN__ + if (done || (SDL_GetAudioStatus() != SDL_AUDIO_PLAYING)) { + emscripten_cancel_main_loop(); + } + else +#endif + { + /* The device from SDL_OpenAudio() is always device #1. */ + const Uint32 queued = SDL_GetQueuedAudioSize(1); + SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued); + if (queued <= 8192) { /* time to requeue the whole thing? */ + if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) { + SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen); + } else { + SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError()); + } + } + } +} + int main(int argc, char *argv[]) { @@ -96,25 +123,22 @@ main(int argc, char *argv[]) /* Let the audio run */ SDL_PauseAudio(0); + done = 0; + /* Note that we stuff the entire audio buffer into the queue in one shot. Most apps would want to feed it a little at a time, as it plays, but we're going for simplicity here. */ +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(loop, 0, 1); +#else while (!done && (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING)) { - /* The device from SDL_OpenAudio() is always device #1. */ - const Uint32 queued = SDL_GetQueuedAudioSize(1); - SDL_Log("Device has %u bytes queued.\n", (unsigned int) queued); - if (queued <= 8192) { /* time to requeue the whole thing? */ - if (SDL_QueueAudio(1, wave.sound, wave.soundlen) == 0) { - SDL_Log("Device queued %u more bytes.\n", (unsigned int) wave.soundlen); - } else { - SDL_Log("Device FAILED to queue %u more bytes: %s\n", (unsigned int) wave.soundlen, SDL_GetError()); - } - } + loop(); SDL_Delay(100); /* let it play for awhile. */ } +#endif /* Clean up on signal */ SDL_CloseAudio(); From cd86ab1347f116022df4516c57a8ddfb13ce1639 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Mon, 23 Mar 2015 20:24:04 +0100 Subject: [PATCH 107/142] Android: Removed not needed include statement. --- src/audio/SDL_audio.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 603a2adec..dfc55fa62 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -590,10 +590,6 @@ SDL_ClearQueuedAudio(SDL_AudioDeviceID devid) } -#if defined(__ANDROID__) -#include -#endif - /* The general mixing thread function */ int SDLCALL SDL_RunAudio(void *devicep) From a0881fff0038ed10427b98d92ae6025238de3432 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Mar 2015 19:47:08 -0400 Subject: [PATCH 108/142] Windows: Report window HDC in SDL_SysWMinfo. Fixes Bugzilla #2668. --HG-- extra : rebase_source : d45a1a2af2c6e79d4b778383dd88a6a994c3e81a --- include/SDL_syswm.h | 1 + src/video/windows/SDL_windowswindow.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/SDL_syswm.h b/include/SDL_syswm.h index 03c3b025d..c26533384 100644 --- a/include/SDL_syswm.h +++ b/include/SDL_syswm.h @@ -186,6 +186,7 @@ struct SDL_SysWMinfo struct { HWND window; /**< The window handle */ + HDC hdc; /**< The window device context */ } win; #endif #if defined(SDL_VIDEO_DRIVER_WINRT) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index 94328339f..463db1e06 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -643,10 +643,11 @@ WIN_DestroyWindow(_THIS, SDL_Window * window) SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata; if (info->version.major <= SDL_MAJOR_VERSION) { info->subsystem = SDL_SYSWM_WINDOWS; - info->info.win.window = hwnd; + info->info.win.window = data->hwnd; + info->info.win.hdc = data->hdc; return SDL_TRUE; } else { SDL_SetError("Application not compiled with SDL %d.%d\n", From 8b5daef277351045672b38c7d92ebf66f907353d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Mar 2015 19:54:33 -0400 Subject: [PATCH 109/142] X11: Reenabled setlocale() and fork() for message boxes. Fixes Bugzilla #1658. --- src/video/x11/SDL_x11messagebox.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index e8396c562..ea99cdc25 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -31,8 +31,8 @@ #include -#define SDL_FORK_MESSAGEBOX 0 -#define SDL_SET_LOCALE 0 +#define SDL_FORK_MESSAGEBOX 1 +#define SDL_SET_LOCALE 1 #if SDL_FORK_MESSAGEBOX #include @@ -718,9 +718,6 @@ X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) int fds[2]; int status = 0; - /* Need to flush here in case someone has turned grab off and it hasn't gone through yet, etc. */ - X11_XFlush(data->display); - if (pipe(fds) == -1) { return X11_ShowMessageBoxImpl(messageboxdata, buttonid); /* oh well. */ } From c01c90ce0cc7366d312b02c0a0eb3006fea9b9c2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 23 Mar 2015 20:07:24 -0400 Subject: [PATCH 110/142] configure script: fix recursive mutex test on Linux systems (thanks, Ozkan!). --- configure | 12 ++++++++---- configure.in | 6 ++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/configure b/configure index 81e6b24b2..e220948ad 100755 --- a/configure +++ b/configure @@ -21916,6 +21916,7 @@ $as_echo_n "checking for recursive mutexes... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #define _GNU_SOURCE 1 #include int @@ -21929,7 +21930,7 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : has_recursive_mutexes=yes @@ -21937,12 +21938,14 @@ $as_echo "#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi if test x$has_recursive_mutexes = xno; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ + #define _GNU_SOURCE 1 #include int @@ -21956,7 +21959,7 @@ main () return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : +if ac_fn_c_try_link "$LINENO"; then : has_recursive_mutexes=yes @@ -21964,7 +21967,8 @@ $as_echo "#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1" >>confdefs.h fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_recursive_mutexes" >&5 $as_echo "$has_recursive_mutexes" >&6; } diff --git a/configure.in b/configure.in index a2ad20a67..6e3878247 100644 --- a/configure.in +++ b/configure.in @@ -2424,7 +2424,8 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]]) AC_MSG_CHECKING(for recursive mutexes) has_recursive_mutexes=no if test x$has_recursive_mutexes = xno; then - AC_TRY_COMPILE([ + AC_TRY_LINK([ + #define _GNU_SOURCE 1 #include ],[ pthread_mutexattr_t attr; @@ -2435,7 +2436,8 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]]) ]) fi if test x$has_recursive_mutexes = xno; then - AC_TRY_COMPILE([ + AC_TRY_LINK([ + #define _GNU_SOURCE 1 #include ],[ pthread_mutexattr_t attr; From 8dacecf1c6e1da78589386c00a24e6f51492ccf8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 02:13:25 -0400 Subject: [PATCH 111/142] winmm: Let audio callback buffer size be less than 1/4 second (thanks, Jon!). Maybe this was here for Win9x? There's no reason to insert this much latency by default. Fixes Bugzilla #2835. --- src/audio/winmm/SDL_winmm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/audio/winmm/SDL_winmm.c b/src/audio/winmm/SDL_winmm.c index 5600ec3a9..a61ac237d 100644 --- a/src/audio/winmm/SDL_winmm.c +++ b/src/audio/winmm/SDL_winmm.c @@ -248,10 +248,6 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) if (this->spec.channels > 2) this->spec.channels = 2; /* !!! FIXME: is this right? */ - /* Check the buffer size -- minimum of 1/4 second (word aligned) */ - if (this->spec.samples < (this->spec.freq / 4)) - this->spec.samples = ((this->spec.freq / 4) + 3) & ~3; - while ((!valid_datatype) && (test_format)) { switch (test_format) { case AUDIO_U8: From c3c8b8335a978b385800df4bdfd7b75ab0169eea Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 02:47:25 -0400 Subject: [PATCH 112/142] Added Logitect RumblePad 2 controller mapping for Linux (thanks, Nicholas!). Fixes Bugzilla #2091. --- src/joystick/SDL_gamecontrollerdb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index ddd537139..e0eb9e4e9 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -74,6 +74,7 @@ static const char *s_ControllerMappings [] = "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", + "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", #endif #if defined(__ANDROID__) "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", From 9da4b2b5b83dec831b7f35f533f97ede1baac51a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 02:48:16 -0400 Subject: [PATCH 113/142] Ran hardcoded game controller database through sort_controllers.py. --- src/joystick/SDL_gamecontrollerdb.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index e0eb9e4e9..e864834da 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -63,6 +63,7 @@ static const char *s_ControllerMappings [] = "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", + "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", "050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", @@ -73,14 +74,13 @@ static const char *s_ControllerMappings [] = "030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", - "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,", - "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,", + "030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", #endif #if defined(__ANDROID__) "4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", #endif #if defined(SDL_JOYSTICK_EMSCRIPTEN) - "emscripten,Standard Gamepad,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,back:b8,start:b9,leftstick:b10,rightstick:b11,dpup:b12,dpdown:b13,dpleft:b14,dpright:b15,guide:b16,leftx:a0,lefty:a1,rightx:a2,righty:a3,", + "emscripten,Standard Gamepad,a:b0,b:b1,back:b8,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b16,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", #endif NULL }; From 1816bcb659c3929dbb11843c1e9833d9f24408a5 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 03:12:35 -0400 Subject: [PATCH 114/142] Make SDL error string formatting deal with nasty corner cases. We continued looping while maxlen > 0, but maxlen was unsigned, so an overflow would make it a large number instead of negative. Fixed. Some snprintf() implementations might return a negative value if there isn't enough space, and we now check for that. Don't overrun the SDL error message buffer, if snprintf() returned the number of chars it wanted to write instead of the number it did. snprintf is a portability mess, we should just never use the C runtime for it. Fixes Bugzilla #2049. --HG-- extra : histedit_source : 4c21dac5eefc6070bc54a5a83be523d28d484844%2C790b58948a82e2a4322d9ddd1e298bc873d44d4a --- src/SDL_error.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/SDL_error.c b/src/SDL_error.c index 2df29aa13..80e8620f8 100644 --- a/src/SDL_error.c +++ b/src/SDL_error.c @@ -120,7 +120,7 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) so that it supports internationalization and thread-safe errors. */ static char * -SDL_GetErrorMsg(char *errstr, unsigned int maxlen) +SDL_GetErrorMsg(char *errstr, int maxlen) { SDL_error *error; @@ -163,37 +163,55 @@ SDL_GetErrorMsg(char *errstr, unsigned int maxlen) len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_i); - msg += len; - maxlen -= len; + if (len > 0) { + msg += len; + maxlen -= len; + } break; + case 'f': len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_f); - msg += len; - maxlen -= len; + if (len > 0) { + msg += len; + maxlen -= len; + } break; + case 'p': len = SDL_snprintf(msg, maxlen, tmp, error->args[argi++].value_ptr); - msg += len; - maxlen -= len; + if (len > 0) { + msg += len; + maxlen -= len; + } break; + case 's': len = SDL_snprintf(msg, maxlen, tmp, SDL_LookupString(error->args[argi++]. buf)); - msg += len; - maxlen -= len; + if (len > 0) { + msg += len; + maxlen -= len; + } break; + } } else { *msg++ = *fmt++; maxlen -= 1; } } + + /* slide back if we've overshot the end of our buffer. */ + if (maxlen < 0) { + msg -= (-maxlen) + 1; + } + *msg = 0; /* NULL terminate the string */ } return (errstr); From 2b9c893e8b3606acd3a517fedd1b23a5db6afe53 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 03:21:57 -0400 Subject: [PATCH 115/142] Better fixes for CMake subsystem enabling (thanks, Sebastian!). Fixes Bugzilla #2875. --- CMakeLists.txt | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b07a2b93..d24a95bb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,9 +118,9 @@ else() endif() if (UNIX_OR_MAC_SYS AND NOT EMSCRIPTEN) # JavaScript does not yet have threading support, so disable pthreads when building for Emscripten. - set(PTHREADS_ENABLED_BY_DEFAULT ON) + set(SDL_PTHREADS_ENABLED_BY_DEFAULT ON) else() - set(PTHREADS_ENABLED_BY_DEFAULT OFF) + set(SDL_PTHREADS_ENABLED_BY_DEFAULT OFF) endif() # Default option knobs @@ -202,6 +202,7 @@ include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include) # All these ENABLED_BY_DEFAULT vars will default to ON if not specified, so # you only need to have a platform override them if they are disabling. +set(OPT_DEF_ASM TRUE) if(EMSCRIPTEN) # Set up default values for the currently supported set of subsystems: # Emscripten/Javascript does not have assembly support, a dynamic library @@ -212,20 +213,12 @@ if(EMSCRIPTEN) set(SDL_THREADS_ENABLED_BY_DEFAULT OFF) set(SDL_LOADSO_ENABLED_BY_DEFAULT OFF) set(SDL_CPUINFO_ENABLED_BY_DEFAULT OFF) - set(DLOPEN_ENABLED_BY_DEFAULT OFF) -else() - set(OPT_DEF_ASM TRUE) - set(SDL_SHARED_ENABLED_BY_DEFAULT ON) - set(SDL_ATOMIC_ENABLED_BY_DEFAULT ON) - set(SDL_THREADS_ENABLED_BY_DEFAULT ON) - set(SDL_LOADSO_ENABLED_BY_DEFAULT ON) - set(SDL_CPUINFO_ENABLED_BY_DEFAULT ON) - set(DLOPEN_ENABLED_BY_DEFAULT ON) + set(SDL_DLOPEN_ENABLED_BY_DEFAULT OFF) endif() set(SDL_SUBSYSTEMS Atomic Audio Video Render Events Joystick Haptic Power Threads Timers - File Loadso CPUinfo Filesystem) + File Loadso CPUinfo Filesystem Dlopen) foreach(_SUB ${SDL_SUBSYSTEMS}) string(TOUPPER ${_SUB} _OPT) if (NOT DEFINED SDL_${_OPT}_ENABLED_BY_DEFAULT) @@ -254,9 +247,9 @@ dep_option(FUSIONSOUND_SHARED "Dynamically load fusionsound audio support" ON " set_option(VIDEO_DUMMY "Use dummy video driver" ON) set_option(VIDEO_OPENGL "Include OpenGL support" ON) set_option(VIDEO_OPENGLES "Include OpenGL ES support" ON) -set_option(PTHREADS "Use POSIX threads for multi-threading" ${PTHREADS_ENABLED_BY_DEFAULT}) +set_option(PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_ENABLED_BY_DEFAULT}) dep_option(PTHREADS_SEM "Use pthread semaphores" ON "PTHREADS" OFF) -set_option(SDL_DLOPEN "Use dlopen for shared object loading" ${DLOPEN_ENABLED_BY_DEFAULT}) +set_option(SDL_DLOPEN "Use dlopen for shared object loading" ${SDL_DLOPEN_ENABLED_BY_DEFAULT}) set_option(OSS "Support the OSS audio API" ${UNIX_SYS}) set_option(ALSA "Support the ALSA audio API" ${UNIX_SYS}) dep_option(ALSA_SHARED "Dynamically load ALSA audio support" ON "ALSA" OFF) From e03d7a79a95c710695b7500f09522decd6a4c8e7 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 03:24:57 -0400 Subject: [PATCH 116/142] Mac: patched to compile with haptic subsystem disabled (thanks, Rodrigo!). Fixes Bugzilla #2717. --- src/joystick/darwin/SDL_sysjoystick.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index 45966b72b..cc8228691 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -412,12 +412,12 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */ const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); +#if SDL_HAPTIC_IOKIT if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { device->ffservice = ioservice; -#if SDL_HAPTIC_IOKIT MacHaptic_MaybeAddDevice(ioservice); -#endif } +#endif } device->send_open_event = 1; From 3ff618a9c747fc39748f86aad31a19bf529ec1d2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 13:52:01 -0400 Subject: [PATCH 117/142] Cleanups in the joystick code. Removed some redundant state and other confusions. Fixes Bugzilla #2738. --HG-- extra : rebase_source : 35dd561553379e00eb8d169ce12ecc99393b2f84 --- src/joystick/SDL_joystick.c | 9 +++------ src/joystick/SDL_sysjoystick.h | 3 +-- src/joystick/android/SDL_sysjoystick.c | 7 +------ src/joystick/bsd/SDL_sysjoystick.c | 2 -- src/joystick/darwin/SDL_sysjoystick.c | 21 ++++++--------------- src/joystick/darwin/SDL_sysjoystick_c.h | 3 +-- src/joystick/dummy/SDL_sysjoystick.c | 5 +---- src/joystick/emscripten/SDL_sysjoystick.c | 7 +------ src/joystick/haiku/SDL_haikujoystick.cc | 1 - src/joystick/iphoneos/SDL_sysjoystick.m | 1 - src/joystick/linux/SDL_sysjoystick.c | 4 +--- src/joystick/psp/SDL_sysjoystick.c | 1 - src/joystick/windows/SDL_mmjoystick.c | 2 -- src/joystick/windows/SDL_windowsjoystick.c | 11 +++-------- test/testjoystick.c | 6 ++++++ 15 files changed, 24 insertions(+), 59 deletions(-) diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 2a60c0036..44cc21677 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -206,10 +206,6 @@ SDL_PrivateJoystickValid(SDL_Joystick * joystick) valid = 1; } - if (joystick && joystick->closed) { - valid = 0; - } - return valid; } @@ -412,6 +408,7 @@ SDL_JoystickClose(SDL_Joystick * joystick) } SDL_SYS_JoystickClose(joystick); + joystick->hwdata = NULL; joysticklist = SDL_joysticks; joysticklistprev = NULL; @@ -668,7 +665,7 @@ SDL_JoystickUpdate(void) SDL_SYS_JoystickUpdate(joystick); - if (joystick->closed && joystick->uncentered) { + if (joystick->force_recentering) { int i; /* Tell the app that everything is centered/unpressed... */ @@ -681,7 +678,7 @@ SDL_JoystickUpdate(void) for (i = 0; i < joystick->nhats; i++) SDL_PrivateJoystickHat(joystick, i, SDL_HAT_CENTERED); - joystick->uncentered = SDL_FALSE; + joystick->force_recentering = SDL_FALSE; } SDL_updating_joystick = NULL; diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 819a961af..f126e7519 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -53,8 +53,7 @@ struct _SDL_Joystick int ref_count; /* Reference count for multiple opens */ - SDL_bool closed; /* SDL_TRUE if this device is no longer valid */ - SDL_bool uncentered; /* SDL_TRUE if this device needs to have its state reset to 0 */ + SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */ struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */ }; diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 49fa58428..3d82fcb5b 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -498,7 +498,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) /* Function to determine is this joystick is attached to the system right now */ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick) { - return !joystick->closed && (joystick->hwdata != NULL); + return joystick->hwdata != NULL; } void @@ -529,11 +529,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - if (joystick->hwdata) { - ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL; - joystick->hwdata = NULL; - } - joystick->closed = 1; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/bsd/SDL_sysjoystick.c b/src/joystick/bsd/SDL_sysjoystick.c index 65a32ed2e..efbd79c59 100644 --- a/src/joystick/bsd/SDL_sysjoystick.c +++ b/src/joystick/bsd/SDL_sysjoystick.c @@ -558,8 +558,6 @@ SDL_SYS_JoystickClose(SDL_Joystick * joy) close(joy->hwdata->fd); SDL_free(joy->hwdata->path); SDL_free(joy->hwdata); - - return; } void diff --git a/src/joystick/darwin/SDL_sysjoystick.c b/src/joystick/darwin/SDL_sysjoystick.c index cc8228691..fc7ae7554 100644 --- a/src/joystick/darwin/SDL_sysjoystick.c +++ b/src/joystick/darwin/SDL_sysjoystick.c @@ -138,7 +138,7 @@ static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender) { recDevice *device = (recDevice *) ctx; - device->removed = 1; + device->removed = SDL_TRUE; device->deviceRef = NULL; // deviceRef was invalidated due to the remove #if SDL_HAPTIC_IOKIT MacHaptic_MaybeRemoveDevice(device->ffservice); @@ -677,16 +677,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick) { - recDevice *device = gpDeviceList; - - while (device) { - if (joystick->instance_id == device->instance_id) { - return SDL_TRUE; - } - device = device->pNext; - } - - return SDL_FALSE; + return joystick->hwdata != NULL; } /* Function to update the state of a joystick - called as a device poll. @@ -707,9 +698,10 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) } if (device->removed) { /* device was unplugged; ignore it. */ - joystick->closed = 1; - joystick->uncentered = 1; - joystick->hwdata = NULL; + if (joystick->hwdata) { + joystick->force_recentering = SDL_TRUE; + joystick->hwdata = NULL; + } return; } @@ -797,7 +789,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - joystick->closed = 1; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/darwin/SDL_sysjoystick_c.h b/src/joystick/darwin/SDL_sysjoystick_c.h index 0a15ba18d..4c3300dca 100644 --- a/src/joystick/darwin/SDL_sysjoystick_c.h +++ b/src/joystick/darwin/SDL_sysjoystick_c.h @@ -58,8 +58,7 @@ struct joystick_hwdata recElement *firstButton; recElement *firstHat; - int removed; - int uncentered; + SDL_bool removed; int instance_id; SDL_JoystickGUID guid; diff --git a/src/joystick/dummy/SDL_sysjoystick.c b/src/joystick/dummy/SDL_sysjoystick.c index 1d1c16a12..a046e0e5f 100644 --- a/src/joystick/dummy/SDL_sysjoystick.c +++ b/src/joystick/dummy/SDL_sysjoystick.c @@ -34,7 +34,7 @@ int SDL_SYS_JoystickInit(void) { - return (0); + return 0; } int SDL_SYS_NumJoysticks() @@ -85,21 +85,18 @@ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick) void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { - return; } /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - return; } /* Function to perform any system-specific joystick related cleanup */ void SDL_SYS_JoystickQuit(void) { - return; } SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index ) diff --git a/src/joystick/emscripten/SDL_sysjoystick.c b/src/joystick/emscripten/SDL_sysjoystick.c index 5b8267750..a1e9c1552 100644 --- a/src/joystick/emscripten/SDL_sysjoystick.c +++ b/src/joystick/emscripten/SDL_sysjoystick.c @@ -326,7 +326,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) /* Function to determine is this joystick is attached to the system right now */ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick) { - return !joystick->closed && (joystick->hwdata != NULL); + return joystick->hwdata != NULL; } /* Function to update the state of a joystick - called as a device poll. @@ -378,11 +378,6 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - if (joystick->hwdata) { - ((SDL_joylist_item*)joystick->hwdata)->joystick = NULL; - joystick->hwdata = NULL; - } - joystick->closed = 1; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/haiku/SDL_haikujoystick.cc b/src/joystick/haiku/SDL_haikujoystick.cc index 394804e08..c9b7e114a 100644 --- a/src/joystick/haiku/SDL_haikujoystick.cc +++ b/src/joystick/haiku/SDL_haikujoystick.cc @@ -228,7 +228,6 @@ extern "C" SDL_free(joystick->hwdata->new_hats); SDL_free(joystick->hwdata->new_axes); SDL_free(joystick->hwdata); - joystick->hwdata = NULL; } } diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index dd626f207..56c392583 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -153,7 +153,6 @@ void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { [motionManager stopAccelerometerUpdates]; - joystick->closed = 1; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c index d4e42e4c4..7dd33efd0 100644 --- a/src/joystick/linux/SDL_sysjoystick.c +++ b/src/joystick/linux/SDL_sysjoystick.c @@ -624,7 +624,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) /* Function to determine is this joystick is attached to the system right now */ SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick *joystick) { - return !joystick->closed && (joystick->hwdata->item != NULL); + return joystick->hwdata->item != NULL; } static SDL_INLINE void @@ -841,9 +841,7 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick) SDL_free(joystick->hwdata->balls); SDL_free(joystick->hwdata->fname); SDL_free(joystick->hwdata); - joystick->hwdata = NULL; } - joystick->closed = 1; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/psp/SDL_sysjoystick.c b/src/joystick/psp/SDL_sysjoystick.c index 9eae4e259..41f9358fc 100644 --- a/src/joystick/psp/SDL_sysjoystick.c +++ b/src/joystick/psp/SDL_sysjoystick.c @@ -233,7 +233,6 @@ void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) /* Function to close a joystick after use */ void SDL_SYS_JoystickClose(SDL_Joystick *joystick) { - /* Do nothing. */ } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/windows/SDL_mmjoystick.c b/src/joystick/windows/SDL_mmjoystick.c index 7fd555d99..6c02597a9 100644 --- a/src/joystick/windows/SDL_mmjoystick.c +++ b/src/joystick/windows/SDL_mmjoystick.c @@ -383,9 +383,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { - /* free system specific hardware data */ SDL_free(joystick->hwdata); - joystick->hwdata = NULL; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/src/joystick/windows/SDL_windowsjoystick.c b/src/joystick/windows/SDL_windowsjoystick.c index 3404899fb..5682a223f 100644 --- a/src/joystick/windows/SDL_windowsjoystick.c +++ b/src/joystick/windows/SDL_windowsjoystick.c @@ -460,7 +460,6 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) /* allocate memory for system specific hardware data */ joystick->instance_id = joystickdevice->nInstanceID; - joystick->closed = SDL_FALSE; joystick->hwdata = (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata)); if (joystick->hwdata == NULL) { @@ -480,13 +479,13 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick) { - return !joystick->closed && !joystick->hwdata->removed; + return joystick->hwdata && !joystick->hwdata->removed; } void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { - if (joystick->closed || !joystick->hwdata) { + if (!joystick->hwdata || joystick->hwdata->removed) { return; } @@ -497,8 +496,7 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) } if (joystick->hwdata->removed) { - joystick->closed = SDL_TRUE; - joystick->uncentered = SDL_TRUE; + joystick->force_recentering = SDL_TRUE; } } @@ -512,10 +510,7 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick) SDL_DINPUT_JoystickClose(joystick); } - /* free system specific hardware data */ SDL_free(joystick->hwdata); - - joystick->closed = SDL_TRUE; } /* Function to perform any system-specific joystick related cleanup */ diff --git a/test/testjoystick.c b/test/testjoystick.c index 72f056ccb..adb376e02 100644 --- a/test/testjoystick.c +++ b/test/testjoystick.c @@ -56,6 +56,12 @@ loop(void *arg) while (SDL_PollEvent(&event)) { switch (event.type) { + + case SDL_JOYDEVICEREMOVED: + SDL_Log("Joystick device %d removed.\n", (int) event.jdevice.which); + SDL_Log("Our instance ID is %d\n", (int) SDL_JoystickInstanceID(joystick)); + break; + case SDL_JOYAXISMOTION: SDL_Log("Joystick %d axis %d value: %d\n", event.jaxis.which, From d9474bba87cf1c2d0f9f95ee6e2df6ddd9b8bfde Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 14:29:25 -0400 Subject: [PATCH 118/142] Added a hint to prevent SDL from installing signal handlers. Fixes Bugzilla #2431. --- include/SDL_hints.h | 12 ++++++++++++ src/events/SDL_quit.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index a3508ff0d..2ffeb3b3d 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -546,6 +546,18 @@ extern "C" { */ #define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" +/** + * \brief Tell SDL not to handle SIGINT. + * + * This hint only applies to Unix-like platforms. + * + * The variable can be set to the following values: + * "0" - SDL will install a SIGINT handler, and when it catches the + * signal, conver it into an SDL_QUIT event. + * "1" - SDL will not install a SIGINT handler. + */ +#define SDL_HINT_DISABLE_SIGINT_HANDLER "SDL_DISABLE_SIGINT_HANDLER" + /** * \brief An enumeration of hint priorities */ diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index db7af98fa..c1ece1c00 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -19,6 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "../SDL_internal.h" +#include "SDL_hints.h" /* General quit handling code for SDL */ @@ -30,6 +31,8 @@ #include "SDL_events_c.h" +static SDL_bool disable_signals = SDL_FALSE; + #ifdef HAVE_SIGNAL_H static void SDL_HandleSIG(int sig) @@ -46,6 +49,12 @@ SDL_HandleSIG(int sig) int SDL_QuitInit(void) { + const char *hint = SDL_GetHint(SDL_HINT_DISABLE_SIGINT_HANDLER); + disable_signals = hint && (SDL_atoi(hint) == 1); + if (disable_signals) { + return 0; + } + #ifdef HAVE_SIGACTION struct sigaction action; sigaction(SIGINT, NULL, &action); @@ -80,12 +89,16 @@ SDL_QuitInit(void) #endif /* HAVE_SIGNAL_H */ /* That's it! */ - return (0); + return 0; } void SDL_QuitQuit(void) { + if (disable_signals) { + return; + } + #ifdef HAVE_SIGACTION struct sigaction action; sigaction(SIGINT, NULL, &action); From 77d434ab8919fc1202cb0cfbd91aca7dc32644f3 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 14:36:36 -0400 Subject: [PATCH 119/142] Make the signal handler hint more generic. --- include/SDL_hints.h | 10 +++++----- src/events/SDL_quit.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 2ffeb3b3d..04a75f1a6 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -547,16 +547,16 @@ extern "C" { #define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" /** - * \brief Tell SDL not to handle SIGINT. + * \brief Tell SDL not to catch the SIGINT or SIGTERM signals. * * This hint only applies to Unix-like platforms. * * The variable can be set to the following values: - * "0" - SDL will install a SIGINT handler, and when it catches the - * signal, conver it into an SDL_QUIT event. - * "1" - SDL will not install a SIGINT handler. + * "0" - SDL will install a SIGINT and SIGTERM handler, and when it + * catches a signal, convert it into an SDL_QUIT event. + * "1" - SDL will not install a signal handler at all. */ -#define SDL_HINT_DISABLE_SIGINT_HANDLER "SDL_DISABLE_SIGINT_HANDLER" +#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" /** * \brief An enumeration of hint priorities diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index c1ece1c00..898e33a73 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -49,7 +49,7 @@ SDL_HandleSIG(int sig) int SDL_QuitInit(void) { - const char *hint = SDL_GetHint(SDL_HINT_DISABLE_SIGINT_HANDLER); + const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS); disable_signals = hint && (SDL_atoi(hint) == 1); if (disable_signals) { return 0; From 79ca08bb2507c18f3bcf4004a4d64d702f3f1cdf Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 24 Mar 2015 14:40:31 -0400 Subject: [PATCH 120/142] Patched to compile on C89 compilers. --- src/events/SDL_quit.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/events/SDL_quit.c b/src/events/SDL_quit.c index 898e33a73..c80812202 100644 --- a/src/events/SDL_quit.c +++ b/src/events/SDL_quit.c @@ -46,15 +46,9 @@ SDL_HandleSIG(int sig) #endif /* HAVE_SIGNAL_H */ /* Public functions */ -int -SDL_QuitInit(void) +static int +SDL_QuitInit_Internal(void) { - const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS); - disable_signals = hint && (SDL_atoi(hint) == 1); - if (disable_signals) { - return 0; - } - #ifdef HAVE_SIGACTION struct sigaction action; sigaction(SIGINT, NULL, &action); @@ -92,13 +86,20 @@ SDL_QuitInit(void) return 0; } -void -SDL_QuitQuit(void) +int +SDL_QuitInit(void) { - if (disable_signals) { - return; + const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS); + disable_signals = hint && (SDL_atoi(hint) == 1); + if (!disable_signals) { + return SDL_QuitInit_Internal(); } + return 0; +} +static void +SDL_QuitQuit_Internal(void) +{ #ifdef HAVE_SIGACTION struct sigaction action; sigaction(SIGINT, NULL, &action); @@ -123,6 +124,14 @@ SDL_QuitQuit(void) #endif /* HAVE_SIGNAL_H */ } +void +SDL_QuitQuit(void) +{ + if (!disable_signals) { + SDL_QuitQuit_Internal(); + } +} + /* This function returns 1 if it's okay to close the application window */ int SDL_SendQuit(void) From 9c0de6016064be299b4057fd918d842ea0c3c7fd Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Mar 2015 10:19:10 -0400 Subject: [PATCH 121/142] Keep track of maximum number of events in-flight in the SDL queue at once. --- src/events/SDL_events.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 963b9bd7c..cfbdcf89a 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -75,12 +75,13 @@ static struct SDL_mutex *lock; volatile SDL_bool active; volatile int count; + volatile int max_events_seen; SDL_EventEntry *head; SDL_EventEntry *tail; SDL_EventEntry *free; SDL_SysWMEntry *wmmsg_used; SDL_SysWMEntry *wmmsg_free; -} SDL_EventQ = { NULL, SDL_TRUE }; +} SDL_EventQ = { NULL, SDL_TRUE, 0, 0, NULL, NULL, NULL, NULL, NULL }; /* Public functions */ @@ -88,6 +89,7 @@ static struct void SDL_StopEventLoop(void) { + const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS"); int i; SDL_EventEntry *entry; SDL_SysWMEntry *wmmsg; @@ -98,6 +100,11 @@ SDL_StopEventLoop(void) SDL_EventQ.active = SDL_FALSE; + if (report && SDL_atoi(report)) { + SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n", + SDL_EventQ.max_events_seen); + } + /* Clean out EventQ */ for (entry = SDL_EventQ.head; entry; ) { SDL_EventEntry *next = entry->next; @@ -119,7 +126,9 @@ SDL_StopEventLoop(void) SDL_free(wmmsg); wmmsg = next; } + SDL_EventQ.count = 0; + SDL_EventQ.max_events_seen = 0; SDL_EventQ.head = NULL; SDL_EventQ.tail = NULL; SDL_EventQ.free = NULL; @@ -218,6 +227,10 @@ SDL_AddEvent(SDL_Event * event) } ++SDL_EventQ.count; + if (SDL_EventQ.count > SDL_EventQ.max_events_seen) { + SDL_EventQ.max_events_seen = SDL_EventQ.count; + } + return 1; } From 3dcf5c743fc9fcefc5b08cff5fd7a9f149e9a154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseba=20Garc=C3=ADa=20Etxebarria?= Date: Tue, 24 Mar 2015 20:45:29 +0100 Subject: [PATCH 122/142] * Improve mouse support in Android. These changes require Android API v12 to compile --- .../src/org/libsdl/app/SDLActivity.java | 123 ++++++++++++------ include/SDL_hints.h | 12 ++ src/core/android/SDL_android.c | 17 +++ src/video/android/SDL_androidmouse.c | 85 ++++++++++++ src/video/android/SDL_androidmouse.h | 31 +++++ src/video/android/SDL_androidtouch.c | 32 +++-- 6 files changed, 249 insertions(+), 51 deletions(-) create mode 100644 src/video/android/SDL_androidmouse.c create mode 100644 src/video/android/SDL_androidmouse.h diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index a39d05ef1..71280d1b3 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -401,6 +401,7 @@ public class SDLActivity extends Activity { public static native void onNativeKeyDown(int keycode); public static native void onNativeKeyUp(int keycode); public static native void onNativeKeyboardFocusLost(); + public static native void onNativeMouse(int button, int action, float x, float y); public static native void onNativeTouch(int touchDevId, int pointerFingerId, int action, float x, float y, float p); @@ -1087,8 +1088,8 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, // Dispatch the different events depending on where they come from // Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD // So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD - - if ( (event.getSource() & 0x00000401) != 0 || /* API 12: SOURCE_GAMEPAD */ + + if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 || (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) { @@ -1125,50 +1126,58 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, final int pointerCount = event.getPointerCount(); int action = event.getActionMasked(); int pointerFingerId; + int mouseButton; int i = -1; float x,y,p; - - switch(action) { - case MotionEvent.ACTION_MOVE: - for (i = 0; i < pointerCount; i++) { + + if (event.getSource() == InputDevice.SOURCE_MOUSE && + SDLActivity.nativeGetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH").equals("1")) { + mouseButton = 1; // For Android==12 all mouse buttons are the left button + + SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0)); + } else { + switch(action) { + case MotionEvent.ACTION_MOVE: + for (i = 0; i < pointerCount; i++) { + pointerFingerId = event.getPointerId(i); + x = event.getX(i) / mWidth; + y = event.getY(i) / mHeight; + p = event.getPressure(i); + SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); + } + break; + + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_DOWN: + // Primary pointer up/down, the index is always zero + i = 0; + case MotionEvent.ACTION_POINTER_UP: + case MotionEvent.ACTION_POINTER_DOWN: + // Non primary pointer up/down + if (i == -1) { + i = event.getActionIndex(); + } + pointerFingerId = event.getPointerId(i); x = event.getX(i) / mWidth; y = event.getY(i) / mHeight; p = event.getPressure(i); SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); - } - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_DOWN: - // Primary pointer up/down, the index is always zero - i = 0; - case MotionEvent.ACTION_POINTER_UP: - case MotionEvent.ACTION_POINTER_DOWN: - // Non primary pointer up/down - if (i == -1) { - i = event.getActionIndex(); - } + break; - pointerFingerId = event.getPointerId(i); - x = event.getX(i) / mWidth; - y = event.getY(i) / mHeight; - p = event.getPressure(i); - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p); - break; - - case MotionEvent.ACTION_CANCEL: - for (i = 0; i < pointerCount; i++) { - pointerFingerId = event.getPointerId(i); - x = event.getX(i) / mWidth; - y = event.getY(i) / mHeight; - p = event.getPressure(i); - SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p); - } - break; + case MotionEvent.ACTION_CANCEL: + for (i = 0; i < pointerCount; i++) { + pointerFingerId = event.getPointerId(i); + x = event.getX(i) / mWidth; + y = event.getY(i) / mHeight; + p = event.getPressure(i); + SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p); + } + break; - default: - break; + default: + break; + } } return true; @@ -1497,11 +1506,47 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { } } -class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { +class SDLGenericMotionListener implements View.OnGenericMotionListener { // Generic Motion (mouse hover, joystick...) events go here // We only have joysticks yet @Override public boolean onGenericMotion(View v, MotionEvent event) { - return SDLActivity.handleJoystickMotionEvent(event); + float x, y; + int mouseButton; + int action; + + switch ( event.getSource() ) { + case InputDevice.SOURCE_JOYSTICK: + case InputDevice.SOURCE_GAMEPAD: + case InputDevice.SOURCE_DPAD: + SDLActivity.handleJoystickMotionEvent(event); + return true; + + case InputDevice.SOURCE_MOUSE: + action = event.getActionMasked(); + switch(event.getActionMasked()) { + case MotionEvent.ACTION_SCROLL: + x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); + y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); + SDLActivity.onNativeMouse(0, action, x, y); + return true; + + case MotionEvent.ACTION_HOVER_MOVE: + x = event.getX(0); + y = event.getY(0); + + SDLActivity.onNativeMouse(0, action, x, y); + return true; + + default: + break; + } + + default: + break; + } + + // Event was not managed + return false; } } diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 04a75f1a6..ecc3ba0fd 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -532,6 +532,18 @@ extern "C" { */ #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" + /** + * \brief A variable to control whether mouse and touch events are to be treated together or separately + * + * The variable can be set to the following values: + * "0" - Mouse events will be handled as touch events, and touch will raise fake mouse + * events. This is the behaviour of SDL <= 2.0.3. (default) + * "1" - Mouse events will be handled separately from pure touch events. + * + * The value of this hint is used at runtime, so it can be changed at any time. + */ +#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH" + /** * \brief override the binding element for keyboard inputs for Emscripten builds * diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index b29f7e4ee..8e3d87391 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -32,6 +32,7 @@ #include "../../events/SDL_events_c.h" #include "../../video/android/SDL_androidkeyboard.h" +#include "../../video/android/SDL_androidmouse.h" #include "../../video/android/SDL_androidtouch.h" #include "../../video/android/SDL_androidvideo.h" #include "../../video/android/SDL_androidwindow.h" @@ -293,6 +294,22 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeTouch( Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p); } +/* Mouse */ +JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse( + JNIEnv* env, jclass jcls, + jint button, jint action, jfloat x, jfloat y) +{ + Android_OnMouse(button, action, x, y); +} + +/* Mouse */ +JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse( + JNIEnv* env, jclass jcls, + jint button, jint action, jfloat x, jfloat y) +{ + Android_OnMouse(button, action, x, y); +} + /* Accelerometer */ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel( JNIEnv* env, jclass jcls, diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c new file mode 100644 index 000000000..35bc67555 --- /dev/null +++ b/src/video/android/SDL_androidmouse.c @@ -0,0 +1,85 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_ANDROID + +#include "SDL_androidmouse.h" +#include "SDL_Log.h" + +#include "SDL_events.h" +#include "../../events/SDL_mouse_c.h" + +#include "../../core/android/SDL_android.h" + +#define ACTION_DOWN 0 +#define ACTION_UP 1 +#define ACTION_HOVER_MOVE 7 +#define ACTION_SCROLL 8 +#define BUTTON_PRIMARY 1 +#define BUTTON_SECONDARY 2 +#define BUTTON_TERTIARY 4 + +void Android_OnMouse( int androidButton, int action, float x, float y) { + static Uint8 SDLButton; + + if (!Android_Window) { + return; + } + + switch(action) { + case ACTION_DOWN: + // Determine which button originated the event, and store it for ACTION_UP + SDLButton = SDL_BUTTON_LEFT; + if (androidButton == BUTTON_SECONDARY) { + SDLButton = SDL_BUTTON_RIGHT; + } else if (androidButton == BUTTON_TERTIARY) { + SDLButton = SDL_BUTTON_MIDDLE; + } + SDL_SendMouseMotion(Android_Window, 0, 0, x, y); + SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, SDLButton); + break; + + case ACTION_UP: + // Android won't give us the button that originated the ACTION_DOWN event, so we'll + // assume it's the one we stored + SDL_SendMouseMotion(Android_Window, 0, 0, x, y); + SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, SDLButton); + break; + + case ACTION_HOVER_MOVE: + SDL_SendMouseMotion(Android_Window, 0, 0, x, y); + break; + + case ACTION_SCROLL: + SDL_SendMouseWheel(Android_Window, 0, x, y); + break; + + default: + break; + } +} + +#endif /* SDL_VIDEO_DRIVER_ANDROID */ + +/* vi: set ts=4 sw=4 expandtab: */ + diff --git a/src/video/android/SDL_androidmouse.h b/src/video/android/SDL_androidmouse.h new file mode 100644 index 000000000..ebc6a7a1c --- /dev/null +++ b/src/video/android/SDL_androidmouse.h @@ -0,0 +1,31 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2014 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_androidmouse_h +#define _SDL_androidmouse_h + +#include "SDL_androidvideo.h" + +extern void Android_OnMouse( int button, int action, float x, float y); + +#endif /* _SDL_androidmouse_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 5f33429b5..4a9266e3f 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -69,6 +69,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio SDL_TouchID touchDeviceId = 0; SDL_FingerID fingerId = 0; int window_x, window_y; + char * hint; static SDL_FingerID pointerFingerID = 0; if (!Android_Window) { @@ -81,40 +82,47 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio } fingerId = (SDL_FingerID)pointer_finger_id_in; + hint = SDL_GetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"); switch (action) { case ACTION_DOWN: /* Primary pointer down */ Android_GetWindowCoordinates(x, y, &window_x, &window_y); - /* send moved event */ - SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); - /* send mouse down event */ - SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + /* send moved event */ + SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); + /* send mouse down event */ + SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + } pointerFingerID = fingerId; case ACTION_POINTER_DOWN: /* Non primary pointer down */ SDL_SendTouch(touchDeviceId, fingerId, SDL_TRUE, x, y, p); break; - + case ACTION_MOVE: if (!pointerFingerID) { Android_GetWindowCoordinates(x, y, &window_x, &window_y); - /* send moved event */ - SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); + if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + /* send moved event */ + SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); + } } SDL_SendTouchMotion(touchDeviceId, fingerId, x, y, p); break; - + case ACTION_UP: /* Primary pointer up */ - /* send mouse up */ - pointerFingerID = (SDL_FingerID) 0; - SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + /* send mouse up */ + pointerFingerID = (SDL_FingerID) 0; + SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + } case ACTION_POINTER_UP: /* Non primary pointer up */ SDL_SendTouch(touchDeviceId, fingerId, SDL_FALSE, x, y, p); break; - + default: break; } From e997a4144dba669ddc8786da6cff2652c9785e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseba=20Garc=C3=ADa=20Etxebarria?= Date: Tue, 24 Mar 2015 21:02:28 +0100 Subject: [PATCH 123/142] * More Android patch work --- android-project/src/org/libsdl/app/SDLActivity.java | 2 +- src/core/android/SDL_android.c | 8 -------- src/video/android/SDL_androidmouse.c | 4 ++-- src/video/android/SDL_androidtouch.c | 9 ++++----- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 71280d1b3..993c98e4c 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -950,7 +950,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); if(Build.VERSION.SDK_INT >= 12) { - setOnGenericMotionListener(new SDLGenericMotionListener_API12()); + setOnGenericMotionListener(new SDLGenericMotionListener()); } // Some arbitrary defaults to avoid a potential division by zero diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index 8e3d87391..f7238a919 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -302,14 +302,6 @@ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse( Android_OnMouse(button, action, x, y); } -/* Mouse */ -JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeMouse( - JNIEnv* env, jclass jcls, - jint button, jint action, jfloat x, jfloat y) -{ - Android_OnMouse(button, action, x, y); -} - /* Accelerometer */ JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeAccel( JNIEnv* env, jclass jcls, diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c index 35bc67555..12263fd12 100644 --- a/src/video/android/SDL_androidmouse.c +++ b/src/video/android/SDL_androidmouse.c @@ -24,7 +24,7 @@ #if SDL_VIDEO_DRIVER_ANDROID #include "SDL_androidmouse.h" -#include "SDL_Log.h" +#include "SDL_log.h" #include "SDL_events.h" #include "../../events/SDL_mouse_c.h" @@ -71,7 +71,7 @@ void Android_OnMouse( int androidButton, int action, float x, float y) { break; case ACTION_SCROLL: - SDL_SendMouseWheel(Android_Window, 0, x, y); + SDL_SendMouseWheel(Android_Window, 0, x, y, SDL_MOUSEWHEEL_NORMAL); break; default: diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 4a9266e3f..1ad78dd1b 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -24,13 +24,12 @@ #include +#include "SDL_hints.h" #include "SDL_events.h" +#include "SDL_log.h" +#include "SDL_androidtouch.h" #include "../../events/SDL_mouse_c.h" #include "../../events/SDL_touch_c.h" -#include "SDL_log.h" - -#include "SDL_androidtouch.h" - #include "../../core/android/SDL_android.h" #define ACTION_DOWN 0 @@ -69,7 +68,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio SDL_TouchID touchDeviceId = 0; SDL_FingerID fingerId = 0; int window_x, window_y; - char * hint; + const char * hint; static SDL_FingerID pointerFingerID = 0; if (!Android_Window) { From b335d1a18284d1454d480eb1238c5bd77e7c97a4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Mar 2015 10:48:59 -0400 Subject: [PATCH 124/142] Removed unnecessary SDL_log.h include. --- src/video/android/SDL_androidmouse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video/android/SDL_androidmouse.c b/src/video/android/SDL_androidmouse.c index 12263fd12..af828af1f 100644 --- a/src/video/android/SDL_androidmouse.c +++ b/src/video/android/SDL_androidmouse.c @@ -24,7 +24,6 @@ #if SDL_VIDEO_DRIVER_ANDROID #include "SDL_androidmouse.h" -#include "SDL_log.h" #include "SDL_events.h" #include "../../events/SDL_mouse_c.h" From d9f45dce57f9ee2fdc1c7efc1b9d3bfd9e0ecde6 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Mar 2015 10:59:10 -0400 Subject: [PATCH 125/142] Add a hint watch callback for SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH. --- src/video/android/SDL_androidtouch.c | 31 +++++++++++++++++++++------- src/video/android/SDL_androidtouch.h | 1 + src/video/android/SDL_androidvideo.c | 1 + 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 1ad78dd1b..27b78598f 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -50,11 +50,24 @@ static void Android_GetWindowCoordinates(float x, float y, *window_y = (int)(y * window_h); } +static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE; + +static void +SeparateEventsHintWatcher(void *userdata, const char *name, + const char *oldValue, const char *newValue) +{ + separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0)); +} + void Android_InitTouch(void) { int i; int* ids; - int number = Android_JNI_GetTouchDeviceIds(&ids); + const int number = Android_JNI_GetTouchDeviceIds(&ids); + + SDL_AddHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, + SeparateEventsHintWatcher, NULL); + if (0 < number) { for (i = 0; i < number; ++i) { SDL_AddTouch((SDL_TouchID) ids[i], ""); /* no error handling */ @@ -63,12 +76,18 @@ void Android_InitTouch(void) } } +void Android_QuitTouch(void) +{ + SDL_DelHintCallback(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, + SeparateEventsHintWatcher, NULL); + separate_mouse_and_touch = SDL_FALSE; +} + void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p) { SDL_TouchID touchDeviceId = 0; SDL_FingerID fingerId = 0; int window_x, window_y; - const char * hint; static SDL_FingerID pointerFingerID = 0; if (!Android_Window) { @@ -81,12 +100,11 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio } fingerId = (SDL_FingerID)pointer_finger_id_in; - hint = SDL_GetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH"); switch (action) { case ACTION_DOWN: /* Primary pointer down */ Android_GetWindowCoordinates(x, y, &window_x, &window_y); - if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + if (!separate_mouse_and_touch) { /* send moved event */ SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); /* send mouse down event */ @@ -101,8 +119,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio case ACTION_MOVE: if (!pointerFingerID) { Android_GetWindowCoordinates(x, y, &window_x, &window_y); - - if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + if (!separate_mouse_and_touch) { /* send moved event */ SDL_SendMouseMotion(Android_Window, SDL_TOUCH_MOUSEID, 0, window_x, window_y); } @@ -112,7 +129,7 @@ void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int actio case ACTION_UP: /* Primary pointer up */ - if ((!hint) || (hint && SDL_strcmp(hint, "1") != 0)) { + if (!separate_mouse_and_touch) { /* send mouse up */ pointerFingerID = (SDL_FingerID) 0; SDL_SendMouseButton(Android_Window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); diff --git a/src/video/android/SDL_androidtouch.h b/src/video/android/SDL_androidtouch.h index 81a0cb50e..904e0d2a6 100644 --- a/src/video/android/SDL_androidtouch.h +++ b/src/video/android/SDL_androidtouch.h @@ -23,6 +23,7 @@ #include "SDL_androidvideo.h" extern void Android_InitTouch(void); +extern void Android_QuitTouch(void); extern void Android_OnTouch( int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p); /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 5e034615b..66384b261 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -188,6 +188,7 @@ Android_VideoInit(_THIS) void Android_VideoQuit(_THIS) { + Android_QuitTouch(); } /* This function gets called before VideoInit() */ From adc62e29fbd4d029741a4f3b02d5cb4ac20bac73 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 25 Mar 2015 11:18:54 -0400 Subject: [PATCH 126/142] Make the Dynamic API master switch more clear. --- src/dynapi/SDL_dynapi.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index df8760019..5f4ea8d28 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -49,7 +49,10 @@ #define SDL_DYNAMIC_API 0 #elif defined(__clang_analyzer__) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ -#else /* everyone else. */ +#endif + +/* everyone else. This is where we turn on the API if nothing forced it off. */ +#ifndef SDL_DYNAMIC_API #define SDL_DYNAMIC_API 1 #endif From 8f0ea4bcf789367d7d077e6c6db9479620e9626a Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Wed, 25 Mar 2015 22:47:22 +0100 Subject: [PATCH 127/142] Android: Removed outdated comment from source. --- android-project/src/org/libsdl/app/SDLActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 993c98e4c..42aef32a9 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -1508,7 +1508,6 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { class SDLGenericMotionListener implements View.OnGenericMotionListener { // Generic Motion (mouse hover, joystick...) events go here - // We only have joysticks yet @Override public boolean onGenericMotion(View v, MotionEvent event) { float x, y; From bc4a24e207fb2b06344223f8a1abd451324a6591 Mon Sep 17 00:00:00 2001 From: Philipp Wiesemann Date: Wed, 25 Mar 2015 22:48:57 +0100 Subject: [PATCH 128/142] Removed not needed call to SDL_free(). --- src/video/dummy/SDL_nullvideo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index 28147bd18..79f831eee 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -82,7 +82,6 @@ DUMMY_CreateDevice(int devindex) device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); if (!device) { SDL_OutOfMemory(); - SDL_free(device); return (0); } From 1163b6da1ca282090af7c480d97421bf38574b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseba=20Garc=C3=ADa=20Etxebarria?= Date: Fri, 27 Mar 2015 18:09:51 -0400 Subject: [PATCH 129/142] Renamed SDLGenericMotionListener back to SDLGenericMotionListener_API12 --- android-project/src/org/libsdl/app/SDLActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 42aef32a9..70d1acc66 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -950,7 +950,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE); if(Build.VERSION.SDK_INT >= 12) { - setOnGenericMotionListener(new SDLGenericMotionListener()); + setOnGenericMotionListener(new SDLGenericMotionListener_API12()); } // Some arbitrary defaults to avoid a potential division by zero @@ -1506,7 +1506,7 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { } } -class SDLGenericMotionListener implements View.OnGenericMotionListener { +class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { // Generic Motion (mouse hover, joystick...) events go here @Override public boolean onGenericMotion(View v, MotionEvent event) { From d6ffb03a601a2f590f2167a74172cb1f80dcd5a4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 28 Mar 2015 00:48:03 -0400 Subject: [PATCH 130/142] Minor input grab clarifications. Clarify that grabbing the mouse only works with one window at a time; this was always true at the system level, though SDL could previously get confused by multiple simultaneous grabs, so now we explicitly break any existing grab before starting a new one and document it as such. Also track the window that is currently grabbed, and provide an API to query for that window. This makes it easy to automate mouse ungrabbing at breakpoints with gdb7's scripting, since the scripts can now know which window to ungrab. In 2.1, we should probably change this API to SDL_GrabInput(win) and SDL_UngrabInput(void), or something. --HG-- extra : rebase_source : c99570ccdaeb40c13fb0b00236fc77669705a189 extra : amend_source : 40993aa08816ef218bc10aa5d3a2aaa84f284240 --- include/SDL_video.h | 12 ++++++++++++ src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 23 ++++++++++++++++++++++- 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/SDL_video.h b/include/SDL_video.h index 782fcb0fb..fe1386889 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -722,6 +722,9 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window * window, * \param window The window for which the input grab mode should be set. * \param grabbed This is SDL_TRUE to grab input, and SDL_FALSE to release input. * + * If the caller enables a grab while another window is currently grabbed, + * the other window loses its grab in favor of the caller's window. + * * \sa SDL_GetWindowGrab() */ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, @@ -736,6 +739,15 @@ extern DECLSPEC void SDLCALL SDL_SetWindowGrab(SDL_Window * window, */ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowGrab(SDL_Window * window); +/** + * \brief Get the window that currently has an input grab enabled. + * + * \return This returns the window if input is grabbed, and NULL otherwise. + * + * \sa SDL_SetWindowGrab() + */ +extern DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void); + /** * \brief Set the brightness (gamma correction) for a window. * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 8bcde6312..dcc6d4677 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -591,3 +591,4 @@ #define SDL_QueueAudio SDL_QueueAudio_REAL #define SDL_GetQueuedAudioSize SDL_GetQueuedAudioSize_REAL #define SDL_ClearQueuedAudio SDL_ClearQueuedAudio_REAL +#define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index c41cdc9f0..6408e3f89 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -623,3 +623,4 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return) SDL_DYNAPI_PROC(int,SDL_QueueAudio,(SDL_AudioDeviceID a, const void *b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(Uint32,SDL_GetQueuedAudioSize,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(void,SDL_ClearQueuedAudio,(SDL_AudioDeviceID a),(a),) +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 6966f2bd3..9b2f7d170 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -274,6 +274,7 @@ struct SDL_VideoDevice int num_displays; SDL_VideoDisplay *displays; SDL_Window *windows; + SDL_Window *grabbed_window; Uint8 window_magic; Uint32 next_object_id; char * clipboard_text; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index b93c11e76..c8cb2fac8 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -2116,6 +2116,7 @@ void SDL_UpdateWindowGrab(SDL_Window * window) { if (_this->SetWindowGrab) { + SDL_Window *grabbed_window; SDL_bool grabbed; if ((SDL_GetMouse()->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { @@ -2123,6 +2124,19 @@ SDL_UpdateWindowGrab(SDL_Window * window) } else { grabbed = SDL_FALSE; } + + grabbed_window = _this->grabbed_window; + if (grabbed) { + if (grabbed_window && (grabbed_window != window)) { + /* stealing a grab from another window! */ + grabbed_window->flags &= ~SDL_WINDOW_INPUT_GRABBED; + _this->SetWindowGrab(_this, grabbed_window, SDL_FALSE); + } + _this->grabbed_window = window; + } else if (grabbed_window == window) { + _this->grabbed_window = NULL; /* ungrabbing. */ + } + _this->SetWindowGrab(_this, window, grabbed); } } @@ -2147,8 +2161,15 @@ SDL_bool SDL_GetWindowGrab(SDL_Window * window) { CHECK_WINDOW_MAGIC(window, SDL_FALSE); + SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0)); + return window == _this->grabbed_window; +} - return ((window->flags & SDL_WINDOW_INPUT_GRABBED) != 0); +SDL_Window * +SDL_GetGrabbedWindow(void) +{ + SDL_assert(!_this->grabbed_window || ((_this->grabbed_window->flags & SDL_WINDOW_INPUT_GRABBED) != 0)); + return _this->grabbed_window; } void From ba8fa2b18aa37f778ac698d0f9ff198ccc51802a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 30 Mar 2015 11:31:53 -0700 Subject: [PATCH 131/142] Fixed relative mouse motion moving farther and farther off screen. --- src/events/SDL_mouse.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 0ce443a3c..326bbbadc 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -293,9 +293,14 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ event.motion.yrel = yrel; posted = (SDL_PushEvent(&event) > 0); } - /* Use unclamped values if we're getting events outside the window */ - mouse->last_x = x; - mouse->last_y = y; + if (relative) { + mouse->last_x = mouse->x; + mouse->last_y = mouse->y; + } else { + /* Use unclamped values if we're getting events outside the window */ + mouse->last_x = x; + mouse->last_y = y; + } return posted; } From bedac6b53ad6a505eb1d2e49992afef2cde66a8f Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Apr 2015 12:14:56 -0400 Subject: [PATCH 132/142] Android: more separate-mouse-and-touch work. This avoids a hint lookup for each mouse event we get by setting a static Java variable from native code during our hint watcher callback. Also attempts to do the right thing with mouse buttons if you happen to be on an API14 (Ice Cream Sandwich, Android 4.0) or later device. We still target API12 (Honeycomb MR1, Android 3.1) for SDL 2.0.4 though. This isn't tested, so I'm pushing to see what the Android buildbot says. Stand back, I'm a professional! --HG-- extra : amend_source : 7748c650f37edd47c721e4e7e96cf5995f5ac459 --- .../src/org/libsdl/app/SDLActivity.java | 19 +++++++++++++++---- src/video/android/SDL_androidtouch.c | 3 +++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 70d1acc66..2a228d63e 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -41,6 +41,10 @@ public class SDLActivity extends Activity { /** If shared libraries (e.g. SDL or the native application) could not be loaded. */ public static boolean mBrokenLibraries; + // If we want to separate mouse and touch events. + // This is only toggled in native code when a hint is set! + public static boolean mSeparateMouseAndTouch; + // Main components protected static SDLActivity mSingleton; protected static SDLSurface mSurface; @@ -1130,11 +1134,18 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, int i = -1; float x,y,p; - if (event.getSource() == InputDevice.SOURCE_MOUSE && - SDLActivity.nativeGetHint("SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH").equals("1")) { + // !!! FIXME: dump this SDK check after 2.0.4 ships and require API14. + if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) { + if (Build.VERSION.SDK_INT < 14) { mouseButton = 1; // For Android==12 all mouse buttons are the left button - - SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0)); + } else { + try { + mouseButton = event.getClass().getMethod("getButtonState").invoke(event); + } catch(Exception e) { + mouseButton = 1; // oh well. + } + } + SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0)); } else { switch(action) { case MotionEvent.ACTION_MOVE: diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 27b78598f..4a5612acd 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -57,6 +57,9 @@ SeparateEventsHintWatcher(void *userdata, const char *name, const char *oldValue, const char *newValue) { separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0)); + JNIEnv *env = Android_JNI_GetEnv(); + jfieldID fid = (*env)->GetStaticFieldID(env, mActivityClass, "mSeparateMouseAndTouch", "Z"); + (*env)->SetStaticBooleanField(env, mActivityClass, fid, separate_mouse_and_touch ? JNI_TRUE : JNI_FALSE); } void Android_InitTouch(void) From 7ccd2d26a9d1607e76f589840881c96341de0f17 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Wed, 1 Apr 2015 14:45:09 -0400 Subject: [PATCH 133/142] Patched to compile on Android (I hope). --- src/core/android/SDL_android.c | 5 +++++ src/core/android/SDL_android.h | 1 + src/video/android/SDL_androidtouch.c | 4 +++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index f7238a919..e7f90bacd 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -1610,6 +1610,11 @@ const char * SDL_AndroidGetExternalStoragePath() return s_AndroidExternalFilesPath; } +jclass Android_JNI_GetActivityClass(void) +{ + return mActivityClass; +} + #endif /* __ANDROID__ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index 051958a49..d749bf101 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -78,6 +78,7 @@ int Android_JNI_GetTouchDeviceIds(int **ids); #include JNIEnv *Android_JNI_GetEnv(void); int Android_JNI_SetupThread(void); +jclass Android_JNI_GetActivityClass(void); /* Generic messages */ int Android_JNI_SendMessage(int command, int param); diff --git a/src/video/android/SDL_androidtouch.c b/src/video/android/SDL_androidtouch.c index 4a5612acd..3b406c96e 100644 --- a/src/video/android/SDL_androidtouch.c +++ b/src/video/android/SDL_androidtouch.c @@ -56,9 +56,11 @@ static void SeparateEventsHintWatcher(void *userdata, const char *name, const char *oldValue, const char *newValue) { - separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0)); + jclass mActivityClass = Android_JNI_GetActivityClass(); JNIEnv *env = Android_JNI_GetEnv(); jfieldID fid = (*env)->GetStaticFieldID(env, mActivityClass, "mSeparateMouseAndTouch", "Z"); + + separate_mouse_and_touch = (newValue && (SDL_strcmp(newValue, "1") == 0)); (*env)->SetStaticBooleanField(env, mActivityClass, fid, separate_mouse_and_touch ? JNI_TRUE : JNI_FALSE); } From 9e9a67f64eb5f2b0be33058c3157e0792995f808 Mon Sep 17 00:00:00 2001 From: Edward Rudd Date: Wed, 1 Apr 2015 16:11:37 -0400 Subject: [PATCH 134/142] handle the case where the ibus address can't be found. (prevents nasty crash) --- src/core/linux/SDL_ibus.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 1a0729f26..6b84be2e9 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -462,6 +462,9 @@ SDL_IBus_Init(void) ibus_addr_file = SDL_strdup(addr_file); addr = IBus_ReadAddressFromFile(addr_file); + if (!addr) { + return SDL_FALSE; + } if (inotify_fd < 0) { inotify_fd = inotify_init(); From 9549f560bad12680dd954fb8712e0049409711d3 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 1 Apr 2015 18:22:42 -0700 Subject: [PATCH 135/142] Added a game controller entry for the NVIDIA Controller --- src/joystick/SDL_gamecontrollerdb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index e864834da..4906262a1 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -64,6 +64,7 @@ static const char *s_ControllerMappings [] = "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", + "03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,", "050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", From ddad0a13155467d1ae42fd8a1f1dbf1ce39cb6a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joseba=20Garc=C3=ADa=20Etxebarria?= Date: Thu, 2 Apr 2015 00:55:45 +0200 Subject: [PATCH 136/142] Cast the result of calling getButtonState to an Integer --- android-project/src/org/libsdl/app/SDLActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 2a228d63e..bd047d638 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -1140,7 +1140,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, mouseButton = 1; // For Android==12 all mouse buttons are the left button } else { try { - mouseButton = event.getClass().getMethod("getButtonState").invoke(event); + mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event); } catch(Exception e) { mouseButton = 1; // oh well. } From d18f975b1b21cf282eb50fcf27ac570c1631163e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 1 Apr 2015 19:18:56 -0700 Subject: [PATCH 137/142] Fixed detecting the NVIDIA controller which shows up as both a mouse and a game controller --- src/core/linux/SDL_udev.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/core/linux/SDL_udev.c b/src/core/linux/SDL_udev.c index d00fd82a7..b1310bc3f 100644 --- a/src/core/linux/SDL_udev.c +++ b/src/core/linux/SDL_udev.c @@ -350,17 +350,19 @@ guess_device_class(struct udev_device *dev) devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ } else if (test_bit(BTN_TOUCH, bitmask_key)) { ; /* ID_INPUT_TOUCHSCREEN */ - } else if (test_bit(BTN_TRIGGER, bitmask_key) || - test_bit(BTN_A, bitmask_key) || - test_bit(BTN_1, bitmask_key) || - test_bit(ABS_RX, bitmask_abs) || - test_bit(ABS_RY, bitmask_abs) || - test_bit(ABS_RZ, bitmask_abs) || - test_bit(ABS_THROTTLE, bitmask_abs) || - test_bit(ABS_RUDDER, bitmask_abs) || - test_bit(ABS_WHEEL, bitmask_abs) || - test_bit(ABS_GAS, bitmask_abs) || - test_bit(ABS_BRAKE, bitmask_abs)) { + } + + if (test_bit(BTN_TRIGGER, bitmask_key) || + test_bit(BTN_A, bitmask_key) || + test_bit(BTN_1, bitmask_key) || + test_bit(ABS_RX, bitmask_abs) || + test_bit(ABS_RY, bitmask_abs) || + test_bit(ABS_RZ, bitmask_abs) || + test_bit(ABS_THROTTLE, bitmask_abs) || + test_bit(ABS_RUDDER, bitmask_abs) || + test_bit(ABS_WHEEL, bitmask_abs) || + test_bit(ABS_GAS, bitmask_abs) || + test_bit(ABS_BRAKE, bitmask_abs)) { devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */ } } From dd2a173a330b27b00b106ebe0d65d64bb929f41d Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 5 Apr 2015 15:52:37 -0400 Subject: [PATCH 138/142] Patched to compile on Android when audio subsystem is disabled (thanks, Jonas!) Fixes Bugzilla #2797. --- src/video/android/SDL_androidevents.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/video/android/SDL_androidevents.c b/src/video/android/SDL_androidevents.c index 2662d1b3d..ef7d55648 100644 --- a/src/video/android/SDL_androidevents.c +++ b/src/video/android/SDL_androidevents.c @@ -32,8 +32,14 @@ void android_egl_context_backup(); void android_egl_context_restore(); + +#if SDL_AUDIO_DRIVER_ANDROID void AndroidAUD_ResumeDevices(void); void AndroidAUD_PauseDevices(void); +#else +static void AndroidAUD_ResumeDevices(void) {} +static void AndroidAUD_PauseDevices(void) {} +#endif void android_egl_context_restore() From f7e517a061e25c323ada0b34ae0f9a8232c083a2 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 5 Apr 2015 18:44:24 -0400 Subject: [PATCH 139/142] Add some SDL_SetError() calls to the dollar gesture code (thanks, Martin!). Fixes Bugzilla #2673. --- src/events/SDL_gesture.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events/SDL_gesture.c b/src/events/SDL_gesture.c index 46a554635..28b85add7 100644 --- a/src/events/SDL_gesture.c +++ b/src/events/SDL_gesture.c @@ -184,7 +184,7 @@ static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch, SDL_FloatPoint* path) int index = -1; int i = 0; if (inTouch == NULL) { - if (SDL_numGestureTouches == 0) return -1; + if (SDL_numGestureTouches == 0) return SDL_SetError("no gesture touch devices registered"); for (i = 0; i < SDL_numGestureTouches; i++) { inTouch = &SDL_gestureTouch[i]; index = SDL_AddDollarGesture_one(inTouch, path); @@ -206,7 +206,7 @@ int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) for (i = 0; i < SDL_numGestureTouches; i++) if (SDL_gestureTouch[i].id == touchId) touch = &SDL_gestureTouch[i]; - if (touch == NULL) return -1; + if (touch == NULL) return SDL_SetError("given touch id not found"); } while (1) { From a5fff20ab1bd03d85a4cc1b076a8cb34743c1ee8 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 5 Apr 2015 18:59:52 -0400 Subject: [PATCH 140/142] Make loading/saving dollar gesture templates endian clean (thanks, Martin!). Fixes Bugzilla #2674. --- src/events/SDL_gesture.c | 51 ++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/events/SDL_gesture.c b/src/events/SDL_gesture.c index 28b85add7..746d11630 100644 --- a/src/events/SDL_gesture.c +++ b/src/events/SDL_gesture.c @@ -24,6 +24,7 @@ /* General mouse handling code for SDL */ #include "SDL_events.h" +#include "SDL_endian.h" #include "SDL_events_c.h" #include "SDL_gesture_c.h" @@ -114,14 +115,34 @@ static unsigned long SDL_HashDollar(SDL_FloatPoint* points) static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops *dst) { - if (dst == NULL) return 0; + if (dst == NULL) { + return 0; + } /* No Longer storing the Hash, rehash on load */ /* if (SDL_RWops.write(dst, &(templ->hash), sizeof(templ->hash), 1) != 1) return 0; */ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN if (SDL_RWwrite(dst, templ->path, - sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) + sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) { return 0; + } +#else + { + SDL_DollarTemplate copy = *templ; + SDL_FloatPoint *p = copy.path; + int i; + for (i = 0; i < DOLLARNPOINTS; i++, p++) { + p->x = SDL_SwapFloatLE(p->x); + p->y = SDL_SwapFloatLE(p->y); + } + + if (SDL_RWwrite(dst, copy.path, + sizeof(copy.path[0]),DOLLARNPOINTS) != DOLLARNPOINTS) { + return 0; + } + } +#endif return 1; } @@ -203,17 +224,33 @@ int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src) SDL_GestureTouch *touch = NULL; if (src == NULL) return 0; if (touchId >= 0) { - for (i = 0; i < SDL_numGestureTouches; i++) - if (SDL_gestureTouch[i].id == touchId) + for (i = 0; i < SDL_numGestureTouches; i++) { + if (SDL_gestureTouch[i].id == touchId) { touch = &SDL_gestureTouch[i]; - if (touch == NULL) return SDL_SetError("given touch id not found"); + } + } + if (touch == NULL) { + return SDL_SetError("given touch id not found"); + } } while (1) { SDL_DollarTemplate templ; - if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < - DOLLARNPOINTS) break; + if (SDL_RWread(src,templ.path,sizeof(templ.path[0]),DOLLARNPOINTS) < DOLLARNPOINTS) { + if (loaded == 0) { + return SDL_SetError("could not read any dollar gesture from rwops"); + } + break; + } + +#if SDL_BYTEORDER != SDL_LIL_ENDIAN + for (i = 0; i < DOLLARNPOINTS; i++) { + SDL_FloatPoint *p = &templ.path[i]; + p->x = SDL_SwapFloatLE(p->x); + p->y = SDL_SwapFloatLE(p->y); + } +#endif if (touchId >= 0) { /* printf("Adding loaded gesture to 1 touch\n"); */ From 51fdbabb56a28c66a7ee0802fb8b4d89fc00939e Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Apr 2015 00:10:54 -0400 Subject: [PATCH 141/142] This function can be static. --- src/video/x11/SDL_x11opengl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index df6008ccd..a19d23d40 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -392,7 +392,7 @@ X11_GL_InitExtensions(_THIS) /* glXChooseVisual and glXChooseFBConfig have some small differences in * the attribute encoding, it can be chosen with the for_FBConfig parameter. */ -int +static int X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int size, Bool for_FBConfig) { int i = 0; From a47b4d648c77e2d4409c807f3cf5c12a09012728 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Apr 2015 00:11:58 -0400 Subject: [PATCH 142/142] X11: Always specify "True" if setting GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB. Fixes Bugzilla #2897. --- src/video/x11/SDL_x11opengl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/video/x11/SDL_x11opengl.c b/src/video/x11/SDL_x11opengl.c index a19d23d40..7bc3256bd 100644 --- a/src/video/x11/SDL_x11opengl.c +++ b/src/video/x11/SDL_x11opengl.c @@ -474,9 +474,7 @@ X11_GL_GetAttributes(_THIS, Display * display, int screen, int * attribs, int si if (_this->gl_config.framebuffer_srgb_capable) { attribs[i++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB; - if( for_FBConfig ) { - attribs[i++] = True; - } + attribs[i++] = True; /* always needed, for_FBConfig or not! */ } if (_this->gl_config.accelerated >= 0 &&