Merge branch 'release/V2.1' into Stable
This commit is contained in:
commit
ffe5063d32
22 changed files with 767 additions and 203 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -17,3 +17,7 @@ build/**
|
|||
!.github/**
|
||||
!HarmonyLinkLib/**
|
||||
!HarmonyLinkTest/**
|
||||
|
||||
# Blacklist specific build directories
|
||||
linuxbuild/
|
||||
build/
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
@ -14,6 +27,8 @@ else()
|
|||
message(STATUS "Building with unspecified build type")
|
||||
endif()
|
||||
|
||||
add_compile_definitions($<$<CONFIG:Debug>:DEBUG_MODE>)
|
||||
|
||||
#set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Platform-specific definitions
|
||||
|
@ -55,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)
|
||||
|
|
|
@ -1,5 +1,36 @@
|
|||
# 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)
|
||||
project(HarmonyLinkLib VERSION 2.1.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)
|
||||
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE TRUE)
|
||||
|
||||
# Find the current Git branch and the last commit timestamp
|
||||
find_package(Git QUIET)
|
||||
|
@ -27,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"
|
||||
|
@ -34,6 +75,7 @@ set(COMMON_SOURCES
|
|||
"src/Version.cpp"
|
||||
"src/dllmain.cpp"
|
||||
"src/Platform/WineUtilities.cpp"
|
||||
"src/Utilities.cpp"
|
||||
)
|
||||
|
||||
# Explicitly list include files
|
||||
|
@ -43,16 +85,15 @@ set(COMMON_INCLUDES
|
|||
"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"
|
||||
)
|
||||
|
||||
set(WINDOWS_SOURCES
|
||||
|
@ -88,6 +129,7 @@ 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)
|
||||
|
@ -101,29 +143,41 @@ elseif(UNIX)
|
|||
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)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
target_compile_definitions(HarmonyLinkLib PRIVATE "DEBUG_MODE")
|
||||
endif()
|
||||
# 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 to both shared and static libraries
|
||||
target_link_libraries(HarmonyLinkLibShared PRIVATE fmt::fmt)
|
||||
target_link_libraries(HarmonyLinkLibStatic PRIVATE fmt::fmt)
|
||||
|
|
49
HarmonyLinkLib/Resources/Version.rc.in
Normal file
49
HarmonyLinkLib/Resources/Version.rc.in
Normal file
|
@ -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 <windows.h>
|
||||
#include <winver.h>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
|
@ -16,11 +16,15 @@
|
|||
|
||||
// Use a preprocessor definition to switch between export and import declarations
|
||||
#ifdef _WIN32
|
||||
#ifdef HARMONYLINKLIB_EXPORTS
|
||||
#ifdef HARMONYLINKLIB_STATIC
|
||||
#define HARMONYLINKLIB_API
|
||||
#else
|
||||
#ifdef HARMONYLINKLIB_SHARED
|
||||
#define HARMONYLINKLIB_API __declspec(dllexport)
|
||||
#else
|
||||
#define HARMONYLINKLIB_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define HARMONYLINKLIB_API
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
enum class EDevice : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
DESKTOP,
|
||||
LAPTOP,
|
||||
HANDHELD,
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
enum class EPlatform : uint8_t
|
||||
{
|
||||
UNKNOWN,
|
||||
WINDOWS,
|
||||
LINUX,
|
||||
MAC,
|
||||
|
|
29
HarmonyLinkLib/include/Enums/ESteamDeck.h
Normal file
29
HarmonyLinkLib/include/Enums/ESteamDeck.h
Normal file
|
@ -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 <cstdint>
|
||||
|
||||
// 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,
|
||||
};
|
||||
}
|
|
@ -46,6 +46,10 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
extern "C" HARMONYLINKLIB_API bool get_is_wine();
|
||||
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,3 +23,7 @@
|
|||
|
||||
#define GIT_BRANCH_NAME "@GIT_BRANCH_NAME@"
|
||||
#define GIT_COMMIT_TIMESTAMP "@GIT_COMMIT_TIMESTAMP@"
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <winver.h>
|
||||
|
|
|
@ -32,6 +32,28 @@ 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();
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
|
||||
#include "IPlatformUtilities.h"
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Utilities.h"
|
||||
|
||||
#include "WineUtilities.h"
|
||||
#if BUILD_WINDOWS
|
||||
|
@ -66,6 +70,83 @@ bool IPlatformUtilities::is_linux()
|
|||
#endif
|
||||
}
|
||||
|
||||
bool IPlatformUtilities::is_steam_deck()
|
||||
{
|
||||
const std::shared_ptr<FDevice> 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 = 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<FDevice> 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;
|
||||
|
||||
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(fmt::format("Score: {}/{}", score, FINAL_TARGET_DETECTION_SCORE).c_str());
|
||||
|
||||
return score >= FINAL_TARGET_DETECTION_SCORE;
|
||||
}
|
||||
|
||||
std::shared_ptr<FDevice> IPlatformUtilities::get_device()
|
||||
{
|
||||
FDevice new_device;
|
||||
|
@ -90,47 +171,75 @@ std::shared_ptr<FDevice> IPlatformUtilities::get_device()
|
|||
new_device.device = EDevice::LAPTOP;
|
||||
}
|
||||
|
||||
if (is_steam_deck(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<FDevice>(new_device);
|
||||
}
|
||||
|
||||
// Helper function to check if the device is a Steam Deck
|
||||
bool IPlatformUtilities::is_steam_deck(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<FOSVerInfo> 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<FCPUInfo> cpu_info = get_cpu_info();
|
||||
if (!cpu_info) {
|
||||
wprintf(L"CPU information not available.\n");
|
||||
} else {
|
||||
// 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<FString, ESteamDeck> 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());
|
||||
}
|
||||
}
|
||||
|
||||
// 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<FOSVerInfo> 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"OS version information not available.\n");
|
||||
}
|
||||
|
||||
// Set of known Steam Deck CPU model names
|
||||
const std::set<std::string> steam_deck_models = {"amd custom apu 0405" /*, other models... */};
|
||||
|
||||
// Check for Steam Deck by CPU model name
|
||||
if (const std::shared_ptr<FCPUInfo> 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 steam_deck_model;
|
||||
}
|
||||
|
||||
return false;
|
||||
bool IPlatformUtilities::is_connected_to_ac()
|
||||
{
|
||||
const std::shared_ptr<FBattery> battery = get_battery_status();
|
||||
return battery && battery->is_connected_to_ac;
|
||||
}
|
||||
|
||||
bool IPlatformUtilities::is_charging()
|
||||
{
|
||||
const std::shared_ptr<FBattery> battery = get_battery_status();
|
||||
return battery && battery->has_battery && battery->is_connected_to_ac;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Enums/ESteamDeck.h"
|
||||
#include "Structs/FBattery.h"
|
||||
#include "Structs/FCPUInfo.h"
|
||||
#include "Structs/FDevice.h"
|
||||
|
@ -35,13 +36,24 @@ 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<FDevice> get_device();
|
||||
virtual std::shared_ptr<FCPUInfo> get_cpu_info() = 0;
|
||||
virtual std::shared_ptr<FBattery> get_battery_status() = 0;
|
||||
virtual std::shared_ptr<FOSVerInfo> get_os_version() = 0;
|
||||
virtual bool get_is_external_monitor_connected() = 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;
|
||||
|
||||
bool is_steam_deck(const FDevice& device);
|
||||
ESteamDeck detect_steam_deck(const FDevice& device);
|
||||
bool is_connected_to_ac();
|
||||
bool is_charging();
|
||||
|
||||
// Add more virtual functions for other OS interactions here
|
||||
};
|
||||
|
|
|
@ -18,21 +18,55 @@ namespace HarmonyLinkLib
|
|||
{
|
||||
bool UnixUtilities::is_running_under_wine()
|
||||
{
|
||||
std::wcout << "This feature is not supported on unix systems yet.\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<FCPUInfo> UnixUtilities::get_cpu_info()
|
||||
{
|
||||
std::wcout << "This feature is not supported on unix systems yet.\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<FBattery> UnixUtilities::get_battery_status()
|
||||
{
|
||||
std::wcout << "This feature is not supported on unix systems yet.\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<FOSVerInfo> 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_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;
|
||||
}
|
||||
|
||||
bool UnixUtilities::get_external_controller_detected()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
@ -25,6 +27,16 @@ namespace HarmonyLinkLib
|
|||
std::shared_ptr<FBattery> get_battery_status() override;
|
||||
std::shared_ptr<FOSVerInfo> get_os_version() override;
|
||||
|
||||
bool get_is_external_monitor_connected() 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
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
#include <sstream>
|
||||
#include <Windows.h>
|
||||
|
||||
#include <XInput.h>
|
||||
#pragma comment(lib, "XInput.lib")
|
||||
|
||||
#include "Platform/WineUtilities.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
|
@ -92,4 +96,82 @@ std::shared_ptr<FOSVerInfo> WindowsUtilities::get_os_version()
|
|||
|
||||
return std::make_shared<FOSVerInfo>(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_keyboard_detected()
|
||||
{
|
||||
UINT n_devices;
|
||||
std::vector<RAWINPUTDEVICELIST> 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_TYPEKEYBOARD;
|
||||
});
|
||||
}
|
||||
|
||||
bool WindowsUtilities::get_mouse_detected()
|
||||
{
|
||||
UINT n_devices;
|
||||
std::vector<RAWINPUTDEVICELIST> 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()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,5 +26,15 @@ namespace HarmonyLinkLib
|
|||
std::shared_ptr<FCPUInfo> get_cpu_info() override;
|
||||
|
||||
std::shared_ptr<FOSVerInfo> get_os_version() override;
|
||||
|
||||
bool get_is_external_monitor_connected() 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;
|
||||
};
|
||||
}
|
||||
|
|
53
HarmonyLinkLib/src/Utilities.cpp
Normal file
53
HarmonyLinkLib/src/Utilities.cpp
Normal file
|
@ -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 <iostream>
|
||||
|
||||
#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
|
||||
}
|
30
HarmonyLinkLib/src/Utilities.h
Normal file
30
HarmonyLinkLib/src/Utilities.h
Normal file
|
@ -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);
|
||||
};
|
||||
}
|
|
@ -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
|
||||
"$<TARGET_FILE:HarmonyLinkLib>"
|
||||
"$<TARGET_FILE_DIR:HarmonyLinkTest>")
|
||||
"$<TARGET_FILE:HarmonyLinkLibShared>"
|
||||
"$<TARGET_FILE_DIR:HarmonyLinkTestShared>")
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue