diff --git a/CMakeLists.txt b/CMakeLists.txt index a2e5c3957..3a97a77fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -274,6 +274,7 @@ set(LIBFASTFETCH_SRC src/modules/gpu.c src/modules/host.c src/modules/icons.c + src/modules/gamepad.c src/modules/kernel.c src/modules/locale.c src/modules/localip.c @@ -335,6 +336,7 @@ if(LINUX) src/detection/gtk.c src/detection/host/host_linux.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_linux.c src/detection/opengl/opengl_linux.c @@ -374,6 +376,7 @@ elseif(ANDROID) src/detection/gpu/gpu_nosupport.c src/detection/host/host_android.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_nosupport.c src/detection/memory/memory_linux.c src/detection/opengl/opengl_linux.c @@ -419,6 +422,7 @@ elseif(BSD) src/detection/gtk.c src/detection/host/host_bsd.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_linux.c src/detection/memory/memory_bsd.c src/detection/opengl/opengl_linux.c @@ -460,6 +464,7 @@ elseif(APPLE) src/detection/gpu/gpu_apple.c src/detection/host/host_apple.c src/detection/localip/localip_linux.c + src/detection/gamepad/gamepad_nosupport.c src/detection/media/media_apple.m src/detection/memory/memory_apple.c src/detection/opengl/opengl_apple.c @@ -500,6 +505,7 @@ elseif(WIN32) src/detection/gpu/gpu_windows.cpp src/detection/host/host_windows.c src/detection/localip/localip_windows.c + src/detection/gamepad/gamepad_windows.cpp src/detection/media/media_nosupport.c src/detection/memory/memory_windows.c src/detection/opengl/opengl_windows.c @@ -712,6 +718,7 @@ elseif(WIN32) PRIVATE "version" PRIVATE "setupapi" PRIVATE "dxgi" + PRIVATE "dinput8" PRIVATE "wtsapi32" PRIVATE "powrprof" ) diff --git a/presets/all b/presets/all index dfcaccc44..e8b10e197 100644 --- a/presets/all +++ b/presets/all @@ -1 +1 @@ ---structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Weather:Break:Colors +--structure Title:Separator:OS:Host:Bios:Board:Chassis:Kernel:Uptime:Processes:Packages:Shell:Display:Brightness:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:CPUUsage:GPU:Memory:Swap:Disk:Battery:PowerAdapter:Player:Media:PublicIP:LocalIP:Wifi:DateTime:Locale:Vulkan:OpenGL:OpenCL:Users:Bluetooth:Sound:Gamepad:Weather:Break:Colors diff --git a/src/common/init.c b/src/common/init.c index 42734a1a3..592ba17df 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -117,6 +117,7 @@ static void defaultConfig(FFinstance* instance) initModuleArg(&instance->config.users); initModuleArg(&instance->config.bluetooth); initModuleArg(&instance->config.sound); + initModuleArg(&instance->config.gamepad); ffStrbufInitA(&instance->config.libPCI, 0); ffStrbufInitA(&instance->config.libVulkan, 0); @@ -386,6 +387,7 @@ static void destroyConfig(FFinstance* instance) destroyModuleArg(&instance->config.users); destroyModuleArg(&instance->config.bluetooth); destroyModuleArg(&instance->config.sound); + destroyModuleArg(&instance->config.gamepad); ffStrbufDestroy(&instance->config.libPCI); ffStrbufDestroy(&instance->config.libVulkan); diff --git a/src/data/config_user.txt b/src/data/config_user.txt index 3938e0783..62aef8ad1 100644 --- a/src/data/config_user.txt +++ b/src/data/config_user.txt @@ -309,6 +309,7 @@ #--users-key Users #--bluetooth-key Bluetooth #--sound-key Sound +#--gamepad-key Gamepad # Format options: # Sets the format string for module values. @@ -355,6 +356,7 @@ #--users-format #--bluetooth-format #--sound-format +#--gamepad-format # Error options: # Sets the format string to use if an error occured @@ -401,6 +403,7 @@ #--users-error #--bluetooth-error #--sound-error +#--gamepad-error # Library options: # Sets an user specific path to a library to load. diff --git a/src/detection/gamepad/gamepad.h b/src/detection/gamepad/gamepad.h new file mode 100644 index 000000000..1def1b430 --- /dev/null +++ b/src/detection/gamepad/gamepad.h @@ -0,0 +1,16 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_gamepad_gamepad +#define FF_INCLUDED_detection_gamepad_gamepad + +#include "fastfetch.h" + +typedef struct FFGamepadDevice +{ + FFstrbuf identifier; + FFstrbuf name; +} FFGamepadDevice; + +const char* ffDetectGamepad(const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */); + +#endif diff --git a/src/detection/gamepad/gamepad_nosupport.c b/src/detection/gamepad/gamepad_nosupport.c new file mode 100644 index 000000000..d921d3552 --- /dev/null +++ b/src/detection/gamepad/gamepad_nosupport.c @@ -0,0 +1,6 @@ +#include "gamepad.h" + +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FF_MAYBE_UNUSED FFlist* devices /* List of FFGamepadDevice */) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/gamepad/gamepad_windows.cpp b/src/detection/gamepad/gamepad_windows.cpp new file mode 100644 index 000000000..c30ef9fe4 --- /dev/null +++ b/src/detection/gamepad/gamepad_windows.cpp @@ -0,0 +1,32 @@ +extern "C" { + #include "gamepad.h" +} + +#include +#define DIRECTINPUT_VERSION 0x0800 +#include + +CALLBACK BOOL DIEnumDevicesCallback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef) +{ + FFlist* devices = (FFlist*) pvRef; + + FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices); + ffStrbufInitF(&device->identifier, "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", + lpddi->guidInstance.Data1, lpddi->guidInstance.Data2, lpddi->guidInstance.Data3, + lpddi->guidInstance.Data4[0], lpddi->guidInstance.Data4[1], lpddi->guidInstance.Data4[2], lpddi->guidInstance.Data4[3], + lpddi->guidInstance.Data4[4], lpddi->guidInstance.Data4[5], lpddi->guidInstance.Data4[6], lpddi->guidInstance.Data4[7]); + ffStrbufInitS(&device->name, lpddi->tszInstanceName); + + return DIENUM_CONTINUE; +} + +extern "C" +const char* ffDetectGamepad(FF_MAYBE_UNUSED const FFinstance* instance, FFlist* devices /* List of FFGamepadDevice */) +{ + IDirectInput8A* dinput; + if (!SUCCEEDED(DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8A, (void**)&dinput, NULL))) + return "DirectInput8Create() failed"; + dinput->EnumDevices(DI8DEVCLASS_GAMECTRL, DIEnumDevicesCallback, devices, DIEDFL_ALLDEVICES); + dinput->Release(); + return NULL; +} diff --git a/src/fastfetch.c b/src/fastfetch.c index ded937466..fb6d0fc27 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -463,6 +463,13 @@ static inline void printCommandHelp(const char* command) "Identifier" ); } + else if(strcasecmp(command, "gamepad-format") == 0) + { + constructAndPrintCommandHelpFormat("gamepad", "{1}", 1, + "Name", + "Identifier" + ); + } else fprintf(stderr, "No specific help for command %s provided\n", command); } @@ -1166,6 +1173,7 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con else if(optionParseModuleArgs(key, value, "users", &instance->config.users)) {} else if(optionParseModuleArgs(key, value, "bluetooth", &instance->config.bluetooth)) {} else if(optionParseModuleArgs(key, value, "sound", &instance->config.sound)) {} + else if(optionParseModuleArgs(key, value, "gamepad", &instance->config.gamepad)) {} /////////////////// //Library options// @@ -1478,6 +1486,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintBluetooth(instance); else if(strcasecmp(line, "sound") == 0) ffPrintSound(instance); + else if(strcasecmp(line, "gamepad") == 0) + ffPrintGamepad(instance); else ffPrintErrorString(instance, line, 0, NULL, NULL, ""); } diff --git a/src/fastfetch.h b/src/fastfetch.h index 0d57902c6..b625611b1 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -148,6 +148,7 @@ typedef struct FFconfig FFModuleArgs users; FFModuleArgs bluetooth; FFModuleArgs sound; + FFModuleArgs gamepad; FFstrbuf libPCI; FFstrbuf libVulkan; @@ -326,5 +327,6 @@ void ffPrintUsers(FFinstance* instance); void ffPrintCommand(FFinstance* instance); void ffPrintBluetooth(FFinstance* instance); void ffPrintSound(FFinstance* instance); +void ffPrintGamepad(FFinstance* instance); #endif diff --git a/src/modules/gamepad.c b/src/modules/gamepad.c new file mode 100644 index 000000000..7b935a972 --- /dev/null +++ b/src/modules/gamepad.c @@ -0,0 +1,48 @@ +#include "common/printing.h" +#include "detection/gamepad/gamepad.h" + +#define FF_GAMEPAD_MODULE_NAME "Gamepad" +#define FF_GAMEPAD_NUM_FORMAT_ARGS 2 + +static void printDevice(FFinstance* instance, const FFGamepadDevice* device, uint8_t index) +{ + if(instance->config.sound.outputFormat.length == 0) + { + ffPrintLogoAndKey(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound.key); + ffStrbufPutTo(&device->name, stdout); + } + else + { + ffPrintFormat(instance, FF_GAMEPAD_MODULE_NAME, index, &instance->config.sound, FF_GAMEPAD_NUM_FORMAT_ARGS, (FFformatarg[]) { + {FF_FORMAT_ARG_TYPE_STRBUF, &device->name}, + {FF_FORMAT_ARG_TYPE_STRBUF, &device->identifier}, + }); + } +} + +void ffPrintGamepad(FFinstance* instance) +{ + FF_LIST_AUTO_DESTROY result; + ffListInit(&result, sizeof(FFGamepadDevice)); + const char* error = ffDetectGamepad(instance, &result); + + if(error) + { + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "%s", error); + return; + } + + if(!result.length) + { + ffPrintError(instance, FF_GAMEPAD_MODULE_NAME, 0, &instance->config.sound, "No devices detected"); + return; + } + + uint8_t index = 0; + FF_LIST_FOR_EACH(FFGamepadDevice, device, result) + { + printDevice(instance, device, result.length > 1 ? ++index : 0); + ffStrbufDestroy(&device->identifier); + ffStrbufDestroy(&device->name); + } +}