Added an API to iterate over game controller mappings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h
index 96d64e0..56051a8 100644
--- a/include/SDL_gamecontroller.h
+++ b/include/SDL_gamecontroller.h
@@ -136,6 +136,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
*
* \return the mapping string. Must be freed with SDL_free(). Returns NULL if no mapping is available
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 3b02257..2e20661 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 b225d2a..d6a2ea2 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 f8c5ad7..3d9d967 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 34785d5..bd63565 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;