From dd5d85a4e7bd571b38178d42427a78a962c310a1 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 29 Nov 2016 06:36:57 -0800 Subject: [PATCH] Added an API to iterate over game controller mappings --- include/SDL_gamecontroller.h | 14 +++++++++ src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ src/joystick/SDL_gamecontroller.c | 52 +++++++++++++++++++++++++++++++ test/testgamecontroller.c | 11 +++++++ 5 files changed, 81 insertions(+) diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index 96d64e06e..56051a831 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -135,6 +135,20 @@ extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, */ extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping(const char* mappingString); +/** + * Get the number of mappings installed + * + * \return the number of mappings + */ +extern DECLSPEC int SDLCALL SDL_GameControllerNumMappings(); + +/** + * Get the mapping at a particular index. + * + * \return the mapping string. Must be freed with SDL_free(). Returns NULL if the index is out of range. + */ +extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForIndex(int mapping_index); + /** * Get a mapping string for a GUID * diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 3b02257f4..2e206614f 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -622,3 +622,5 @@ #define SDL_GameControllerGetProduct SDL_GameControllerGetProduct_REAL #define SDL_GameControllerGetProductVersion SDL_GameControllerGetProductVersion_REAL #define SDL_HasNEON SDL_HasNEON_REAL +#define SDL_GameControllerNumMappings SDL_GameControllerNumMappings_REAL +#define SDL_GameControllerMappingForIndex SDL_GameControllerMappingForIndex_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index b225d2afd..d6a2ea207 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -654,3 +654,5 @@ SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetVendor,(SDL_GameController *a),(a),r SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetProduct,(SDL_GameController *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GameControllerGetProductVersion,(SDL_GameController *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_HasNEON,(void),(),return) +SDL_DYNAPI_PROC(int,SDL_GameControllerNumMappings,(void),(),return) +SDL_DYNAPI_PROC(char*,SDL_GameControllerMappingForIndex,(int a),(a),return) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index f8c5ad789..3d9d967a2 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -96,6 +96,7 @@ typedef struct _ControllerMapping_t struct _ControllerMapping_t *next; } ControllerMapping_t; +static SDL_JoystickGUID s_zeroGUID; static ControllerMapping_t *s_pSupportedControllers = NULL; static ControllerMapping_t *s_pXInputMapping = NULL; static ControllerMapping_t *s_pEmscriptenMapping = NULL; @@ -872,6 +873,57 @@ SDL_GameControllerAddMapping(const char *mappingString) return SDL_PrivateGameControllerAddMapping(mappingString, SDL_CONTROLLER_MAPPING_PRIORITY_API); } +/** + * Get the number of mappings installed + */ +int +SDL_GameControllerNumMappings() +{ + int num_mappings = 0; + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + ++num_mappings; + } + return num_mappings; +} + +/** + * Get the mapping at a particular index. + */ +char * +SDL_GameControllerMappingForIndex(int mapping_index) +{ + ControllerMapping_t *mapping; + + for (mapping = s_pSupportedControllers; mapping; mapping = mapping->next) { + if (SDL_memcmp(&mapping->guid, &s_zeroGUID, sizeof(mapping->guid)) == 0) { + continue; + } + if (mapping_index == 0) { + char *pMappingString; + char pchGUID[33]; + size_t needed; + + SDL_JoystickGetGUIDString(mapping->guid, pchGUID, sizeof(pchGUID)); + /* allocate enough memory for GUID + ',' + name + ',' + mapping + \0 */ + needed = SDL_strlen(pchGUID) + 1 + SDL_strlen(mapping->name) + 1 + SDL_strlen(mapping->mapping) + 1; + pMappingString = SDL_malloc(needed); + if (!pMappingString) { + SDL_OutOfMemory(); + return NULL; + } + SDL_snprintf(pMappingString, needed, "%s,%s,%s", pchGUID, mapping->name, mapping->mapping); + return pMappingString; + } + --mapping_index; + } + return NULL; +} + /* * Get the mapping string for this GUID */ diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 34785d5f9..bd63565a3 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -259,6 +259,17 @@ main(int argc, char *argv[]) SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt"); + /* Print information about the mappings */ + SDL_Log("Supported mappings:\n"); + for (i = 0; i < SDL_GameControllerNumMappings(); ++i) { + char *mapping = SDL_GameControllerMappingForIndex(i); + if (mapping) { + SDL_Log("\t%s\n", mapping); + SDL_free(mapping); + } + } + SDL_Log("\n"); + /* Print information about the controller */ for (i = 0; i < SDL_NumJoysticks(); ++i) { const char *name;