From 470f4a318f1c5aaf095c50eceac8e22849c42af0 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Tue, 16 Jan 2024 00:06:06 +0000 Subject: [PATCH 01/17] Add bool is_linux() to the public API for easy access --- HarmonyLinkLib/include/HarmonyLinkLib.h | 2 ++ HarmonyLinkLib/src/HarmonyLinkLib.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/HarmonyLinkLib/include/HarmonyLinkLib.h b/HarmonyLinkLib/include/HarmonyLinkLib.h index aaa1887..dd6bebd 100644 --- a/HarmonyLinkLib/include/HarmonyLinkLib.h +++ b/HarmonyLinkLib/include/HarmonyLinkLib.h @@ -46,6 +46,8 @@ namespace HarmonyLinkLib { extern "C" HARMONYLINKLIB_API bool get_is_wine(); + extern "C" HARMONYLINKLIB_API bool get_is_linux(); + extern "C" HARMONYLINKLIB_API FCPUInfo* get_cpu_info(); extern "C" HARMONYLINKLIB_API FDevice* get_device_info(); diff --git a/HarmonyLinkLib/src/HarmonyLinkLib.cpp b/HarmonyLinkLib/src/HarmonyLinkLib.cpp index fecfc97..ff05bae 100644 --- a/HarmonyLinkLib/src/HarmonyLinkLib.cpp +++ b/HarmonyLinkLib/src/HarmonyLinkLib.cpp @@ -32,6 +32,17 @@ namespace HarmonyLinkLib return PlatformUtilities->is_running_under_wine(); } + bool get_is_linux() + { + if (!PlatformUtilities) + { + std::wcout << "Failed to get platform utilities!\n"; + return false; + } + + return PlatformUtilities->is_linux(); + } + FCPUInfo* get_cpu_info() { if (!PlatformUtilities) From 545815fd6dc9d9d36bedd7add168e65baa315a30 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Tue, 16 Jan 2024 00:09:12 +0000 Subject: [PATCH 02/17] Add initial score-based dock detection This is early development & untested code specifically targeting the steam deck for now until further finalised --- HarmonyLinkLib/include/HarmonyLinkLib.h | 2 + HarmonyLinkLib/src/HarmonyLinkLib.cpp | 11 + .../src/Platform/IPlatformUtilities.cpp | 237 +++++++++++------- .../src/Platform/IPlatformUtilities.h | 11 +- .../src/Platform/Unix/UnixUtilities.cpp | 24 +- .../src/Platform/Unix/UnixUtilities.h | 8 + .../src/Platform/Windows/WindowsUtilities.cpp | 187 +++++++++----- .../src/Platform/Windows/WindowsUtilities.h | 6 + 8 files changed, 336 insertions(+), 150 deletions(-) diff --git a/HarmonyLinkLib/include/HarmonyLinkLib.h b/HarmonyLinkLib/include/HarmonyLinkLib.h index dd6bebd..d6575a5 100644 --- a/HarmonyLinkLib/include/HarmonyLinkLib.h +++ b/HarmonyLinkLib/include/HarmonyLinkLib.h @@ -48,6 +48,8 @@ namespace HarmonyLinkLib extern "C" HARMONYLINKLIB_API bool get_is_linux(); + extern "C" HARMONYLINKLIB_API bool get_is_docked(); + extern "C" HARMONYLINKLIB_API FCPUInfo* get_cpu_info(); extern "C" HARMONYLINKLIB_API FDevice* get_device_info(); diff --git a/HarmonyLinkLib/src/HarmonyLinkLib.cpp b/HarmonyLinkLib/src/HarmonyLinkLib.cpp index ff05bae..91ccc2c 100644 --- a/HarmonyLinkLib/src/HarmonyLinkLib.cpp +++ b/HarmonyLinkLib/src/HarmonyLinkLib.cpp @@ -43,6 +43,17 @@ namespace HarmonyLinkLib return PlatformUtilities->is_linux(); } + bool get_is_docked() + { + if (!PlatformUtilities) + { + std::wcout << "Failed to get platform utilities!\n"; + return false; + } + + return PlatformUtilities->is_docked(); + } + FCPUInfo* get_cpu_info() { if (!PlatformUtilities) diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index 4475379..8c53695 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -31,106 +31,173 @@ namespace HarmonyLinkLib { static std::shared_ptr INSTANCE = nullptr; -std::shared_ptr& IPlatformUtilities::GetInstance() -{ - if (!INSTANCE) + std::shared_ptr& IPlatformUtilities::GetInstance() { -#if BUILD_WINDOWS - INSTANCE = std::make_shared(); -#elif BUILD_LINUX - INSTANCE = std::make_shared(); -#elif BUILD_MAC - INSTANCE = std::make_shared(); -#elif BUILD_UNIX - INSTANCE = std::make_shared(); -// ... other platform checks -#else - std::wcout << "Platform is not supported.\n" -#endif + if (!INSTANCE) + { + #if BUILD_WINDOWS + INSTANCE = std::make_shared(); + #elif BUILD_LINUX + INSTANCE = std::make_shared(); + #elif BUILD_MAC + INSTANCE = std::make_shared(); + #elif BUILD_UNIX + INSTANCE = std::make_shared(); + // ... other platform checks + #else + std::wcout << "Platform is not supported.\n" + #endif + } + + return INSTANCE; } - - return INSTANCE; -} -bool IPlatformUtilities::is_running_under_wine() -{ - return WineUtilities::is_wine_present(); -} - -bool IPlatformUtilities::is_linux() -{ -#ifdef BUILD_LINUX - return true; -#else - return is_running_under_wine(); -#endif -} - -std::shared_ptr IPlatformUtilities::get_device() -{ - FDevice new_device; - - if (is_linux()) + bool IPlatformUtilities::is_running_under_wine() { - new_device.platform = EPlatform::LINUX; + return WineUtilities::is_wine_present(); } - else + + bool IPlatformUtilities::is_linux() { - new_device.platform = EPlatform::WINDOWS; - } - - const std::shared_ptr battery_status = get_battery_status(); - - if (battery_status && !battery_status->has_battery) - { - new_device.device = EDevice::DESKTOP; - } - else - { - new_device.device = EDevice::LAPTOP; - } - - if (is_steam_deck(new_device)) { - new_device.device = EDevice::STEAM_DECK; - } - return std::make_shared(new_device); -} - -// Helper function to check if the device is a Steam Deck -bool IPlatformUtilities::is_steam_deck(const FDevice& device) { - - // Check if the device is already identified as a Steam Deck - if (device.device == EDevice::STEAM_DECK) { + #ifdef BUILD_LINUX return true; + #else + return is_running_under_wine(); + #endif } - // Check for Steam Deck by OS version - if (const std::shared_ptr version = get_os_version()) { - if (version->variant_id == "steamdeck" && version->name == "SteamOS") { + bool IPlatformUtilities::is_steam_deck() + { + const std::shared_ptr device = get_device(); + + return device && device->device == EDevice::STEAM_DECK; + } + + bool IPlatformUtilities::is_docked() + { + static constexpr uint8_t CHARGING_SCORE = 3; + static constexpr uint8_t EXTERNAL_MONITOR_SCORE = 3; + static constexpr uint8_t KEYBOARD_DETECTION_SCORE = 2; + static constexpr uint8_t CONTROLLER_DETECTION_SCORE = 2; + static constexpr uint8_t FINAL_TARGET_DETECTION_SCORE = 6; + + + const std::shared_ptr device = get_device(); + + if (!device) + { + std::wcout << "Error: failed to get device.\n"; + return false; + } + + if (device->device != EDevice::STEAM_DECK) + { + std::wcout << "Error: Dock detection is currently only supported on Steam Decks.\n"; + return false; + } + + uint8_t score = 0; + + if (is_charging()) + { + score += CHARGING_SCORE; + } + + if (get_is_external_monitor_connected()) + { + score += EXTERNAL_MONITOR_SCORE; + } + + if (get_mouse_keyboard_detected()) + { + score += KEYBOARD_DETECTION_SCORE; + } + + if (get_external_controller_detected()) + { + score += CONTROLLER_DETECTION_SCORE; + } + + return score >= FINAL_TARGET_DETECTION_SCORE; + } + + std::shared_ptr IPlatformUtilities::get_device() + { + FDevice new_device; + + if (is_linux()) + { + new_device.platform = EPlatform::LINUX; + } + else + { + new_device.platform = EPlatform::WINDOWS; + } + + const std::shared_ptr battery_status = get_battery_status(); + + if (battery_status && !battery_status->has_battery) + { + new_device.device = EDevice::DESKTOP; + } + else + { + new_device.device = EDevice::LAPTOP; + } + + if (is_steam_deck_detected(new_device)) { + new_device.device = EDevice::STEAM_DECK; + } + return std::make_shared(new_device); + } + + // Helper function to check if the device is a Steam Deck + bool IPlatformUtilities::is_steam_deck_detected(const FDevice& device) { + + // Check if the device is already identified as a Steam Deck + if (device.device == EDevice::STEAM_DECK) { return true; } - } else { - wprintf(L"OS version information not available.\n"); - } - // Set of known Steam Deck CPU model names - const std::set steam_deck_models = {"amd custom apu 0405" /*, other models... */}; - - // Check for Steam Deck by CPU model name - if (const std::shared_ptr cpu_info = get_cpu_info()) { - const FString cpu_model_lower = FString::to_lower(cpu_info->Model_Name); - for (const auto& model : steam_deck_models) { - if (cpu_model_lower == model) { - wprintf(L"Steam Deck detected by CPU model name.\n"); + // Check for Steam Deck by OS version + if (const std::shared_ptr version = get_os_version()) { + if (version->variant_id == "steamdeck" && version->name == "SteamOS") { return true; } + } else { + wprintf(L"OS version information not available.\n"); } - } else { - wprintf(L"CPU information not available.\n"); + + // Set of known Steam Deck CPU model names + const std::set steam_deck_models = {"amd custom apu 0405" /*, other models... */}; + + // Check for Steam Deck by CPU model name + if (const std::shared_ptr cpu_info = get_cpu_info()) { + const FString cpu_model_lower = FString::to_lower(cpu_info->Model_Name); + for (const auto& model : steam_deck_models) { + if (cpu_model_lower == model) { + wprintf(L"Steam Deck detected by CPU model name.\n"); + return true; + } + } + } else { + wprintf(L"CPU information not available.\n"); + } + + wprintf(L"Device is not a Steam Deck.\n"); + + return false; } - wprintf(L"Device is not a Steam Deck.\n"); - - return false; -} + bool IPlatformUtilities::is_connected_to_ac() + { + const std::shared_ptr battery = get_battery_status(); + return battery && battery->is_connected_to_ac; + } + + bool IPlatformUtilities::is_charging() + { + const std::shared_ptr battery = get_battery_status(); + return battery && battery->has_battery && battery->is_connected_to_ac; + } } diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h index 933b5db..856e1a4 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h @@ -35,13 +35,22 @@ namespace HarmonyLinkLib // General OS-level functions virtual bool is_running_under_wine(); virtual bool is_linux(); + virtual bool is_steam_deck(); + virtual bool is_docked(); virtual std::shared_ptr get_device(); virtual std::shared_ptr get_cpu_info() = 0; virtual std::shared_ptr get_battery_status() = 0; virtual std::shared_ptr get_os_version() = 0; + virtual bool get_is_external_monitor_connected() = 0; + virtual bool get_mouse_keyboard_detected() = 0; + virtual bool get_external_controller_detected() = 0; + //virtual bool get_is_ethernet_connected() = 0; + //virtual bool get_is_external_input_detected() = 0; - bool is_steam_deck(const FDevice& device); + bool is_steam_deck_detected(const FDevice& device); + bool is_connected_to_ac(); + bool is_charging(); // Add more virtual functions for other OS interactions here }; diff --git a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp index 98864a1..63fef64 100644 --- a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp @@ -18,21 +18,43 @@ namespace HarmonyLinkLib { bool UnixUtilities::is_running_under_wine() { - return false; + std::wcout << "This feature is not supported on unix systems yet.\n"; + return false; } std::shared_ptr UnixUtilities::get_cpu_info() { + std::wcout << "This feature is not supported on unix systems yet.\n"; return nullptr; } std::shared_ptr UnixUtilities::get_battery_status() { + std::wcout << "This feature is not supported on unix systems yet.\n"; return nullptr; } std::shared_ptr UnixUtilities::get_os_version() { + std::wcout << "This feature is not supported on unix systems yet.\n"; return nullptr; } + + bool UnixUtilities::get_is_external_monitor_connected() + { + std::wcout << "This feature is not supported on unix-based systems yet.\n"; + return false; + } + + bool UnixUtilities::get_mouse_keyboard_detected() + { + std::wcout << "This feature is not supported on unix-based systems yet.\n"; + return false; + } + + bool UnixUtilities::get_external_controller_detected() + { + std::wcout << "This feature is not supported on unix-based systems yet.\n"; + return false; + } } \ No newline at end of file diff --git a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h index c627c0a..7e0fd5a 100644 --- a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h +++ b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h @@ -17,6 +17,8 @@ #include "Platform/IPlatformUtilities.h" namespace HarmonyLinkLib { + // This is more of a "catch all" for all unix-based systems + // that don't have their own implementations. class UnixUtilities : public IPlatformUtilities { public: bool is_running_under_wine() override; @@ -24,6 +26,12 @@ namespace HarmonyLinkLib std::shared_ptr get_cpu_info() override; std::shared_ptr get_battery_status() override; std::shared_ptr get_os_version() override; + + bool get_is_external_monitor_connected() override; + + bool get_mouse_keyboard_detected() override; + + bool get_external_controller_detected() override; // Implementation for other Unix/Linux-specific functions }; diff --git a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp index 6185502..f363bd8 100644 --- a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp @@ -17,79 +17,140 @@ #include #include +#include +#pragma comment(lib, "XInput.lib") + #include "Platform/WineUtilities.h" namespace HarmonyLinkLib { std::shared_ptr WindowsUtilities::get_battery_status() -{ - if (is_linux()) { - return WineUtilities::get_battery_status(); - } - FBattery result; - - SYSTEM_POWER_STATUS status; - if (GetSystemPowerStatus(&status)) { - result.has_battery = status.BatteryFlag != 128; // 128 indicates no battery - result.is_connected_to_ac = status.ACLineStatus == 1; - result.battery_percent = result.has_battery ? status.BatteryLifePercent : 0; - } else { - std::wcout << "Failed to get power statistics.\n"; - } - - return std::make_shared(result); -} - -std::shared_ptr WindowsUtilities::get_cpu_info() -{ - if (is_linux()) - { - return WineUtilities::get_cpu_info(); - } - - return {}; -} - -std::shared_ptr WindowsUtilities::get_os_version() -{ - if (is_linux()) - { - return WineUtilities::get_linux_info(); - } - - OSVERSIONINFOEX os_version_info; - ZeroMemory(&os_version_info, sizeof(OSVERSIONINFOEX)); - os_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - if (!GetVersionEx(reinterpret_cast(&os_version_info))) { - // Handle error if needed - return nullptr; - } - - FOSVerInfo os_version; - - HKEY h_key; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_READ, &h_key) == ERROR_SUCCESS) - { - DWORD dw_size; - DWORD dw_type; - char sz_product_name[256]; - dw_size = sizeof(sz_product_name); - if (RegQueryValueEx(h_key, TEXT("ProductName"), nullptr, &dw_type, reinterpret_cast(sz_product_name), &dw_size) == ERROR_SUCCESS) + if (is_linux()) { - os_version.pretty_name = sz_product_name; + return WineUtilities::get_battery_status(); } - RegCloseKey(h_key); + FBattery result; + + SYSTEM_POWER_STATUS status; + if (GetSystemPowerStatus(&status)) { + result.has_battery = status.BatteryFlag != 128; // 128 indicates no battery + result.is_connected_to_ac = status.ACLineStatus == 1; + result.battery_percent = result.has_battery ? status.BatteryLifePercent : 0; + } else { + std::wcout << "Failed to get power statistics.\n"; + } + + return std::make_shared(result); } - std::stringstream version; - version << os_version_info.dwMajorVersion << "." << os_version_info.dwMinorVersion; - os_version.version_id = version.str(); + std::shared_ptr WindowsUtilities::get_cpu_info() + { + if (is_linux()) + { + return WineUtilities::get_cpu_info(); + } + + return {}; + } - os_version.name = "Windows"; - os_version.version = os_version_info.dwBuildNumber; // Build number as the version + std::shared_ptr WindowsUtilities::get_os_version() + { + if (is_linux()) + { + return WineUtilities::get_linux_info(); + } + + OSVERSIONINFOEX os_version_info; + ZeroMemory(&os_version_info, sizeof(OSVERSIONINFOEX)); + os_version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - return std::make_shared(os_version); -} + if (!GetVersionEx(reinterpret_cast(&os_version_info))) { + // Handle error if needed + return nullptr; + } + + FOSVerInfo os_version; + + HKEY h_key; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_READ, &h_key) == ERROR_SUCCESS) + { + DWORD dw_size; + DWORD dw_type; + char sz_product_name[256]; + dw_size = sizeof(sz_product_name); + if (RegQueryValueEx(h_key, TEXT("ProductName"), nullptr, &dw_type, reinterpret_cast(sz_product_name), &dw_size) == ERROR_SUCCESS) + { + os_version.pretty_name = sz_product_name; + } + RegCloseKey(h_key); + } + + std::stringstream version; + version << os_version_info.dwMajorVersion << "." << os_version_info.dwMinorVersion; + os_version.version_id = version.str(); + + os_version.name = "Windows"; + os_version.version = os_version_info.dwBuildNumber; // Build number as the version + + return std::make_shared(os_version); + } + + bool WindowsUtilities::get_is_external_monitor_connected() + { + // SM_CMONITORS returns the count of all display monitors. + const int monitorCount = GetSystemMetrics(SM_CMONITORS); + + // More than one monitor implies an external monitor is connected. + return monitorCount > 1; + } + + bool WindowsUtilities::get_mouse_keyboard_detected() + { + UINT n_devices; + GetRawInputDeviceList(nullptr, &n_devices, sizeof(RAWINPUTDEVICELIST)); + + if (n_devices > 0) { + bool mouse_detected = false; + bool keyboard_detected = false; + + std::vector devices(n_devices); + GetRawInputDeviceList(devices.data(), &n_devices, sizeof(RAWINPUTDEVICELIST)); + + for (const auto& device : devices) { + switch (device.dwType) + { + case RIM_TYPEMOUSE: + mouse_detected = true; + break; + case RIM_TYPEKEYBOARD: + keyboard_detected = true; + break; + + default: + break; + } + } + return mouse_detected && keyboard_detected; + } + return false; + } + + bool WindowsUtilities::get_external_controller_detected() + { + static_assert(XUSER_MAX_COUNT <= UINT8_MAX, "XUSER_MAX_COUNT exceeds uint8_t size"); + + uint8_t connectedGamepads = 0; + + for (DWORD i = 0; i < XUSER_MAX_COUNT; ++i) { + XINPUT_STATE state; + ZeroMemory(&state, sizeof(XINPUT_STATE)); + + if (XInputGetState(i, &state) == ERROR_SUCCESS) { + connectedGamepads++; + } + } + + return connectedGamepads > 1; + } } diff --git a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h index 583ca45..c51eacb 100644 --- a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h +++ b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h @@ -26,5 +26,11 @@ namespace HarmonyLinkLib std::shared_ptr get_cpu_info() override; std::shared_ptr get_os_version() override; + + bool get_is_external_monitor_connected() override; + + bool get_mouse_keyboard_detected() override; + + bool get_external_controller_detected() override; }; } From ea7042c9adb3094e0ea1c544115bf98ce919ec2c Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Tue, 16 Jan 2024 02:04:22 +0000 Subject: [PATCH 03/17] Improved dock detection --- .../src/Platform/IPlatformUtilities.cpp | 22 ++++-- .../src/Platform/IPlatformUtilities.h | 4 +- .../src/Platform/Unix/UnixUtilities.cpp | 14 +++- .../src/Platform/Unix/UnixUtilities.h | 6 +- .../src/Platform/Windows/WindowsUtilities.cpp | 71 ++++++++++++------- .../src/Platform/Windows/WindowsUtilities.h | 6 +- HarmonyLinkTest/src/main.cpp | 6 ++ 7 files changed, 95 insertions(+), 34 deletions(-) diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index 8c53695..e5ff858 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -76,10 +76,12 @@ namespace HarmonyLinkLib bool IPlatformUtilities::is_docked() { static constexpr uint8_t CHARGING_SCORE = 3; - static constexpr uint8_t EXTERNAL_MONITOR_SCORE = 3; - static constexpr uint8_t KEYBOARD_DETECTION_SCORE = 2; - static constexpr uint8_t CONTROLLER_DETECTION_SCORE = 2; - static constexpr uint8_t FINAL_TARGET_DETECTION_SCORE = 6; + static constexpr uint8_t EXTERNAL_MONITOR_SCORE = 4; + static constexpr uint8_t STEAM_DECK_RESOLUTION_SCORE = 3; + static constexpr uint8_t KEYBOARD_DETECTION_SCORE = 1; + static constexpr uint8_t MOUSE_DETECTION_SCORE = 2; + static constexpr uint8_t CONTROLLER_DETECTION_SCORE = 3; + static constexpr uint8_t FINAL_TARGET_DETECTION_SCORE = 9; const std::shared_ptr device = get_device(); @@ -108,11 +110,21 @@ namespace HarmonyLinkLib score += EXTERNAL_MONITOR_SCORE; } - if (get_mouse_keyboard_detected()) + if (get_is_steam_deck_native_resolution()) + { + score += STEAM_DECK_RESOLUTION_SCORE; + } + + if (get_keyboard_detected()) { score += KEYBOARD_DETECTION_SCORE; } + if (get_mouse_detected()) + { + score += MOUSE_DETECTION_SCORE; + } + if (get_external_controller_detected()) { score += CONTROLLER_DETECTION_SCORE; diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h index 856e1a4..420edef 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h @@ -43,8 +43,10 @@ namespace HarmonyLinkLib virtual std::shared_ptr get_battery_status() = 0; virtual std::shared_ptr get_os_version() = 0; virtual bool get_is_external_monitor_connected() = 0; - virtual bool get_mouse_keyboard_detected() = 0; + virtual bool get_keyboard_detected() = 0; + virtual bool get_mouse_detected() = 0; virtual bool get_external_controller_detected() = 0; + virtual bool get_is_steam_deck_native_resolution() = 0; //virtual bool get_is_ethernet_connected() = 0; //virtual bool get_is_external_input_detected() = 0; diff --git a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp index 63fef64..0d3b777 100644 --- a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp @@ -46,7 +46,13 @@ namespace HarmonyLinkLib return false; } - bool UnixUtilities::get_mouse_keyboard_detected() + bool UnixUtilities::get_keyboard_detected() + { + std::wcout << "This feature is not supported on unix-based systems yet.\n"; + return false; + } + + bool UnixUtilities::get_mouse_detected() { std::wcout << "This feature is not supported on unix-based systems yet.\n"; return false; @@ -57,4 +63,10 @@ namespace HarmonyLinkLib std::wcout << "This feature is not supported on unix-based systems yet.\n"; return false; } + + bool UnixUtilities::get_is_steam_deck_native_resolution() + { + std::wcout << "This feature is not supported on unix-based systems yet.\n"; + return false; + } } \ No newline at end of file diff --git a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h index 7e0fd5a..8a06546 100644 --- a/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h +++ b/HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h @@ -29,9 +29,13 @@ namespace HarmonyLinkLib bool get_is_external_monitor_connected() override; - bool get_mouse_keyboard_detected() override; + bool get_keyboard_detected() override; + + bool get_mouse_detected() override; bool get_external_controller_detected() override; + + bool get_is_steam_deck_native_resolution() override; // Implementation for other Unix/Linux-specific functions }; diff --git a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp index f363bd8..dfd7aa8 100644 --- a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp @@ -21,6 +21,7 @@ #pragma comment(lib, "XInput.lib") #include "Platform/WineUtilities.h" +#include namespace HarmonyLinkLib { @@ -105,35 +106,40 @@ namespace HarmonyLinkLib return monitorCount > 1; } - bool WindowsUtilities::get_mouse_keyboard_detected() + bool WindowsUtilities::get_keyboard_detected() { UINT n_devices; - GetRawInputDeviceList(nullptr, &n_devices, sizeof(RAWINPUTDEVICELIST)); + std::vector devices; + + GetRawInputDeviceList(devices.data(), &n_devices, sizeof(RAWINPUTDEVICELIST)); - if (n_devices > 0) { - bool mouse_detected = false; - bool keyboard_detected = false; - - std::vector devices(n_devices); - GetRawInputDeviceList(devices.data(), &n_devices, sizeof(RAWINPUTDEVICELIST)); - - for (const auto& device : devices) { - switch (device.dwType) - { - case RIM_TYPEMOUSE: - mouse_detected = true; - break; - case RIM_TYPEKEYBOARD: - keyboard_detected = true; - break; - - default: - break; - } - } - return mouse_detected && keyboard_detected; + if (n_devices == 0) + { + return false; } - return false; + + return std::any_of(devices.begin(), devices.end(), [](const RAWINPUTDEVICELIST& device) + { + return device.dwType == RIM_TYPEKEYBOARD; + }); + } + + bool WindowsUtilities::get_mouse_detected() + { + UINT n_devices; + std::vector devices; + + GetRawInputDeviceList(devices.data(), &n_devices, sizeof(RAWINPUTDEVICELIST)); + + if (n_devices == 0) + { + return false; + } + + return std::any_of(devices.begin(), devices.end(), [](const RAWINPUTDEVICELIST& device) + { + return device.dwType == RIM_TYPEMOUSE; + }); } bool WindowsUtilities::get_external_controller_detected() @@ -153,4 +159,19 @@ namespace HarmonyLinkLib return connectedGamepads > 1; } + + bool WindowsUtilities::get_is_steam_deck_native_resolution() + { + DEVMODE devMode; + devMode.dmSize = sizeof(DEVMODE); + + // Get the current display settings for the primary monitor + if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode)) { + // Check if the resolution is higher than 800p (1280x800) + if (devMode.dmPelsWidth > 1280 || devMode.dmPelsHeight > 800) { + return true; + } + } + return false; + } } diff --git a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h index c51eacb..809b204 100644 --- a/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h +++ b/HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h @@ -29,8 +29,12 @@ namespace HarmonyLinkLib bool get_is_external_monitor_connected() override; - bool get_mouse_keyboard_detected() override; + bool get_keyboard_detected() override; + + bool get_mouse_detected() override; bool get_external_controller_detected() override; + + bool get_is_steam_deck_native_resolution() override; }; } diff --git a/HarmonyLinkTest/src/main.cpp b/HarmonyLinkTest/src/main.cpp index 69c0957..e9eaf87 100644 --- a/HarmonyLinkTest/src/main.cpp +++ b/HarmonyLinkTest/src/main.cpp @@ -128,6 +128,12 @@ int main() battery->free(); } + const bool is_docked = HarmonyLinkLib::get_is_docked(); + + const char* dock_check_string = is_docked ? "is" : "isn't"; + + wprintf(L"Device %hs docked\n", dock_check_string); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } From ce7de29721185ce8fa5181a2e18a7e5c7c40fd24 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 00:54:31 +0100 Subject: [PATCH 04/17] Add Utilities class to add utility functions --- HarmonyLinkLib/CMakeLists.txt | 4 ++ .../src/Platform/IPlatformUtilities.cpp | 12 +++++ HarmonyLinkLib/src/Utilities.cpp | 53 +++++++++++++++++++ HarmonyLinkLib/src/Utilities.h | 30 +++++++++++ 4 files changed, 99 insertions(+) create mode 100644 HarmonyLinkLib/src/Utilities.cpp create mode 100644 HarmonyLinkLib/src/Utilities.h diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index 8412f45..10486b1 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -34,11 +34,13 @@ set(COMMON_SOURCES "src/Version.cpp" "src/dllmain.cpp" "src/Platform/WineUtilities.cpp" + "src/Utilities.cpp" ) # Explicitly list include files set(COMMON_INCLUDES "include/Core.h" + "include/Structs/FBattery.h" "include/Structs/FOSVerInfo.h" "include/Structs/FDevice.h" @@ -53,6 +55,8 @@ set(COMMON_INCLUDES "src/Platform/IPlatformUtilities.h" "src/Platform/WineUtilities.h" + + "src//Utilities.h" ) set(WINDOWS_SOURCES diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index e5ff858..90bd62a 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -14,7 +14,9 @@ #include "IPlatformUtilities.h" +#include #include +#include "Utilities.h" #include "WineUtilities.h" #if BUILD_WINDOWS @@ -100,35 +102,45 @@ namespace HarmonyLinkLib uint8_t score = 0; + Utilities::DebugPrint("Detected: ", false); + if (is_charging()) { + Utilities::DebugPrint("Charging, ", false); score += CHARGING_SCORE; } if (get_is_external_monitor_connected()) { + Utilities::DebugPrint("External monitor, ", false); score += EXTERNAL_MONITOR_SCORE; } if (get_is_steam_deck_native_resolution()) { + Utilities::DebugPrint("Non-native resolution, ", false); score += STEAM_DECK_RESOLUTION_SCORE; } if (get_keyboard_detected()) { + Utilities::DebugPrint("keyboard ", false); score += KEYBOARD_DETECTION_SCORE; } if (get_mouse_detected()) { + Utilities::DebugPrint("mouse, ", false); score += MOUSE_DETECTION_SCORE; } if (get_external_controller_detected()) { + Utilities::DebugPrint("external controller, ", false); score += CONTROLLER_DETECTION_SCORE; } + + Utilities::DebugPrint(std::format("Score: {}/{}", score, FINAL_TARGET_DETECTION_SCORE).c_str()); return score >= FINAL_TARGET_DETECTION_SCORE; } diff --git a/HarmonyLinkLib/src/Utilities.cpp b/HarmonyLinkLib/src/Utilities.cpp new file mode 100644 index 0000000..608437c --- /dev/null +++ b/HarmonyLinkLib/src/Utilities.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2024 Jordon Brooks +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "Utilities.h" + +#include + +#include "FString.h" + +void HarmonyLinkLib::Utilities::DebugPrint(const FString& String, bool AddNewline) +{ +#ifdef DEBUG_MODE + std::wcout << String.c_str(); + + if (AddNewline) + { + std::wcout << L"\n"; + } +#endif +} + +void HarmonyLinkLib::Utilities::DebugPrint(const char* String, bool AddNewline) +{ +#ifdef DEBUG_MODE + std::wcout << std::wstring(String, String + std::strlen(String)); + + if (AddNewline) { + std::wcout << L"\n"; + } +#endif +} + +void HarmonyLinkLib::Utilities::DebugPrint(const wchar_t* String, bool AddNewline) +{ +#ifdef DEBUG_MODE + std::wcout << String; + + if (AddNewline) { + std::wcout << L"\n"; + } +#endif +} diff --git a/HarmonyLinkLib/src/Utilities.h b/HarmonyLinkLib/src/Utilities.h new file mode 100644 index 0000000..d6114c8 --- /dev/null +++ b/HarmonyLinkLib/src/Utilities.h @@ -0,0 +1,30 @@ +// Copyright (c) 2024 Jordon Brooks +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include "HarmonyLinkLib.h" + +namespace HarmonyLinkLib +{ + class FString; + + class Utilities + { + public: + static void DebugPrint(const FString& String, bool AddNewline = true); + static void DebugPrint(const char* String, bool AddNewline = true); + static void DebugPrint(const wchar_t* String, bool AddNewline = true); + }; +} From d0e1c3749f31511a67013d1c1c1e7a9c4425e96a Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 00:55:35 +0100 Subject: [PATCH 05/17] Fix debug compile definition not working --- CMakeLists.txt | 2 ++ HarmonyLinkLib/CMakeLists.txt | 4 ---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bf0723..16e76c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ else() message(STATUS "Building with unspecified build type") endif() +add_compile_definitions($<$:DEBUG_MODE>) + #set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Platform-specific definitions diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index 10486b1..138a697 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -118,10 +118,6 @@ target_include_directories(HarmonyLinkLib target_compile_definitions(HarmonyLinkLib PRIVATE HARMONYLINKLIB_EXPORTS) -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - target_compile_definitions(HarmonyLinkLib PRIVATE "DEBUG_MODE") -endif() - # Set output directories for all build types foreach(TYPE IN ITEMS DEBUG RELEASE) string(TOUPPER ${TYPE} TYPE_UPPER) From 270adff68e2260c5b384001dbd71693b7053ec45 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 00:57:46 +0100 Subject: [PATCH 06/17] Add Dev branch to compile check workflow --- .github/workflows/cmake-multi-platform.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index dd86440..41e82b4 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -5,9 +5,9 @@ name: CMake on multiple platforms on: workflow_dispatch: push: - branches: [ "Stable" ] + branches: [ "Stable", "Dev" ] pull_request: - branches: [ "Stable" ] + branches: [ "Stable", "Dev" ] jobs: build: From 5b34e9de0fee6dcca0e6f3c8c70d2b295263637b Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 01:05:36 +0100 Subject: [PATCH 07/17] Update CMakeLists to use C++ 20 --- HarmonyLinkLib/CMakeLists.txt | 2 +- HarmonyLinkTest/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index 138a697..76b4ccf 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -24,7 +24,7 @@ endif() configure_file(include/Version.h.in Version.generated.h) # Specify the C++ standard -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) # Explicitly list source files diff --git a/HarmonyLinkTest/CMakeLists.txt b/HarmonyLinkTest/CMakeLists.txt index 5616a24..3b4c7d7 100644 --- a/HarmonyLinkTest/CMakeLists.txt +++ b/HarmonyLinkTest/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(HarmonyLinkTest) # Specify the C++ standard -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) # Automatically add all .cpp and .h/.hpp files in the src directory From 448f0c2124d10e83ee41844d5102435ec116a8ed Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 01:29:06 +0100 Subject: [PATCH 08/17] Replace std::format with oss fmt library --- HarmonyLinkLib/CMakeLists.txt | 20 +++++++++++++++++++ .../src/Platform/IPlatformUtilities.cpp | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index 76b4ccf..e551e6c 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -1,6 +1,23 @@ cmake_minimum_required(VERSION 3.10) project(HarmonyLinkLib VERSION 2.0.0) +include(FetchContent) + +FetchContent_Declare( + fmt + GIT_REPOSITORY https://github.com/fmtlib/fmt.git + GIT_TAG 10.2.1 # Specify the desired version of {fmt} +) + +FetchContent_MakeAvailable(fmt) +if(NOT fmt_POPULATED) + FetchContent_Populate(fmt) + # Add fmt but exclude it from the ALL target, reducing IDE clutter + add_subdirectory(${fmt_SOURCE_DIR} ${fmt_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + +set_target_properties(fmt PROPERTIES FOLDER External) + # Find the current Git branch and the last commit timestamp find_package(Git QUIET) if(GIT_FOUND) @@ -127,3 +144,6 @@ foreach(TYPE IN ITEMS DEBUG RELEASE) ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/${PROJECT_NAME}" ) endforeach() + +# Link fmt library +target_link_libraries(${PROJECT_NAME} PRIVATE fmt::fmt) diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index 90bd62a..ecfb670 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -14,7 +14,7 @@ #include "IPlatformUtilities.h" -#include +#include #include #include "Utilities.h" @@ -140,7 +140,7 @@ namespace HarmonyLinkLib score += CONTROLLER_DETECTION_SCORE; } - Utilities::DebugPrint(std::format("Score: {}/{}", score, FINAL_TARGET_DETECTION_SCORE).c_str()); + Utilities::DebugPrint(fmt::format("Score: {}/{}", score, FINAL_TARGET_DETECTION_SCORE).c_str()); return score >= FINAL_TARGET_DETECTION_SCORE; } From e3830ccf3686f31e58ebeca8a6aea7648aee51f1 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 01:34:16 +0100 Subject: [PATCH 09/17] Enable PIC --- HarmonyLinkLib/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index e551e6c..a702863 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -18,6 +18,8 @@ endif() set_target_properties(fmt PROPERTIES FOLDER External) +set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + # Find the current Git branch and the last commit timestamp find_package(Git QUIET) if(GIT_FOUND) From 1b15cd1de1d84774c5deb3c9d81fa54a9caa41e9 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 01:35:50 +0100 Subject: [PATCH 10/17] enable PIC specifically for fmt --- HarmonyLinkLib/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index a702863..c36aa39 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -17,8 +17,7 @@ if(NOT fmt_POPULATED) endif() set_target_properties(fmt PROPERTIES FOLDER External) - -set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) +set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE TRUE) # Find the current Git branch and the last commit timestamp find_package(Git QUIET) From eacab9957851a41c5430565bc87c0129306b09d2 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sun, 7 Apr 2024 01:38:42 +0100 Subject: [PATCH 11/17] switch back to C++ 17 --- HarmonyLinkLib/CMakeLists.txt | 2 +- HarmonyLinkTest/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index c36aa39..af70787 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -42,7 +42,7 @@ endif() configure_file(include/Version.h.in Version.generated.h) # Specify the C++ standard -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) # Explicitly list source files diff --git a/HarmonyLinkTest/CMakeLists.txt b/HarmonyLinkTest/CMakeLists.txt index 3b4c7d7..5616a24 100644 --- a/HarmonyLinkTest/CMakeLists.txt +++ b/HarmonyLinkTest/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(HarmonyLinkTest) # Specify the C++ standard -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) # Automatically add all .cpp and .h/.hpp files in the src directory From 8c617f8b400b191e5eb58d583896a7b76e431294 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sat, 11 May 2024 22:45:58 +0100 Subject: [PATCH 12/17] Force cpu_model_lower to actually check if its actually lower --- HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index ecfb670..0884ca1 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -199,7 +199,7 @@ namespace HarmonyLinkLib if (const std::shared_ptr cpu_info = get_cpu_info()) { const FString cpu_model_lower = FString::to_lower(cpu_info->Model_Name); for (const auto& model : steam_deck_models) { - if (cpu_model_lower == model) { + if (cpu_model_lower == FString::to_lower(model.c_str())) { wprintf(L"Steam Deck detected by CPU model name.\n"); return true; } From e16f008dfc0f19dc4ba0b6e84f3c8485ba4d89a1 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sat, 11 May 2024 22:47:56 +0100 Subject: [PATCH 13/17] Added Steam Deck OLED support --- HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index 0884ca1..2f5d6fc 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -193,7 +193,10 @@ namespace HarmonyLinkLib } // Set of known Steam Deck CPU model names - const std::set steam_deck_models = {"amd custom apu 0405" /*, other models... */}; + const std::set steam_deck_models = { + "amd custom apu 0405" // LCD Steam Deck + "amd custom apu 0932", // OLED Steam Deck + }; // Check for Steam Deck by CPU model name if (const std::shared_ptr cpu_info = get_cpu_info()) { From 07f18771175ebd2c14de8a07919bf865c4e422c0 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Sat, 11 May 2024 23:58:06 +0100 Subject: [PATCH 14/17] Rework `is_steam_deck_detected` function to detect unknown models --- HarmonyLinkLib/CMakeLists.txt | 1 + HarmonyLinkLib/include/Enums/EDevice.h | 1 + HarmonyLinkLib/include/Enums/EPlatform.h | 1 + HarmonyLinkLib/include/Enums/ESteamDeck.h | 29 ++++++++ HarmonyLinkLib/include/Structs/FDevice.h | 6 +- .../src/Platform/IPlatformUtilities.cpp | 73 +++++++++++-------- .../src/Platform/IPlatformUtilities.h | 3 +- 7 files changed, 82 insertions(+), 32 deletions(-) create mode 100644 HarmonyLinkLib/include/Enums/ESteamDeck.h diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index af70787..a0dbaad 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -66,6 +66,7 @@ set(COMMON_INCLUDES "include/Enums/EDevice.h" "include/Enums/EPlatform.h" + "include/Enums/ESteamDeck.h" "include/FString.h" "include/HarmonyLinkLib.h" diff --git a/HarmonyLinkLib/include/Enums/EDevice.h b/HarmonyLinkLib/include/Enums/EDevice.h index 31f9bfe..f49c7ec 100644 --- a/HarmonyLinkLib/include/Enums/EDevice.h +++ b/HarmonyLinkLib/include/Enums/EDevice.h @@ -21,6 +21,7 @@ namespace HarmonyLinkLib { enum class EDevice : uint8_t { + UNKNOWN, DESKTOP, LAPTOP, HANDHELD, diff --git a/HarmonyLinkLib/include/Enums/EPlatform.h b/HarmonyLinkLib/include/Enums/EPlatform.h index 66697ee..ffa2be7 100644 --- a/HarmonyLinkLib/include/Enums/EPlatform.h +++ b/HarmonyLinkLib/include/Enums/EPlatform.h @@ -21,6 +21,7 @@ namespace HarmonyLinkLib { enum class EPlatform : uint8_t { + UNKNOWN, WINDOWS, LINUX, MAC, diff --git a/HarmonyLinkLib/include/Enums/ESteamDeck.h b/HarmonyLinkLib/include/Enums/ESteamDeck.h new file mode 100644 index 0000000..9fbad64 --- /dev/null +++ b/HarmonyLinkLib/include/Enums/ESteamDeck.h @@ -0,0 +1,29 @@ +// Copyright (c) 2024 Jordon Brooks +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma once + +#include + +// Enum class for representing different types of devices +namespace HarmonyLinkLib +{ + enum class ESteamDeck : uint8_t + { + NONE, // Device is not a steam deck + UNKNOWN, // Device is a steam deck but model cannot be determined + LCD, + OLED, + }; +} diff --git a/HarmonyLinkLib/include/Structs/FDevice.h b/HarmonyLinkLib/include/Structs/FDevice.h index 50a1a5c..b574d6a 100644 --- a/HarmonyLinkLib/include/Structs/FDevice.h +++ b/HarmonyLinkLib/include/Structs/FDevice.h @@ -18,13 +18,15 @@ #include "Enums/EDevice.h" #include "Enums/EPlatform.h" +#include "Enums/ESteamDeck.h" namespace HarmonyLinkLib { // Struct to represent a specific device with both platform and device type struct FDevice : HarmonyLinkStruct { - EPlatform platform; - EDevice device; + EPlatform platform = EPlatform::UNKNOWN; + EDevice device = EDevice::UNKNOWN; + ESteamDeck steam_deck_model = ESteamDeck::NONE; }; } diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp index 2f5d6fc..735eeab 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include "Utilities.h" #include "WineUtilities.h" @@ -169,51 +171,64 @@ namespace HarmonyLinkLib new_device.device = EDevice::LAPTOP; } - if (is_steam_deck_detected(new_device)) { + const ESteamDeck steam_deck_model = detect_steam_deck(new_device); + + if (steam_deck_model != ESteamDeck::NONE) { new_device.device = EDevice::STEAM_DECK; + new_device.steam_deck_model = steam_deck_model; } return std::make_shared(new_device); } // Helper function to check if the device is a Steam Deck - bool IPlatformUtilities::is_steam_deck_detected(const FDevice& device) { - + ESteamDeck IPlatformUtilities::detect_steam_deck(const FDevice& device) { // Check if the device is already identified as a Steam Deck - if (device.device == EDevice::STEAM_DECK) { - return true; + if (device.device == EDevice::STEAM_DECK && device.steam_deck_model != ESteamDeck::NONE) { + return device.steam_deck_model; } - // Check for Steam Deck by OS version - if (const std::shared_ptr version = get_os_version()) { - if (version->variant_id == "steamdeck" && version->name == "SteamOS") { - return true; - } + ESteamDeck steam_deck_model = ESteamDeck::NONE; + + // Retrieve and process CPU information + const std::shared_ptr cpu_info = get_cpu_info(); + if (!cpu_info) { + wprintf(L"CPU information not available.\n"); } else { - wprintf(L"OS version information not available.\n"); + // Convert the CPU model name to lower case once + FString cpu_model_lower = FString::to_lower(cpu_info->Model_Name); + + // Map of CPU models to their corresponding Steam Deck models + static const std::unordered_map model_map = { + {FString::to_lower("amd custom apu 0405"), ESteamDeck::LCD}, + {FString::to_lower("amd custom apu 0932"), ESteamDeck::OLED} + }; + + auto iterator = model_map.find(cpu_model_lower); + if (iterator != model_map.end()) { + steam_deck_model = iterator->second; + wprintf(L"Steam Deck detected by CPU model name: %hs.\n", cpu_model_lower.c_str()); + } } - // Set of known Steam Deck CPU model names - const std::set steam_deck_models = { - "amd custom apu 0405" // LCD Steam Deck - "amd custom apu 0932", // OLED Steam Deck - }; - - // Check for Steam Deck by CPU model name - if (const std::shared_ptr cpu_info = get_cpu_info()) { - const FString cpu_model_lower = FString::to_lower(cpu_info->Model_Name); - for (const auto& model : steam_deck_models) { - if (cpu_model_lower == FString::to_lower(model.c_str())) { - wprintf(L"Steam Deck detected by CPU model name.\n"); - return true; + // Check for Steam Deck by OS version only if no model has been detected yet + if (steam_deck_model == ESteamDeck::NONE) + { + if (const std::shared_ptr version = get_os_version()) + { + if (version->variant_id == "steamdeck" && version->name == "SteamOS") + { + // Use UNKNOWN if OS matches but CPU model doesn't fit known profiles + steam_deck_model = ESteamDeck::UNKNOWN; + wprintf(L"Steam Deck OS detected but model is unknown.\n"); } } - } else { - wprintf(L"CPU information not available.\n"); + else + { + wprintf(L"OS version information not available.\n"); + } } - wprintf(L"Device is not a Steam Deck.\n"); - - return false; + return steam_deck_model; } bool IPlatformUtilities::is_connected_to_ac() diff --git a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h index 420edef..e6f034f 100644 --- a/HarmonyLinkLib/src/Platform/IPlatformUtilities.h +++ b/HarmonyLinkLib/src/Platform/IPlatformUtilities.h @@ -14,6 +14,7 @@ #pragma once +#include "Enums/ESteamDeck.h" #include "Structs/FBattery.h" #include "Structs/FCPUInfo.h" #include "Structs/FDevice.h" @@ -50,7 +51,7 @@ namespace HarmonyLinkLib //virtual bool get_is_ethernet_connected() = 0; //virtual bool get_is_external_input_detected() = 0; - bool is_steam_deck_detected(const FDevice& device); + ESteamDeck detect_steam_deck(const FDevice& device); bool is_connected_to_ac(); bool is_charging(); From 2eb90cf0212c2ee29e6f639ba176f562fc4a7e2c Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Mon, 13 May 2024 17:08:47 +0100 Subject: [PATCH 15/17] Add ignores for specific build directiries --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 46fd768..0839667 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,8 @@ build/** !Images/* !.github/** !HarmonyLinkLib/** -!HarmonyLinkTest/** \ No newline at end of file +!HarmonyLinkTest/** + +# Blacklist specific build directories +linuxbuild/ +build/ From 3f7e6a6a870c6de4433eefe2e3b3108893ed9839 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Thu, 16 May 2024 14:19:48 +0100 Subject: [PATCH 16/17] Version Bump --- HarmonyLinkLib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index a0dbaad..1f7f490 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(HarmonyLinkLib VERSION 2.0.0) +project(HarmonyLinkLib VERSION 2.1.0) include(FetchContent) From d6fcb24863e122f83b96ee686ceb34e85dd84d66 Mon Sep 17 00:00:00 2001 From: Jordon Brooks Date: Thu, 16 May 2024 14:22:33 +0100 Subject: [PATCH 17/17] Added static library linking --- CMakeLists.txt | 15 ++++- HarmonyLinkLib/CMakeLists.txt | 86 ++++++++++++++++++-------- HarmonyLinkLib/Resources/Version.rc.in | 49 +++++++++++++++ HarmonyLinkLib/include/Core.h | 10 ++- HarmonyLinkLib/include/Version.h.in | 4 ++ HarmonyLinkTest/CMakeLists.txt | 49 +++++++++++---- 6 files changed, 171 insertions(+), 42 deletions(-) create mode 100644 HarmonyLinkLib/Resources/Version.rc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 16e76c5..02296e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,16 @@ +# Copyright (c) 2024 Jordon Brooks +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + cmake_minimum_required(VERSION 3.10) project(HarmonyLinkProject) @@ -57,7 +70,7 @@ add_subdirectory(HarmonyLinkTest) #add_executable(Testing ${TEST_SOURCES}) # Set HarmonyLinkTest as the default startup project -set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT HarmonyLinkTest) +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT HarmonyLinkTestShared) # Link Google Test and HarmonyLink library to the test executable #target_link_libraries(Testing gtest gtest_main gmock HarmonyLinkLib) diff --git a/HarmonyLinkLib/CMakeLists.txt b/HarmonyLinkLib/CMakeLists.txt index a0dbaad..97ec61a 100644 --- a/HarmonyLinkLib/CMakeLists.txt +++ b/HarmonyLinkLib/CMakeLists.txt @@ -1,3 +1,16 @@ +# Copyright (c) 2024 Jordon Brooks +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + cmake_minimum_required(VERSION 3.10) project(HarmonyLinkLib VERSION 2.0.0) @@ -45,6 +58,16 @@ configure_file(include/Version.h.in Version.generated.h) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) +# Define metadata variables +set(FILE_DESCRIPTION "Enhances handheld gaming with intelligent hardware recognition, dynamic adaptability, and robust API access for Windows and Linux, including Steam Deck and Wine support.") +set(INTERNAL_NAME "HarmonyLinkLib") +set(ORIGINAL_FILENAME "HarmonyLinkLib.dll") +set(PRODUCT_NAME "HarmonyLinkLib") +set(COMMENTS "") + +# Configure version.rc file for shared library +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Resources/Version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) + # Explicitly list source files set(COMMON_SOURCES "src/Platform/IPlatformUtilities.cpp" @@ -58,24 +81,19 @@ set(COMMON_SOURCES # Explicitly list include files set(COMMON_INCLUDES "include/Core.h" - "include/Structs/FBattery.h" "include/Structs/FOSVerInfo.h" "include/Structs/FDevice.h" "include/Structs/FCPUInfo.h" - "include/Enums/EDevice.h" "include/Enums/EPlatform.h" "include/Enums/ESteamDeck.h" - "include/FString.h" "include/HarmonyLinkLib.h" "include/Version.h" - "src/Platform/IPlatformUtilities.h" "src/Platform/WineUtilities.h" - - "src//Utilities.h" + "src/Utilities.h" ) set(WINDOWS_SOURCES @@ -111,41 +129,55 @@ if(WIN32) message(STATUS "Compiling for Windows...") list(APPEND LIB_SOURCES ${COMMON_SOURCES} ${WINDOWS_SOURCES}) list(APPEND LIB_INCLUDES ${COMMON_INCLUDES} ${WINDOWS_INCLUDES}) + list(APPEND SHARED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/version.rc) elseif(UNIX) - message(STATUS "Compiling for Unix-based systems...") - if(APPLE) - message(STATUS "Compiling for Mac...") - list(APPEND LIB_SOURCES ${COMMON_SOURCES} ${MAC_SOURCES}) - list(APPEND LIB_INCLUDES ${COMMON_INCLUDES} ${MAC_INCLUDES}) - else() - message(STATUS "Compiling for Linux...") - list(APPEND LIB_SOURCES ${COMMON_SOURCES} ${LINUX_SOURCES}) - list(APPEND LIB_INCLUDES ${COMMON_INCLUDES} ${LINUX_INCLUDES}) - endif() + message(STATUS "Compiling for Unix-based systems...") + if(APPLE) + message(STATUS "Compiling for Mac...") + list(APPEND LIB_SOURCES ${COMMON_SOURCES} ${MAC_SOURCES}) + list(APPEND LIB_INCLUDES ${COMMON_INCLUDES} ${MAC_INCLUDES}) + else() + message(STATUS "Compiling for Linux...") + list(APPEND LIB_SOURCES ${COMMON_SOURCES} ${LINUX_SOURCES}) + list(APPEND LIB_INCLUDES ${COMMON_INCLUDES} ${LINUX_INCLUDES}) + endif() endif() -# Add library -add_library(HarmonyLinkLib SHARED ${LIB_SOURCES} ${LIB_INCLUDES}) - -target_include_directories(HarmonyLinkLib +# Create the shared library +add_library(HarmonyLinkLibShared SHARED ${LIB_SOURCES} ${SHARED_SOURCES}) +target_include_directories(HarmonyLinkLibShared PRIVATE "${PROJECT_SOURCE_DIR}/src" PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include" ) +target_compile_definitions(HarmonyLinkLibShared PRIVATE HARMONYLINKLIB_SHARED) -target_compile_definitions(HarmonyLinkLib PRIVATE HARMONYLINKLIB_EXPORTS) +# Create the static library +add_library(HarmonyLinkLibStatic STATIC ${LIB_SOURCES}) +target_include_directories(HarmonyLinkLibStatic + PRIVATE + "${PROJECT_SOURCE_DIR}/src" + PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/include" +) +target_compile_definitions(HarmonyLinkLibStatic PRIVATE HARMONYLINKLIB_STATIC) # Set output directories for all build types foreach(TYPE IN ITEMS DEBUG RELEASE) string(TOUPPER ${TYPE} TYPE_UPPER) - set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/lib/${TYPE}/${PROJECT_NAME}" - ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/${PROJECT_NAME}" + set_target_properties(HarmonyLinkLibShared PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/HarmonyLinkLib" + LIBRARY_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/lib/${TYPE}/HarmonyLinkLib" + ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/HarmonyLinkLib" + ) + set_target_properties(HarmonyLinkLibStatic PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/HarmonyLinkLibStatic" ) endforeach() -# Link fmt library -target_link_libraries(${PROJECT_NAME} PRIVATE fmt::fmt) +# Link fmt library to both shared and static libraries +target_link_libraries(HarmonyLinkLibShared PRIVATE fmt::fmt) +target_link_libraries(HarmonyLinkLibStatic PRIVATE fmt::fmt) diff --git a/HarmonyLinkLib/Resources/Version.rc.in b/HarmonyLinkLib/Resources/Version.rc.in new file mode 100644 index 0000000..1d443f8 --- /dev/null +++ b/HarmonyLinkLib/Resources/Version.rc.in @@ -0,0 +1,49 @@ +// Copyright (c) 2024 Jordon Brooks +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@,0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L +{ + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", "N/A" + VALUE "FileDescription", "@FILE_DESCRIPTION@" + VALUE "FileVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.0" + VALUE "InternalName", "@INTERNAL_NAME@" + VALUE "OriginalFilename", "@ORIGINAL_FILENAME@" + VALUE "ProductName", "@PRODUCT_NAME@" + VALUE "ProductVersion", "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.0" + VALUE "Comments", "@COMMENTS@" + VALUE "LegalCopyright", "N/A" + VALUE "LegalTrademarks", "N/A" + VALUE "PrivateBuild", "N/A" + VALUE "SpecialBuild", "N/A" + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x409, 1200 + } +} diff --git a/HarmonyLinkLib/include/Core.h b/HarmonyLinkLib/include/Core.h index ec6ef9d..94a32d2 100644 --- a/HarmonyLinkLib/include/Core.h +++ b/HarmonyLinkLib/include/Core.h @@ -16,10 +16,14 @@ // Use a preprocessor definition to switch between export and import declarations #ifdef _WIN32 - #ifdef HARMONYLINKLIB_EXPORTS - #define HARMONYLINKLIB_API __declspec(dllexport) + #ifdef HARMONYLINKLIB_STATIC + #define HARMONYLINKLIB_API #else - #define HARMONYLINKLIB_API __declspec(dllimport) + #ifdef HARMONYLINKLIB_SHARED + #define HARMONYLINKLIB_API __declspec(dllexport) + #else + #define HARMONYLINKLIB_API __declspec(dllimport) + #endif #endif #else #define HARMONYLINKLIB_API diff --git a/HarmonyLinkLib/include/Version.h.in b/HarmonyLinkLib/include/Version.h.in index 08881c5..0802c01 100644 --- a/HarmonyLinkLib/include/Version.h.in +++ b/HarmonyLinkLib/include/Version.h.in @@ -23,3 +23,7 @@ #define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@" #define GIT_COMMIT_TIMESTAMP "@GIT_COMMIT_TIMESTAMP@" + + +#include +#include diff --git a/HarmonyLinkTest/CMakeLists.txt b/HarmonyLinkTest/CMakeLists.txt index 5616a24..949ea4f 100644 --- a/HarmonyLinkTest/CMakeLists.txt +++ b/HarmonyLinkTest/CMakeLists.txt @@ -1,3 +1,16 @@ +# Copyright (c) 2024 Jordon Brooks +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + cmake_minimum_required(VERSION 3.10) project(HarmonyLinkTest) @@ -9,23 +22,37 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) file(GLOB_RECURSE TEST_SOURCES "src/*.cpp") file(GLOB_RECURSE TEST_HEADERS "src/*.h" "src/*.hpp") -# Add executable -add_executable(HarmonyLinkTest ${TEST_SOURCES} ${TEST_HEADERS}) +# Add executable for static library +add_executable(HarmonyLinkTestStatic ${TEST_SOURCES} ${TEST_HEADERS}) +target_link_libraries(HarmonyLinkTestStatic PRIVATE HarmonyLinkLibStatic) +target_compile_definitions(HarmonyLinkTestStatic PRIVATE HARMONYLINKLIB_STATIC) -# Link the HarmonyLinkLib with HarmonyLinkTest -target_link_libraries(HarmonyLinkTest PRIVATE HarmonyLinkLib) +# Add executable for shared library +add_executable(HarmonyLinkTestShared ${TEST_SOURCES} ${TEST_HEADERS}) +target_link_libraries(HarmonyLinkTestShared PRIVATE HarmonyLinkLibShared) +target_compile_definitions(HarmonyLinkTestShared PRIVATE HARMONYLINKLIB_SHARED) # Set output directories for all build types foreach(TYPE IN ITEMS DEBUG RELEASE) string(TOUPPER ${TYPE} TYPE_UPPER) - set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/${PROJECT_NAME}" - LIBRARY_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/${PROJECT_NAME}" - ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/${PROJECT_NAME}" + + # Static test executable properties + set_target_properties(HarmonyLinkTestStatic PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/HarmonyLinkTestStatic" + LIBRARY_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/lib/${TYPE}/HarmonyLinkTestStatic" + ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/HarmonyLinkTestStatic" + ) + + # Shared test executable properties + set_target_properties(HarmonyLinkTestShared PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/bin/${TYPE}/HarmonyLinkTestShared" + LIBRARY_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/lib/${TYPE}/HarmonyLinkTestShared" + ARCHIVE_OUTPUT_DIRECTORY_${TYPE_UPPER} "${CMAKE_BINARY_DIR}/archive/${TYPE}/HarmonyLinkTestShared" ) endforeach() -add_custom_command(TARGET HarmonyLinkTest POST_BUILD +# Copy the DLL to the executable directory after building the shared test executable +add_custom_command(TARGET HarmonyLinkTestShared POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "$") + "$" + "$")