diff --git a/openVulkanoCpp/Host/MacOS/SystemInfo.mm b/openVulkanoCpp/Host/MacOS/SystemInfo.mm index 4e37d0f..ad149f1 100644 --- a/openVulkanoCpp/Host/MacOS/SystemInfo.mm +++ b/openVulkanoCpp/Host/MacOS/SystemInfo.mm @@ -10,6 +10,7 @@ #include #include +#include #import #import @@ -81,12 +82,14 @@ namespace OpenVulkano std::string SystemInfo::GetDeviceModelName() { - return ""; //TODO + struct utsname systemInfo; + uname(&systemInfo); + return systemInfo.machine; } std::string SystemInfo::GetOsName() { - return ""; //TODO + return "MacOS"; } OsVersion SystemInfo::GetOsVersion() diff --git a/openVulkanoCpp/Host/SystemInfo.hpp b/openVulkanoCpp/Host/SystemInfo.hpp index b480d09..2825457 100644 --- a/openVulkanoCpp/Host/SystemInfo.hpp +++ b/openVulkanoCpp/Host/SystemInfo.hpp @@ -38,6 +38,8 @@ namespace OpenVulkano static std::string GetUserName(); static std::string GetHostName(); + + // Device name as given by the user static std::string GetDeviceName(); static std::string GetDeviceVendorName(); static std::string GetDeviceModelName(); diff --git a/openVulkanoCpp/Host/iOS/IosDeviceNameDecoder.hpp b/openVulkanoCpp/Host/iOS/IosDeviceNameDecoder.hpp new file mode 100644 index 0000000..fb02ed5 --- /dev/null +++ b/openVulkanoCpp/Host/iOS/IosDeviceNameDecoder.hpp @@ -0,0 +1,154 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Base/Logger.hpp" +#include "Data/Containers/String.hpp" +#include +#include +#include + +namespace OpenVulkano +{ + namespace + { + std::tuple SplitAppleModelComponents(std::string_view input) + { + size_t commaPos = input.rfind(','); + + // Find the boundary between text and number + size_t numberStart = commaPos - 1; + while (numberStart > 0 && std::isdigit(input[numberStart - 1])) { --numberStart; } + + if (numberStart < 1 || commaPos == std::string_view::npos) return { input, -1, -1 }; + + std::string_view beforeNumber = input.substr(0, numberStart); + std::string_view number = input.substr(numberStart, commaPos - numberStart); + std::string_view afterComma = input.substr(commaPos + 1); + + int major = -1, minor = -1; + c4::from_chars(c4::csubstr(number.begin(), number.length()), &major); + c4::from_chars(c4::csubstr(afterComma.begin(), afterComma.length()), &minor); + + return { beforeNumber, major, minor }; + } + + std::string DecodeIPhoneName(int major, int minor) + { + uint32_t number = std::max(major - 1, 1); + std::string suffix; + switch(major) + { + case 1: if (minor == 1) number = 1; else if (minor == 2) { number = 3; suffix = "G"; } break; + case 2: number = 3; suffix = "GS"; + case 4: suffix = "s"; //fallthrough + case 3: number = 4; break; + case 6: suffix = "s"; //fallthrough + case 5: number = 5; if(minor > 2) suffix = "c"; break; + case 7: if (minor == 1) suffix = " Plus"; break; + case 8: if (minor == 4) return "iPhone SE"; + number = 6; suffix = "s"; + if (minor == 2) suffix += " Plus"; break; + case 9: number = 7; if ((minor & 1) == 0) suffix = " Plus"; break; + case 10: if (minor < 3) { number = 8; if (minor == 2) suffix = " Plus"; } else return "iPhone X"; break; + case 11: { switch (minor) { + case 2: return "iPhone XS"; + case 8: return "iPhone XR"; + case 4: case 6: return "iPhone XS Max"; + } break; } + case 12: + if (minor == 8) return "iPhone SE (2nd generation)"; + if (minor > 2) suffix = " Pro"; if (minor > 4) suffix += " Max"; break; + case 13: + if (minor == 1) { suffix = " Mini"; break; } + if (minor > 2) suffix = " Pro"; if (minor == 4) suffix += " Max"; break; + case 14: if (minor == 6) return "iPhone SE (3nd generation)"; + if (minor == 2) suffix = " Pro"; if (minor == 3) suffix = " Pro Max"; + if (minor == 4) suffix = " Mini"; if (minor > 6) number = 14; if (minor == 8) suffix = " Plus"; + break; + case 15: + if (minor == 2) suffix = " Pro"; else if (minor == 3) suffix = " Pro Max"; + else if (minor > 3) number = 15; if (minor == 5) suffix = " Plus"; break; + case 16: suffix = " Pro"; if (minor == 2) suffix += " Max"; break; + case 17: if (minor == 1) suffix = " Pro"; else if (minor == 2) suffix = " Pro Max"; else if (minor == 4) suffix = " Plus"; break; + } + return fmt::format("iPhone {}{}", number, suffix); + } + + std::string DecodeIPadName(int major, int minor) + { + std::string type = "unknown"; + uint32_t gen = major * 1000 + minor; + std::map, std::pair> options = { + {{1, 1}, {"", 1}}, {{1, 2}, {"", 1}}, {{1, 3}, {"", 1}}, + {{2, 1}, {"", 2}}, {{2, 2}, {"", 2}}, {{2, 3}, {"", 2}}, {{2, 4}, {"", 2}}, + {{3, 1}, {"", 3}}, {{3, 2}, {"", 3}}, {{3, 3}, {"", 3}}, + {{3, 4}, {"", 4}}, {{3, 5}, {"", 4}}, {{3, 6}, {"", 4}}, + {{6, 11}, {"", 5}}, {{6, 12}, {"", 5}}, + {{7, 5}, {"", 6}}, {{7, 6}, {"", 6}}, + {{7, 11}, {"", 7}}, {{7, 12}, {"", 7}}, + {{11, 6}, {"", 8}}, {{11, 7}, {"", 8}}, + {{12, 1}, {"", 9}}, {{12, 2}, {"", 9}}, + {{13, 18}, {"", 10}}, {{13, 19}, {"", 10}}, + {{2, 5}, {"Mini", 1}}, {{2, 6}, {"Mini", 1}}, {{2, 7}, {"Mini", 1}}, + {{4, 4}, {"Mini", 2}}, {{4, 5}, {"Mini", 2}}, {{4, 6}, {"Mini", 2}}, + {{4, 7}, {"Mini", 3}}, {{4, 8}, {"Mini", 3}}, {{4, 9}, {"Mini", 3}}, + {{5, 1}, {"Mini", 4}}, {{5, 2}, {"Mini", 4}}, + {{11, 1}, {"Mini", 5}}, {{11, 2}, {"Mini", 5}}, + {{14, 1}, {"Mini", 6}}, {{14, 2}, {"Mini", 6}}, + {{4, 1}, {"Air", 1}}, {{4, 2}, {"Air", 1}}, {{4, 3}, {"Air", 1}}, + {{5, 3}, {"Air", 2}}, {{5, 4}, {"Air", 2}}, + {{11, 3}, {"Air", 3}}, {{11, 4}, {"Air", 3}}, + {{13, 1}, {"Air", 4}}, {{13, 2}, {"Air", 4}}, + {{13, 16}, {"Air", 5}}, {{13, 17}, {"Air", 5}}, + {{6, 7}, {"Pro 12.9\"", 1}}, {{6, 8}, {"Pro 12.9\"", 1}}, + {{7, 1}, {"Pro 12.9\"", 2}}, {{7, 2}, {"Pro 12.9\"", 2}}, + {{8, 5}, {"Pro 12.9\"", 3}}, {{8, 6}, {"Pro 12.9\"", 3}}, {{8, 7}, {"Pro 12.9\"", 3}}, {{8, 8}, {"Pro 12.9\"", 3}}, + {{8, 11}, {"Pro 12.9\"", 4}}, {{8, 12}, {"Pro 12.9\"", 4}}, + {{13, 8}, {"Pro 12.9\"", 5}}, {{13, 9}, {"Pro 12.9\"", 5}}, {{13, 10}, {"Pro 12.9\"", 5}}, {{13, 11}, {"Pro 12.9\"", 5}}, + {{14, 5}, {"Pro 12.9\"", 6}}, {{14, 6}, {"Pro 12.9\"", 6}}, + {{16, 5}, {"Pro 12.9\"", 7}}, {{16, 6}, {"Pro 12.9\"", 7}}, + {{6, 3}, {"Pro 9.7\"", 1}}, {{6, 4}, {"Pro 9.7\"", 1}}, + {{7, 3}, {"Pro 10.5\"", 1}}, {{7, 4}, {"Pro 10.5\"", 1}}, + {{8, 1}, {"Pro 11\"", 1}}, {{8, 2}, {"Pro 11\"", 1}}, {{8, 3}, {"Pro 11\"", 1}}, {{8, 4}, {"Pro 11\"", 1}}, + {{8, 9}, {"Pro 11\"", 2}}, {{8, 10}, {"Pro 11\"", 2}}, + {{13, 4}, {"Pro 11\"", 3}}, {{13, 5}, {"Pro 11\"", 3}}, {{13, 6}, {"Pro 11\"", 3}}, {{13, 7}, {"Pro 11\"", 3}}, + {{14, 3}, {"Pro 11\"", 4}}, {{14, 4}, {"Pro 11\"", 4}}, + {{16, 3}, {"Pro 11\"", 5}}, {{16, 4}, {"Pro 11\"", 5}}, + }; + auto iter = options.find({major, minor}); + if (iter != options.end()) + { + type = iter->second.first; + gen = iter->second.second; + } + else + { + spdlog::warn("Could not decode iPad identifier iPad{},{}", major, minor); + } + return fmt::format("iPad {} ({}{} generation)", type, gen, String::GetOrdinal(gen)); + } + + std::string DecodeModelString(const std::string& model) + { + if (model == "i386" || model == "x86_64") return "Simulator"; + auto [type, major, minor] = SplitAppleModelComponents(model); + if (type == "iPhone") return DecodeIPhoneName(major, minor); + else if (type == "iPad") return DecodeIPadName(major, minor); + else if (type == "iPod") + { + if (major == 7) major = 6; else if (major == 9) major = 7; + return fmt::format("iPod touch ({}{} generation)", major, String::GetOrdinal(major)); + } + else + { + spdlog::warn("Could not decode identifier {}", model); + } + return ""; + } + } +} diff --git a/openVulkanoCpp/Host/iOS/SystemInfo.mm b/openVulkanoCpp/Host/iOS/SystemInfo.mm index e6107c4..a83d6a3 100644 --- a/openVulkanoCpp/Host/iOS/SystemInfo.mm +++ b/openVulkanoCpp/Host/iOS/SystemInfo.mm @@ -6,10 +6,12 @@ #include "Host/SystemInfo.hpp" #include "Base/Logger.hpp" +#include "IosDeviceNameDecoder.hpp" #include #include #include +#include #import #import @@ -83,7 +85,15 @@ namespace OpenVulkano std::string SystemInfo::GetDeviceModelName() { - return [[[UIDevice currentDevice] model] UTF8String]; + static std::string modelName; + if (modelName.empty()) + { + struct utsname systemInfo; + uname(&systemInfo); + modelName = DecodeModelString(systemInfo.machine); + if (modelName.empty()) modelName = [[[UIDevice currentDevice] model] UTF8String]; + } + return modelName; } std::string SystemInfo::GetOsName() @@ -91,7 +101,7 @@ namespace OpenVulkano return [[[UIDevice currentDevice] systemName] UTF8String]; } - OsVersion SystemInfo::GetOsVersion() + OsVersion SystemInfo::GetOsVersion() { NSOperatingSystemVersion osVersion = [NSProcessInfo processInfo].operatingSystemVersion; return { static_cast(osVersion.majorVersion), static_cast(osVersion.minorVersion), static_cast(osVersion.patchVersion), 0 }; @@ -99,9 +109,7 @@ namespace OpenVulkano std::string SystemInfo::GetOsNameHumanReadable() { - std::stringstream name; - name << GetOsName() << ' ' << GetOsVersion().major; - return name.str(); + return fmt::format("{} {}", GetOsName(), GetOsVersion().major); } DeviceType SystemInfo::GetDeviceType()