Revamp: Transition HarmonyLink to C++ with DLL support
This transformative commit marks the evolution of HarmonyLink from a Rust-based server-side application to a C++ implemented, C-compatible dynamic link library (DLL). We've restructured the codebase to streamline integration into games, eliminating the need for a server setup by end-users. Key Changes: - Introduced .gitattributes and .gitmodules to manage new dependencies and collaborations. - Replaced the GitHub workflow files with CMake configurations to support the new C++ build system. - Introduced a comprehensive set of header and implementation files defining the core functionality, platform-specific utilities, and cross-platform compatibility layers. - Removed all Rust-specific files (Cargo.toml, Cargo.lock, etc.) and references to ensure a clean transition to the C++ environment. - Implemented new testing mechanisms within HarmonyLinkTest to ensure robustness and reliability of the DLL. - Excised previous server-side components and models to focus on the DLL's direct integration into consumer applications. This update is a direct response to community feedback, showcasing our commitment to adaptability and innovation. HarmonyLink 2.0 is now more accessible, efficient, and tailored for diverse gaming environments, providing developers with an unparalleled level of hardware-software harmony. Please refer to the updated README for more details on the new structure and how to integrate HarmonyLink 2.0 into your projects.
This commit is contained in:
parent
d13fc728df
commit
6bf68eb298
60 changed files with 1629 additions and 2389 deletions
94
HarmonyLinkLib/src/HarmonyLinkLib.cpp
Normal file
94
HarmonyLinkLib/src/HarmonyLinkLib.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "HarmonyLinkLib.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "Platform/IPlatformUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
std::shared_ptr<IPlatformUtilities> PlatformUtilities = IPlatformUtilities::GetInstance();
|
||||
|
||||
bool get_is_wine()
|
||||
{
|
||||
if (!PlatformUtilities)
|
||||
{
|
||||
std::wcout << "Failed to get platform utilities!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return PlatformUtilities->is_running_under_wine();
|
||||
}
|
||||
|
||||
FCPUInfo* get_cpu_info()
|
||||
{
|
||||
if (!PlatformUtilities)
|
||||
{
|
||||
std::wcout << "Failed to get platform utilities!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FCPUInfo> cpu_info = PlatformUtilities->get_cpu_info();
|
||||
if (!cpu_info)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FCPUInfo* new_cpu_info = new FCPUInfo(*cpu_info);
|
||||
return new_cpu_info;
|
||||
}
|
||||
|
||||
FDevice* get_device_info()
|
||||
{
|
||||
if (!PlatformUtilities)
|
||||
{
|
||||
std::wcout << "Failed to get platform utilities!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FDevice> device = PlatformUtilities->get_device();
|
||||
if (!device)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FDevice* new_device = new FDevice(*device);
|
||||
return new_device;
|
||||
}
|
||||
|
||||
FOSVerInfo* get_os_version()
|
||||
{
|
||||
|
||||
|
||||
if (!PlatformUtilities)
|
||||
{
|
||||
std::wcout << "Failed to get platform utilities!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FOSVerInfo> os_version_info = PlatformUtilities->get_os_version();
|
||||
if (!os_version_info)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FOSVerInfo* new_os_info = new FOSVerInfo(*os_version_info);
|
||||
return new_os_info;
|
||||
}
|
||||
|
||||
FBattery* get_battery_status()
|
||||
{
|
||||
if (!PlatformUtilities)
|
||||
{
|
||||
std::wcout << "Failed to get platform utilities!\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FBattery> new_battery = PlatformUtilities->get_battery_status();
|
||||
if (!new_battery)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FBattery* battery = new FBattery(*new_battery);
|
||||
return battery;
|
||||
}
|
||||
}
|
122
HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp
Normal file
122
HarmonyLinkLib/src/Platform/IPlatformUtilities.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
#include "IPlatformUtilities.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "WineUtilities.h"
|
||||
#if BUILD_WINDOWS
|
||||
#include "Windows/WindowsUtilities.h"
|
||||
#elif BUILD_LINUX
|
||||
#include "Unix/Linux/LinuxUtilities.h"
|
||||
#elif BUILD_MAC
|
||||
#include "Unix/Mac/MacUtilities.h"
|
||||
#elif BUILD_UNIX
|
||||
#include "Unix/Mac/MacUtilities.h"
|
||||
#endif
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
static std::shared_ptr<IPlatformUtilities> INSTANCE = nullptr;
|
||||
|
||||
std::shared_ptr<IPlatformUtilities>& IPlatformUtilities::GetInstance()
|
||||
{
|
||||
if (!INSTANCE)
|
||||
{
|
||||
#if BUILD_WINDOWS
|
||||
INSTANCE = std::make_shared<WindowsUtilities>();
|
||||
#elif BUILD_LINUX
|
||||
INSTANCE = std::make_shared<LinuxUtilities>();
|
||||
#elif BUILD_MAC
|
||||
INSTANCE = std::make_shared<MacUtilities>();
|
||||
#elif BUILD_UNIX
|
||||
INSTANCE = std::make_shared<UnixUtilities>();
|
||||
// ... other platform checks
|
||||
#else
|
||||
std::wcout << "Platform is not supported.\n"
|
||||
#endif
|
||||
}
|
||||
|
||||
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<FDevice> IPlatformUtilities::get_device()
|
||||
{
|
||||
FDevice new_device;
|
||||
|
||||
if (is_linux())
|
||||
{
|
||||
new_device.platform = EPlatform::LINUX;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_device.platform = EPlatform::WINDOWS;
|
||||
}
|
||||
|
||||
const std::shared_ptr<FBattery> 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<FDevice>(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) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
} 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 false;
|
||||
}
|
||||
}
|
34
HarmonyLinkLib/src/Platform/IPlatformUtilities.h
Normal file
34
HarmonyLinkLib/src/Platform/IPlatformUtilities.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include "Structs/FBattery.h"
|
||||
#include "Structs/FCPUInfo.h"
|
||||
#include "Structs/FDevice.h"
|
||||
#include "Structs/FOSVerInfo.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class IPlatformUtilities {
|
||||
public:
|
||||
static std::shared_ptr<IPlatformUtilities>& GetInstance();
|
||||
|
||||
IPlatformUtilities() = default;
|
||||
IPlatformUtilities(const IPlatformUtilities& other) = default;
|
||||
IPlatformUtilities(IPlatformUtilities&& other) = default;
|
||||
IPlatformUtilities& operator=(const IPlatformUtilities& other) = default;
|
||||
IPlatformUtilities& operator=(IPlatformUtilities&& other) = default;
|
||||
virtual ~IPlatformUtilities() = default;
|
||||
|
||||
// General OS-level functions
|
||||
virtual bool is_running_under_wine();
|
||||
virtual bool is_linux();
|
||||
|
||||
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;
|
||||
|
||||
bool is_steam_deck(const FDevice& device);
|
||||
|
||||
// Add more virtual functions for other OS interactions here
|
||||
};
|
||||
}
|
24
HarmonyLinkLib/src/Platform/Unix/Linux/LinuxUtilities.cpp
Normal file
24
HarmonyLinkLib/src/Platform/Unix/Linux/LinuxUtilities.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "LinuxUtilities.h"
|
||||
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include "Platform/WineUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
std::shared_ptr<FBattery> LinuxUtilities::get_battery_status()
|
||||
{
|
||||
return WineUtilities::get_battery_status();
|
||||
}
|
||||
|
||||
std::shared_ptr<FOSVerInfo> LinuxUtilities::get_os_version()
|
||||
{
|
||||
return WineUtilities::get_linux_info();
|
||||
}
|
||||
|
||||
std::shared_ptr<FCPUInfo> LinuxUtilities::get_cpu_info()
|
||||
{
|
||||
return WineUtilities::get_cpu_info();
|
||||
}
|
||||
}
|
23
HarmonyLinkLib/src/Platform/Unix/Linux/LinuxUtilities.h
Normal file
23
HarmonyLinkLib/src/Platform/Unix/Linux/LinuxUtilities.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "Structs/FOSVerInfo.h"
|
||||
|
||||
#include "Platform/Unix/UnixUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class LinuxUtilities : public UnixUtilities {
|
||||
public:
|
||||
// Implementation for other Linux-specific functions
|
||||
std::shared_ptr<FBattery> get_battery_status() override;
|
||||
|
||||
std::shared_ptr<FOSVerInfo> get_os_version() override;
|
||||
|
||||
std::shared_ptr<FCPUInfo> get_cpu_info() override;
|
||||
|
||||
bool is_linux() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
6
HarmonyLinkLib/src/Platform/Unix/Mac/MacUtilities.cpp
Normal file
6
HarmonyLinkLib/src/Platform/Unix/Mac/MacUtilities.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "MacUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
|
||||
}
|
11
HarmonyLinkLib/src/Platform/Unix/Mac/MacUtilities.h
Normal file
11
HarmonyLinkLib/src/Platform/Unix/Mac/MacUtilities.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "Platform/Unix/UnixUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class MacUtitities : public UnixUtilities {
|
||||
public:
|
||||
// Mac-specific overrides and additional functionality
|
||||
};
|
||||
}
|
24
HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp
Normal file
24
HarmonyLinkLib/src/Platform/Unix/UnixUtilities.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "UnixUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
bool UnixUtilities::is_running_under_wine()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<FCPUInfo> UnixUtilities::get_cpu_info()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<FBattery> UnixUtilities::get_battery_status()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<FOSVerInfo> UnixUtilities::get_os_version()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
16
HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h
Normal file
16
HarmonyLinkLib/src/Platform/Unix/UnixUtilities.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "Platform/IPlatformUtilities.h"
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class UnixUtilities : public IPlatformUtilities {
|
||||
public:
|
||||
bool is_running_under_wine() override;
|
||||
|
||||
std::shared_ptr<FCPUInfo> get_cpu_info() override;
|
||||
std::shared_ptr<FBattery> get_battery_status() override;
|
||||
std::shared_ptr<FOSVerInfo> get_os_version() override;
|
||||
|
||||
// Implementation for other Unix/Linux-specific functions
|
||||
};
|
||||
}
|
81
HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp
Normal file
81
HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include "WindowsUtilities.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "Platform/WineUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
std::shared_ptr<FBattery> 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<FBattery>(result);
|
||||
}
|
||||
|
||||
std::shared_ptr<FCPUInfo> WindowsUtilities::get_cpu_info()
|
||||
{
|
||||
if (is_linux())
|
||||
{
|
||||
return WineUtilities::get_cpu_info();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<FOSVerInfo> 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<OSVERSIONINFO*>(&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<LPBYTE>(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<FOSVerInfo>(os_version);
|
||||
}
|
||||
}
|
16
HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h
Normal file
16
HarmonyLinkLib/src/Platform/Windows/WindowsUtilities.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "Platform/IPlatformUtilities.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class WindowsUtilities : public IPlatformUtilities
|
||||
{
|
||||
public:
|
||||
std::shared_ptr<FBattery> get_battery_status() override;
|
||||
|
||||
std::shared_ptr<FCPUInfo> get_cpu_info() override;
|
||||
|
||||
std::shared_ptr<FOSVerInfo> get_os_version() override;
|
||||
};
|
||||
}
|
202
HarmonyLinkLib/src/Platform/WineUtilities.cpp
Normal file
202
HarmonyLinkLib/src/Platform/WineUtilities.cpp
Normal file
|
@ -0,0 +1,202 @@
|
|||
#include "WineUtilities.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <filesystem>
|
||||
|
||||
#ifdef BUILD_WINDOWS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
bool force_detect_wine = false;
|
||||
|
||||
std::shared_ptr<HarmonyLinkLib::FBattery> HarmonyLinkLib::WineUtilities::get_battery_status()
|
||||
{
|
||||
std::string append;
|
||||
if (is_wine_present())
|
||||
{
|
||||
append = "Z:";
|
||||
}
|
||||
|
||||
FBattery result = {};
|
||||
for (int i = 0; i <= 9; ++i) {
|
||||
if (std::string bat_path = append + "/sys/class/power_supply/BAT" + std::to_string(i); std::filesystem::exists(bat_path)) {
|
||||
result.has_battery = true;
|
||||
|
||||
std::ifstream status_file(bat_path + "/status");
|
||||
std::string status;
|
||||
if (status_file.is_open() && std::getline(status_file, status)) {
|
||||
if (status == "Charging" || status == "AC") {
|
||||
result.is_connected_to_ac = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::ifstream capacity_file(bat_path + "/capacity");
|
||||
if (capacity_file.is_open() && std::getline(capacity_file, status)) {
|
||||
result.battery_percent = static_cast<uint8_t>(std::stoi(status));
|
||||
break; // assuming you only need data from the first battery found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_shared<FBattery>(result);
|
||||
}
|
||||
|
||||
std::shared_ptr<FCPUInfo> WineUtilities::get_cpu_info()
|
||||
{
|
||||
std::wcout << "Getting cpu info\n";
|
||||
|
||||
std::string append;
|
||||
if (is_wine_present())
|
||||
{
|
||||
append = "Z:";
|
||||
}
|
||||
|
||||
FCPUInfo cpu_info;
|
||||
|
||||
std::ifstream file(append + "/proc/cpuinfo");
|
||||
std::unordered_map<HarmonyLinkLib::FString, HarmonyLinkLib::FString> hashmap;
|
||||
|
||||
if (file) {
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
std::istringstream line_stream(line);
|
||||
std::string key, value;
|
||||
if (std::getline(line_stream, key, ':')) {
|
||||
key.erase(key.find_last_not_of(" \t") + 1); // Trim trailing whitespace from key
|
||||
if (std::getline(line_stream, value)) {
|
||||
value.erase(0, value.find_first_not_of(" \t")); // Trim leading whitespace from value
|
||||
|
||||
// Aggregate flags
|
||||
if (key == "flags") {
|
||||
std::istringstream flag_stream(value);
|
||||
std::string flag;
|
||||
while (flag_stream >> flag) {
|
||||
flag.erase(flag.find_last_not_of(" \t") + 1); // Trim trailing whitespace from flag
|
||||
cpu_info.Flags.insert(HarmonyLinkLib::FString(flag));
|
||||
//printf("Flag detected: %s\n", flag.c_str());
|
||||
}
|
||||
} else {
|
||||
hashmap[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Now you can access the values using the keys:
|
||||
cpu_info.VendorID = hashmap["vendor_id"];
|
||||
cpu_info.Model_Name = hashmap["model name"];
|
||||
|
||||
try {
|
||||
cpu_info.Physical_Cores = std::stoi(hashmap["cpu cores"].c_str());
|
||||
} catch (const std::invalid_argument& ia) {
|
||||
std::wcerr << "Invalid argument: " << ia.what() << '\n';
|
||||
} catch (const std::out_of_range& oor) {
|
||||
std::wcerr << "Out of Range error: " << oor.what() << '\n';
|
||||
}
|
||||
|
||||
cpu_info.Logical_Cores = (cpu_info.Flags.find("ht") != cpu_info.Flags.end()) ? cpu_info.Physical_Cores * 2 : cpu_info.Physical_Cores;
|
||||
|
||||
return std::make_shared<FCPUInfo>(cpu_info);
|
||||
}
|
||||
|
||||
std::shared_ptr<FOSVerInfo> WineUtilities::get_linux_info()
|
||||
{
|
||||
std::string append;
|
||||
if (is_wine_present())
|
||||
{
|
||||
append = "Z:";
|
||||
}
|
||||
|
||||
FOSVerInfo os_info;
|
||||
|
||||
std::ifstream file(append + "/etc/os-release");
|
||||
std::unordered_map<HarmonyLinkLib::FString, HarmonyLinkLib::FString> hashmap;
|
||||
|
||||
if (file) {
|
||||
std::string line;
|
||||
while (std::getline(file, line)) {
|
||||
std::istringstream lineStream(line);
|
||||
std::string key, value;
|
||||
if (std::getline(lineStream, key, '=')) {
|
||||
if (std::getline(lineStream, value)) {
|
||||
// Remove leading and trailing whitespace
|
||||
size_t firstNonSpace = value.find_first_not_of(" \t");
|
||||
size_t lastNonSpace = value.find_last_not_of(" \t");
|
||||
if (firstNonSpace != std::string::npos && lastNonSpace != std::string::npos) {
|
||||
value = value.substr(firstNonSpace, lastNonSpace - firstNonSpace + 1);
|
||||
} else {
|
||||
value.clear(); // If value is all whitespace, make it empty
|
||||
}
|
||||
|
||||
// Check for double quotes and remove them
|
||||
if (!value.empty() && value.front() == '"' && value.back() == '"') {
|
||||
value = value.substr(1, value.length() - 2);
|
||||
}
|
||||
|
||||
hashmap[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
// Now you can access the values using the keys:
|
||||
os_info.name = hashmap["NAME"];
|
||||
os_info.id = hashmap["ID"];
|
||||
os_info.version_id = hashmap["VERSION_ID"];
|
||||
os_info.version_codename = hashmap["VERSION_CODENAME"];
|
||||
os_info.pretty_name = hashmap["PRETTY_NAME"];
|
||||
|
||||
try {
|
||||
os_info.version = std::stoi(hashmap["VERSION"].c_str());
|
||||
} catch (const std::invalid_argument& ia) {
|
||||
std::cerr << "Invalid argument: " << ia.what() << '\n';
|
||||
// Handle the error, perhaps by setting a default value or leaving the field unchanged
|
||||
} catch (const std::out_of_range& oor) {
|
||||
std::cerr << "Out of Range error: " << oor.what() << '\n';
|
||||
// Handle the error, perhaps by setting a default value or leaving the field unchanged
|
||||
}
|
||||
|
||||
return std::make_shared<FOSVerInfo>(os_info);
|
||||
}
|
||||
|
||||
bool WineUtilities::is_wine_present()
|
||||
{
|
||||
static bool isWineCached = false; // Static variable to store the cached result
|
||||
static bool isWine = false; // Static variable to indicate if the caching has been done
|
||||
|
||||
if (!isWineCached)
|
||||
{
|
||||
// Only detect wine if force_detect_wine is true or if we haven't cached the result yet
|
||||
#ifdef BUILD_WINDOWS
|
||||
std::wcout << "Detecting wine...\n";
|
||||
bool HasFound = GetProcAddress(GetModuleHandle("ntdll.dll"), "wine_get_version") != nullptr;
|
||||
|
||||
if (!HasFound)
|
||||
HasFound = GetProcAddress(GetModuleHandle("ntdll.dll"), "proton_get_version") != nullptr;
|
||||
|
||||
wprintf(L"wine %s found\n", HasFound ? L"has been" : L"not");
|
||||
|
||||
isWine = HasFound; // Cache the result
|
||||
#else
|
||||
isWine = false; // In non-Windows builds, always set isWine to false
|
||||
#endif
|
||||
isWineCached = true; // Indicate that the result is now cached
|
||||
}
|
||||
|
||||
return isWine; // Return the cached result
|
||||
}
|
||||
|
||||
bool WineUtilities::force_detect_wine_presence()
|
||||
{
|
||||
force_detect_wine = true;
|
||||
return is_wine_present();
|
||||
}
|
||||
}
|
46
HarmonyLinkLib/src/Platform/WineUtilities.h
Normal file
46
HarmonyLinkLib/src/Platform/WineUtilities.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include "Structs/FBattery.h"
|
||||
#include "Structs/FCPUInfo.h"
|
||||
#include "Structs/FOSVerInfo.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
class WineUtilities
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<FBattery> get_battery_status();
|
||||
|
||||
static std::shared_ptr<FCPUInfo> get_cpu_info();
|
||||
|
||||
/**
|
||||
* @brief Retrieves Linux OS version information from a specified file.
|
||||
*
|
||||
* This function parses a file (typically a Linux OS release file) at the given location
|
||||
* to extract operating system version information. It reads key-value pairs from the file,
|
||||
* processes them to handle whitespace and quotes, and then stores them in an FOSVerInfo
|
||||
* structure. If the file location is invalid or the file cannot be opened, it returns an
|
||||
* empty FOSVerInfo structure. Errors during parsing, such as invalid format or out of range
|
||||
* values, are handled with exception catching. In Windows builds where Wine is detected,
|
||||
* this function can use the file location 'Z:/etc/os-release' to retrieve the underlying
|
||||
* Linux system information.
|
||||
*
|
||||
* @param file_location The location of the file containing OS version information.
|
||||
* @return A shared pointer to a structure containing the parsed OS version information.
|
||||
*/
|
||||
static std::shared_ptr<FOSVerInfo> get_linux_info();
|
||||
|
||||
/**
|
||||
* @brief Detects the presence of Wine or Proton in Windows builds.
|
||||
*
|
||||
* This function assesses if the application is running under Wine or Proton by
|
||||
* querying specific functions in the 'ntdll.dll' module. It is only active in
|
||||
* Windows builds, returning false for non-Windows builds.
|
||||
*
|
||||
* @return bool True if Wine or Proton is detected, false otherwise.
|
||||
*/
|
||||
static bool is_wine_present();
|
||||
|
||||
static bool force_detect_wine_presence();
|
||||
};
|
||||
}
|
1
HarmonyLinkLib/src/Version.cpp
Normal file
1
HarmonyLinkLib/src/Version.cpp
Normal file
|
@ -0,0 +1 @@
|
|||
#include "Version.h"
|
49
HarmonyLinkLib/src/dllmain.cpp
Normal file
49
HarmonyLinkLib/src/dllmain.cpp
Normal file
|
@ -0,0 +1,49 @@
|
|||
// Copyright (C) 2024 Jordon Brooks
|
||||
|
||||
#include <iostream>
|
||||
#include "Version.h"
|
||||
|
||||
namespace HarmonyLinkLib
|
||||
{
|
||||
void HarmonyLinkInit()
|
||||
{
|
||||
std::wcout << "HarmonyLink V" << version::ToString().c_str() << " Copyright (C) 2023 Jordon Brooks\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if BUILD_WINDOWS
|
||||
#include <windows.h>
|
||||
|
||||
// Standard DLL entry point
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
// Code to run when the DLL is loaded
|
||||
HarmonyLinkLib::HarmonyLinkInit();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
// Code to run when a thread is created during the DLL's lifetime
|
||||
case DLL_THREAD_DETACH:
|
||||
// Code to run when a thread ends normally.
|
||||
case DLL_PROCESS_DETACH:
|
||||
// Code to run when the DLL is unloaded
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TRUE; // Successful DLL_PROCESS_ATTACH.
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILD_UNIX
|
||||
__attribute__((constructor))
|
||||
static void onLibraryLoad() {
|
||||
// Code to run when the library is loaded
|
||||
HarmonyLinkLib::HarmonyLinkInit();
|
||||
}
|
||||
|
||||
__attribute__((destructor))
|
||||
static void onLibraryUnload() {
|
||||
// Code to run when the library is unloaded
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue