Simple Directmedia Layer
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 254 lines 7.7 kB view raw
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#include "SDL_joystick_c.h" 24#include "SDL_steam_virtual_gamepad.h" 25 26#ifdef SDL_PLATFORM_WIN32 27#include "../core/windows/SDL_windows.h" 28#else 29#include <sys/types.h> 30#include <sys/stat.h> 31#endif 32 33#define SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE "SteamVirtualGamepadInfo" 34 35static char *SDL_steam_virtual_gamepad_info_file SDL_GUARDED_BY(SDL_joystick_lock) = NULL; 36static Uint64 SDL_steam_virtual_gamepad_info_file_mtime SDL_GUARDED_BY(SDL_joystick_lock) = 0; 37static Uint64 SDL_steam_virtual_gamepad_info_check_time SDL_GUARDED_BY(SDL_joystick_lock) = 0; 38static SDL_SteamVirtualGamepadInfo **SDL_steam_virtual_gamepad_info SDL_GUARDED_BY(SDL_joystick_lock) = NULL; 39static int SDL_steam_virtual_gamepad_info_count SDL_GUARDED_BY(SDL_joystick_lock) = 0; 40 41 42static Uint64 GetFileModificationTime(const char *file) 43{ 44 Uint64 modification_time = 0; 45 46#ifdef SDL_PLATFORM_WIN32 47 WCHAR *wFile = WIN_UTF8ToStringW(file); 48 if (wFile) { 49 HANDLE hFile = CreateFileW(wFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 50 if (hFile != INVALID_HANDLE_VALUE) { 51 FILETIME last_write_time; 52 if (GetFileTime(hFile, NULL, NULL, &last_write_time)) { 53 modification_time = last_write_time.dwHighDateTime; 54 modification_time <<= 32; 55 modification_time |= last_write_time.dwLowDateTime; 56 } 57 CloseHandle(hFile); 58 } 59 SDL_free(wFile); 60 } 61#else 62 struct stat sb; 63 64 if (stat(file, &sb) == 0) { 65 modification_time = (Uint64)sb.st_mtime; 66 } 67#endif 68 return modification_time; 69} 70 71static void SDL_FreeSteamVirtualGamepadInfo(void) 72{ 73 int i; 74 75 SDL_AssertJoysticksLocked(); 76 77 for (i = 0; i < SDL_steam_virtual_gamepad_info_count; ++i) { 78 SDL_SteamVirtualGamepadInfo *entry = SDL_steam_virtual_gamepad_info[i]; 79 if (entry) { 80 SDL_free(entry->name); 81 SDL_free(entry); 82 } 83 } 84 SDL_free(SDL_steam_virtual_gamepad_info); 85 SDL_steam_virtual_gamepad_info = NULL; 86 SDL_steam_virtual_gamepad_info_count = 0; 87} 88 89static void AddVirtualGamepadInfo(int slot, SDL_SteamVirtualGamepadInfo *info) 90{ 91 SDL_SteamVirtualGamepadInfo *new_info; 92 93 SDL_AssertJoysticksLocked(); 94 95 if (slot < 0) { 96 return; 97 } 98 99 if (slot >= SDL_steam_virtual_gamepad_info_count) { 100 SDL_SteamVirtualGamepadInfo **slots = (SDL_SteamVirtualGamepadInfo **)SDL_realloc(SDL_steam_virtual_gamepad_info, (slot + 1)*sizeof(*SDL_steam_virtual_gamepad_info)); 101 if (!slots) { 102 return; 103 } 104 while (SDL_steam_virtual_gamepad_info_count <= slot) { 105 slots[SDL_steam_virtual_gamepad_info_count++] = NULL; 106 } 107 SDL_steam_virtual_gamepad_info = slots; 108 } 109 110 if (SDL_steam_virtual_gamepad_info[slot]) { 111 // We already have this slot info 112 return; 113 } 114 115 new_info = (SDL_SteamVirtualGamepadInfo *)SDL_malloc(sizeof(*new_info)); 116 if (!new_info) { 117 return; 118 } 119 SDL_copyp(new_info, info); 120 SDL_steam_virtual_gamepad_info[slot] = new_info; 121 SDL_zerop(info); 122} 123 124void SDL_InitSteamVirtualGamepadInfo(void) 125{ 126 const char *file; 127 128 SDL_AssertJoysticksLocked(); 129 130 // The file isn't available inside the macOS sandbox 131 if (SDL_GetSandbox() == SDL_SANDBOX_MACOS) { 132 return; 133 } 134 135 file = SDL_GetHint(SDL_HINT_STEAM_VIRTUAL_GAMEPAD_INFO_FILE); 136 if (file && *file) { 137 SDL_steam_virtual_gamepad_info_file = SDL_strdup(file); 138 } 139 SDL_UpdateSteamVirtualGamepadInfo(); 140} 141 142bool SDL_SteamVirtualGamepadEnabled(void) 143{ 144 SDL_AssertJoysticksLocked(); 145 146 return (SDL_steam_virtual_gamepad_info != NULL); 147} 148 149bool SDL_UpdateSteamVirtualGamepadInfo(void) 150{ 151 const int UPDATE_CHECK_INTERVAL_MS = 3000; 152 Uint64 now; 153 Uint64 mtime; 154 char *data, *end, *next, *line, *value; 155 size_t size; 156 int slot, new_slot; 157 SDL_SteamVirtualGamepadInfo info; 158 159 SDL_AssertJoysticksLocked(); 160 161 if (!SDL_steam_virtual_gamepad_info_file) { 162 return false; 163 } 164 165 now = SDL_GetTicks(); 166 if (SDL_steam_virtual_gamepad_info_check_time && 167 now < (SDL_steam_virtual_gamepad_info_check_time + UPDATE_CHECK_INTERVAL_MS)) { 168 return false; 169 } 170 SDL_steam_virtual_gamepad_info_check_time = now; 171 172 mtime = GetFileModificationTime(SDL_steam_virtual_gamepad_info_file); 173 if (mtime == 0 || mtime == SDL_steam_virtual_gamepad_info_file_mtime) { 174 return false; 175 } 176 177 data = (char *)SDL_LoadFile(SDL_steam_virtual_gamepad_info_file, &size); 178 if (!data) { 179 return false; 180 } 181 182 SDL_FreeSteamVirtualGamepadInfo(); 183 184 slot = -1; 185 SDL_zero(info); 186 187 for (next = data, end = data + size; next < end; ) { 188 while (next < end && (*next == '\0' || *next == '\r' || *next == '\n')) { 189 ++next; 190 } 191 192 line = next; 193 194 while (next < end && (*next != '\r' && *next != '\n')) { 195 ++next; 196 } 197 *next = '\0'; 198 199 if (SDL_sscanf(line, "[slot %d]", &new_slot) == 1) { 200 if (slot >= 0) { 201 AddVirtualGamepadInfo(slot, &info); 202 } 203 slot = new_slot; 204 } else { 205 value = SDL_strchr(line, '='); 206 if (value) { 207 *value++ = '\0'; 208 209 if (SDL_strcmp(line, "name") == 0) { 210 SDL_free(info.name); 211 info.name = SDL_strdup(value); 212 } else if (SDL_strcmp(line, "VID") == 0) { 213 info.vendor_id = (Uint16)SDL_strtoul(value, NULL, 0); 214 } else if (SDL_strcmp(line, "PID") == 0) { 215 info.product_id = (Uint16)SDL_strtoul(value, NULL, 0); 216 } else if (SDL_strcmp(line, "type") == 0) { 217 info.type = SDL_GetGamepadTypeFromString(value); 218 } else if (SDL_strcmp(line, "handle") == 0) { 219 info.handle = (Uint64)SDL_strtoull(value, NULL, 0); 220 } 221 } 222 } 223 } 224 if (slot >= 0) { 225 AddVirtualGamepadInfo(slot, &info); 226 } 227 SDL_free(info.name); 228 SDL_free(data); 229 230 SDL_steam_virtual_gamepad_info_file_mtime = mtime; 231 232 return true; 233} 234 235const SDL_SteamVirtualGamepadInfo *SDL_GetSteamVirtualGamepadInfo(int slot) 236{ 237 SDL_AssertJoysticksLocked(); 238 239 if (slot < 0 || slot >= SDL_steam_virtual_gamepad_info_count) { 240 return NULL; 241 } 242 return SDL_steam_virtual_gamepad_info[slot]; 243} 244 245void SDL_QuitSteamVirtualGamepadInfo(void) 246{ 247 SDL_AssertJoysticksLocked(); 248 249 if (SDL_steam_virtual_gamepad_info_file) { 250 SDL_FreeSteamVirtualGamepadInfo(); 251 SDL_free(SDL_steam_virtual_gamepad_info_file); 252 SDL_steam_virtual_gamepad_info_file = NULL; 253 } 254}