diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/settings.h | 3 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 36 | ||||
| -rw-r--r-- | src/core/network/network.cpp | 43 | ||||
| -rw-r--r-- | src/core/network/network.h | 5 | ||||
| -rw-r--r-- | src/core/network/network_interface.cpp | 113 | ||||
| -rw-r--r-- | src/core/network/network_interface.h | 25 | ||||
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.h | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure.ui | 10 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_network.cpp (renamed from src/yuzu/configuration/configure_service.cpp) | 38 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_network.h (renamed from src/yuzu/configuration/configure_service.h) | 12 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_network.ui (renamed from src/yuzu/configuration/configure_service.ui) | 63 |
15 files changed, 278 insertions, 90 deletions
diff --git a/src/common/settings.h b/src/common/settings.h index a88ee045d..e1ae72c7a 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -433,9 +433,10 @@ struct Values { | |||
| 433 | BasicSetting<std::string> log_filter{"*:Info", "log_filter"}; | 433 | BasicSetting<std::string> log_filter{"*:Info", "log_filter"}; |
| 434 | BasicSetting<bool> use_dev_keys{false, "use_dev_keys"}; | 434 | BasicSetting<bool> use_dev_keys{false, "use_dev_keys"}; |
| 435 | 435 | ||
| 436 | // Services | 436 | // Network |
| 437 | BasicSetting<std::string> bcat_backend{"none", "bcat_backend"}; | 437 | BasicSetting<std::string> bcat_backend{"none", "bcat_backend"}; |
| 438 | BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"}; | 438 | BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"}; |
| 439 | BasicSetting<std::string> network_interface{std::string(), "network_interface"}; | ||
| 439 | 440 | ||
| 440 | // WebService | 441 | // WebService |
| 441 | BasicSetting<bool> enable_telemetry{true, "enable_telemetry"}; | 442 | BasicSetting<bool> enable_telemetry{true, "enable_telemetry"}; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5c99c00f5..f5cf5c16a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -636,6 +636,8 @@ add_library(core STATIC | |||
| 636 | memory.h | 636 | memory.h |
| 637 | network/network.cpp | 637 | network/network.cpp |
| 638 | network/network.h | 638 | network/network.h |
| 639 | network/network_interface.cpp | ||
| 640 | network/network_interface.h | ||
| 639 | network/sockets.h | 641 | network/sockets.h |
| 640 | perf_stats.cpp | 642 | perf_stats.cpp |
| 641 | perf_stats.h | 643 | perf_stats.h |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 5ef574d20..168053d80 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -179,10 +179,10 @@ private: | |||
| 179 | IPC::ResponseBuilder rb{ctx, 3}; | 179 | IPC::ResponseBuilder rb{ctx, 3}; |
| 180 | rb.Push(ResultSuccess); | 180 | rb.Push(ResultSuccess); |
| 181 | 181 | ||
| 182 | if (Settings::values.bcat_backend.GetValue() == "none") { | 182 | if (Network::GetHostIPv4Address().has_value()) { |
| 183 | rb.PushEnum(RequestState::NotSubmitted); | ||
| 184 | } else { | ||
| 185 | rb.PushEnum(RequestState::Connected); | 183 | rb.PushEnum(RequestState::Connected); |
| 184 | } else { | ||
| 185 | rb.PushEnum(RequestState::NotSubmitted); | ||
| 186 | } | 186 | } |
| 187 | } | 187 | } |
| 188 | 188 | ||
| @@ -322,12 +322,15 @@ private: | |||
| 322 | void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { | 322 | void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { |
| 323 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 323 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 324 | 324 | ||
| 325 | const auto [ipv4, error] = Network::GetHostIPv4Address(); | 325 | auto ipv4 = Network::GetHostIPv4Address(); |
| 326 | UNIMPLEMENTED_IF(error != Network::Errno::SUCCESS); | 326 | if (!ipv4) { |
| 327 | LOG_CRITICAL(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); | ||
| 328 | ipv4.emplace(Network::IPv4Address{0, 0, 0, 0}); | ||
| 329 | } | ||
| 327 | 330 | ||
| 328 | IPC::ResponseBuilder rb{ctx, 3}; | 331 | IPC::ResponseBuilder rb{ctx, 3}; |
| 329 | rb.Push(ResultSuccess); | 332 | rb.Push(ResultSuccess); |
| 330 | rb.PushRaw(ipv4); | 333 | rb.PushRaw(ipv4.value()); |
| 331 | } | 334 | } |
| 332 | void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { | 335 | void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { |
| 333 | LOG_DEBUG(Service_NIFM, "called"); | 336 | LOG_DEBUG(Service_NIFM, "called"); |
| @@ -354,13 +357,16 @@ private: | |||
| 354 | static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), | 357 | static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), |
| 355 | "IpConfigInfo has incorrect size."); | 358 | "IpConfigInfo has incorrect size."); |
| 356 | 359 | ||
| 357 | const auto [ipv4, error] = Network::GetHostIPv4Address(); | 360 | auto ipv4 = Network::GetHostIPv4Address(); |
| 358 | ASSERT_MSG(error == Network::Errno::SUCCESS, "Couldn't get host IPv4 address"); | 361 | if (!ipv4) { |
| 362 | LOG_CRITICAL(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0"); | ||
| 363 | ipv4.emplace(Network::IPv4Address{0, 0, 0, 0}); | ||
| 364 | } | ||
| 359 | 365 | ||
| 360 | const IpConfigInfo ip_config_info{ | 366 | const IpConfigInfo ip_config_info{ |
| 361 | .ip_address_setting{ | 367 | .ip_address_setting{ |
| 362 | .is_automatic{true}, | 368 | .is_automatic{true}, |
| 363 | .current_address{ipv4}, | 369 | .current_address{ipv4.value()}, |
| 364 | .subnet_mask{255, 255, 255, 0}, | 370 | .subnet_mask{255, 255, 255, 0}, |
| 365 | .gateway{192, 168, 1, 1}, | 371 | .gateway{192, 168, 1, 1}, |
| 366 | }, | 372 | }, |
| @@ -387,10 +393,10 @@ private: | |||
| 387 | 393 | ||
| 388 | IPC::ResponseBuilder rb{ctx, 3}; | 394 | IPC::ResponseBuilder rb{ctx, 3}; |
| 389 | rb.Push(ResultSuccess); | 395 | rb.Push(ResultSuccess); |
| 390 | if (Settings::values.bcat_backend.GetValue() == "none") { | 396 | if (Network::GetHostIPv4Address().has_value()) { |
| 391 | rb.Push<u8>(0); | ||
| 392 | } else { | ||
| 393 | rb.Push<u8>(1); | 397 | rb.Push<u8>(1); |
| 398 | } else { | ||
| 399 | rb.Push<u8>(0); | ||
| 394 | } | 400 | } |
| 395 | } | 401 | } |
| 396 | void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { | 402 | void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { |
| @@ -398,10 +404,10 @@ private: | |||
| 398 | 404 | ||
| 399 | IPC::ResponseBuilder rb{ctx, 3}; | 405 | IPC::ResponseBuilder rb{ctx, 3}; |
| 400 | rb.Push(ResultSuccess); | 406 | rb.Push(ResultSuccess); |
| 401 | if (Settings::values.bcat_backend.GetValue() == "none") { | 407 | if (Network::GetHostIPv4Address().has_value()) { |
| 402 | rb.Push<u8>(0); | ||
| 403 | } else { | ||
| 404 | rb.Push<u8>(1); | 408 | rb.Push<u8>(1); |
| 409 | } else { | ||
| 410 | rb.Push<u8>(0); | ||
| 405 | } | 411 | } |
| 406 | } | 412 | } |
| 407 | }; | 413 | }; |
diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp index 7b038041e..67ecf57bd 100644 --- a/src/core/network/network.cpp +++ b/src/core/network/network.cpp | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | 11 | ||
| 12 | #ifdef _WIN32 | 12 | #ifdef _WIN32 |
| 13 | #define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname | ||
| 14 | #include <winsock2.h> | 13 | #include <winsock2.h> |
| 14 | #include <ws2tcpip.h> | ||
| 15 | #elif YUZU_UNIX | 15 | #elif YUZU_UNIX |
| 16 | #include <errno.h> | 16 | #include <errno.h> |
| 17 | #include <fcntl.h> | 17 | #include <fcntl.h> |
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <netinet/in.h> | 19 | #include <netinet/in.h> |
| 20 | #include <poll.h> | 20 | #include <poll.h> |
| 21 | #include <sys/socket.h> | 21 | #include <sys/socket.h> |
| 22 | #include <arpa/inet.h> | ||
| 22 | #include <unistd.h> | 23 | #include <unistd.h> |
| 23 | #else | 24 | #else |
| 24 | #error "Unimplemented platform" | 25 | #error "Unimplemented platform" |
| @@ -27,7 +28,9 @@ | |||
| 27 | #include "common/assert.h" | 28 | #include "common/assert.h" |
| 28 | #include "common/common_types.h" | 29 | #include "common/common_types.h" |
| 29 | #include "common/logging/log.h" | 30 | #include "common/logging/log.h" |
| 31 | #include "common/settings.h" | ||
| 30 | #include "core/network/network.h" | 32 | #include "core/network/network.h" |
| 33 | #include "core/network/network_interface.h" | ||
| 31 | #include "core/network/sockets.h" | 34 | #include "core/network/sockets.h" |
| 32 | 35 | ||
| 33 | namespace Network { | 36 | namespace Network { |
| @@ -357,27 +360,27 @@ NetworkInstance::~NetworkInstance() { | |||
| 357 | Finalize(); | 360 | Finalize(); |
| 358 | } | 361 | } |
| 359 | 362 | ||
| 360 | std::pair<IPv4Address, Errno> GetHostIPv4Address() { | 363 | std::optional<IPv4Address> GetHostIPv4Address() { |
| 361 | std::array<char, 256> name{}; | 364 | const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); |
| 362 | if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { | 365 | const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); |
| 363 | return {IPv4Address{}, GetAndLogLastError()}; | 366 | ASSERT_MSG(network_interfaces.size() > 0, "GetAvailableNetworkInterfaces returned no interfaces"); |
| 364 | } | ||
| 365 | 367 | ||
| 366 | hostent* const ent = gethostbyname(name.data()); | ||
| 367 | if (!ent) { | ||
| 368 | return {IPv4Address{}, GetAndLogLastError()}; | ||
| 369 | } | ||
| 370 | if (ent->h_addr_list == nullptr) { | ||
| 371 | UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list"); | ||
| 372 | return {IPv4Address{}, Errno::SUCCESS}; | ||
| 373 | } | ||
| 374 | if (ent->h_length != sizeof(in_addr)) { | ||
| 375 | UNIMPLEMENTED_MSG("Unexpected size={} in hostent->h_length", ent->h_length); | ||
| 376 | } | ||
| 377 | 368 | ||
| 378 | in_addr addr; | 369 | const auto res = std::ranges::find_if(network_interfaces, |
| 379 | std::memcpy(&addr, ent->h_addr_list[0], sizeof(addr)); | 370 | [&selected_network_interface](const auto& interface) { |
| 380 | return {TranslateIPv4(addr), Errno::SUCCESS}; | 371 | return interface.name == selected_network_interface; |
| 372 | }); | ||
| 373 | |||
| 374 | if (res != network_interfaces.end()) { | ||
| 375 | char ip_addr[16]; | ||
| 376 | ASSERT(inet_ntop(AF_INET, &res->ip_address, ip_addr, sizeof(ip_addr)) != nullptr); | ||
| 377 | LOG_INFO(Network, "IP address: {}", ip_addr); | ||
| 378 | |||
| 379 | return TranslateIPv4(res->ip_address); | ||
| 380 | } else { | ||
| 381 | LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); | ||
| 382 | return {}; | ||
| 383 | } | ||
| 381 | } | 384 | } |
| 382 | 385 | ||
| 383 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { | 386 | std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { |
diff --git a/src/core/network/network.h b/src/core/network/network.h index bd30f1899..cfa68d478 100644 --- a/src/core/network/network.h +++ b/src/core/network/network.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <optional> | ||
| 8 | #include <utility> | 9 | #include <utility> |
| 9 | 10 | ||
| 10 | #include "common/common_funcs.h" | 11 | #include "common/common_funcs.h" |
| @@ -93,7 +94,7 @@ public: | |||
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| 95 | /// @brief Returns host's IPv4 address | 96 | /// @brief Returns host's IPv4 address |
| 96 | /// @return Pair of an array of human ordered IPv4 address (e.g. 192.168.0.1) and an error code | 97 | /// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array |
| 97 | std::pair<IPv4Address, Errno> GetHostIPv4Address(); | 98 | std::optional<IPv4Address> GetHostIPv4Address(); |
| 98 | 99 | ||
| 99 | } // namespace Network | 100 | } // namespace Network |
diff --git a/src/core/network/network_interface.cpp b/src/core/network/network_interface.cpp new file mode 100644 index 000000000..bba4c8b26 --- /dev/null +++ b/src/core/network/network_interface.cpp | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <vector> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/logging/log.h" | ||
| 9 | #include "common/string_util.h" | ||
| 10 | #include "core/network/network_interface.h" | ||
| 11 | |||
| 12 | #ifdef _WIN32 | ||
| 13 | #include <iphlpapi.h> | ||
| 14 | #else | ||
| 15 | #include <ifaddrs.h> | ||
| 16 | #include <net/if.h> | ||
| 17 | #include <cerrno> | ||
| 18 | #endif | ||
| 19 | |||
| 20 | namespace Network { | ||
| 21 | |||
| 22 | #ifdef _WIN32 | ||
| 23 | |||
| 24 | std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { | ||
| 25 | std::vector<NetworkInterface> result; | ||
| 26 | |||
| 27 | std::vector<u8> adapter_addresses_raw; | ||
| 28 | auto adapter_addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_addresses_raw.data()); | ||
| 29 | DWORD ret = ERROR_BUFFER_OVERFLOW; | ||
| 30 | DWORD buf_size = 0; | ||
| 31 | |||
| 32 | // retry up to 5 times | ||
| 33 | for (int i = 0; i < 5 && ret == ERROR_BUFFER_OVERFLOW; i++) { | ||
| 34 | ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER, | ||
| 35 | nullptr, adapter_addresses, &buf_size); | ||
| 36 | |||
| 37 | if (ret == ERROR_BUFFER_OVERFLOW) { | ||
| 38 | adapter_addresses_raw.resize(buf_size); | ||
| 39 | adapter_addresses = | ||
| 40 | reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_addresses_raw.data()); | ||
| 41 | } else { | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | if (ret == NO_ERROR) { | ||
| 47 | for (auto current_address = adapter_addresses; current_address != nullptr; | ||
| 48 | current_address = current_address->Next) { | ||
| 49 | if (current_address->FirstUnicastAddress == nullptr || | ||
| 50 | current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) { | ||
| 51 | continue; | ||
| 52 | } | ||
| 53 | |||
| 54 | if (current_address->OperStatus != IfOperStatusUp) { | ||
| 55 | continue; | ||
| 56 | } | ||
| 57 | |||
| 58 | const auto ip_addr = std::bit_cast<struct sockaddr_in>( | ||
| 59 | *current_address->FirstUnicastAddress->Address.lpSockaddr) | ||
| 60 | .sin_addr; | ||
| 61 | |||
| 62 | result.push_back(NetworkInterface{ | ||
| 63 | .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})}, | ||
| 64 | .ip_address{ip_addr} | ||
| 65 | }); | ||
| 66 | } | ||
| 67 | } else { | ||
| 68 | LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses"); | ||
| 69 | } | ||
| 70 | |||
| 71 | return result; | ||
| 72 | } | ||
| 73 | |||
| 74 | #else | ||
| 75 | |||
| 76 | std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { | ||
| 77 | std::vector<NetworkInterface> result; | ||
| 78 | |||
| 79 | struct ifaddrs* ifaddr = nullptr; | ||
| 80 | |||
| 81 | if (getifaddrs(&ifaddr) != 0) { | ||
| 82 | LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}", | ||
| 83 | std::strerror(errno)); | ||
| 84 | return result; | ||
| 85 | } | ||
| 86 | |||
| 87 | for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { | ||
| 88 | if (ifa->ifa_addr == nullptr) { | ||
| 89 | continue; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (ifa->ifa_addr->sa_family != AF_INET) { | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (!(ifa->ifa_flags & IFF_UP) || ifa->ifa_flags & IFF_LOOPBACK) { | ||
| 97 | continue; | ||
| 98 | } | ||
| 99 | |||
| 100 | result.push_back(NetworkInterface{ | ||
| 101 | .name{ifa->ifa_name}, | ||
| 102 | .ip_address{std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr} | ||
| 103 | }); | ||
| 104 | } | ||
| 105 | |||
| 106 | freeifaddrs(ifaddr); | ||
| 107 | |||
| 108 | return result; | ||
| 109 | } | ||
| 110 | |||
| 111 | #endif | ||
| 112 | |||
| 113 | } // namespace Network | ||
diff --git a/src/core/network/network_interface.h b/src/core/network/network_interface.h new file mode 100644 index 000000000..d7184e14a --- /dev/null +++ b/src/core/network/network_interface.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <string> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | #ifdef _WIN32 | ||
| 11 | #include <winsock2.h> | ||
| 12 | #else | ||
| 13 | #include <netinet/in.h> | ||
| 14 | #endif | ||
| 15 | |||
| 16 | namespace Network { | ||
| 17 | |||
| 18 | struct NetworkInterface { | ||
| 19 | std::string name; | ||
| 20 | struct in_addr ip_address; | ||
| 21 | }; | ||
| 22 | |||
| 23 | std::vector<NetworkInterface> GetAvailableNetworkInterfaces(); | ||
| 24 | |||
| 25 | } // namespace Network | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index cb4bdcc7e..cf68a95b5 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -102,9 +102,9 @@ add_executable(yuzu | |||
| 102 | configuration/configure_profile_manager.cpp | 102 | configuration/configure_profile_manager.cpp |
| 103 | configuration/configure_profile_manager.h | 103 | configuration/configure_profile_manager.h |
| 104 | configuration/configure_profile_manager.ui | 104 | configuration/configure_profile_manager.ui |
| 105 | configuration/configure_service.cpp | 105 | configuration/configure_network.cpp |
| 106 | configuration/configure_service.h | 106 | configuration/configure_network.h |
| 107 | configuration/configure_service.ui | 107 | configuration/configure_network.ui |
| 108 | configuration/configure_system.cpp | 108 | configuration/configure_system.cpp |
| 109 | configuration/configure_system.h | 109 | configuration/configure_system.h |
| 110 | configuration/configure_system.ui | 110 | configuration/configure_system.ui |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 380379eb4..377795326 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -692,6 +692,7 @@ void Config::ReadServiceValues() { | |||
| 692 | qt_config->beginGroup(QStringLiteral("Services")); | 692 | qt_config->beginGroup(QStringLiteral("Services")); |
| 693 | ReadBasicSetting(Settings::values.bcat_backend); | 693 | ReadBasicSetting(Settings::values.bcat_backend); |
| 694 | ReadBasicSetting(Settings::values.bcat_boxcat_local); | 694 | ReadBasicSetting(Settings::values.bcat_boxcat_local); |
| 695 | ReadBasicSetting(Settings::values.network_interface); | ||
| 695 | qt_config->endGroup(); | 696 | qt_config->endGroup(); |
| 696 | } | 697 | } |
| 697 | 698 | ||
| @@ -1144,7 +1145,7 @@ void Config::SaveValues() { | |||
| 1144 | SaveDataStorageValues(); | 1145 | SaveDataStorageValues(); |
| 1145 | SaveDebuggingValues(); | 1146 | SaveDebuggingValues(); |
| 1146 | SaveDisabledAddOnValues(); | 1147 | SaveDisabledAddOnValues(); |
| 1147 | SaveServiceValues(); | 1148 | SaveNetworkValues(); |
| 1148 | SaveUIValues(); | 1149 | SaveUIValues(); |
| 1149 | SaveWebServiceValues(); | 1150 | SaveWebServiceValues(); |
| 1150 | SaveMiscellaneousValues(); | 1151 | SaveMiscellaneousValues(); |
| @@ -1238,11 +1239,12 @@ void Config::SaveDebuggingValues() { | |||
| 1238 | qt_config->endGroup(); | 1239 | qt_config->endGroup(); |
| 1239 | } | 1240 | } |
| 1240 | 1241 | ||
| 1241 | void Config::SaveServiceValues() { | 1242 | void Config::SaveNetworkValues() { |
| 1242 | qt_config->beginGroup(QStringLiteral("Services")); | 1243 | qt_config->beginGroup(QStringLiteral("Services")); |
| 1243 | 1244 | ||
| 1244 | WriteBasicSetting(Settings::values.bcat_backend); | 1245 | WriteBasicSetting(Settings::values.bcat_backend); |
| 1245 | WriteBasicSetting(Settings::values.bcat_boxcat_local); | 1246 | WriteBasicSetting(Settings::values.bcat_boxcat_local); |
| 1247 | WriteBasicSetting(Settings::values.network_interface); | ||
| 1246 | 1248 | ||
| 1247 | qt_config->endGroup(); | 1249 | qt_config->endGroup(); |
| 1248 | } | 1250 | } |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index c1d7feb9f..9555f4498 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -88,7 +88,7 @@ private: | |||
| 88 | void SaveCoreValues(); | 88 | void SaveCoreValues(); |
| 89 | void SaveDataStorageValues(); | 89 | void SaveDataStorageValues(); |
| 90 | void SaveDebuggingValues(); | 90 | void SaveDebuggingValues(); |
| 91 | void SaveServiceValues(); | 91 | void SaveNetworkValues(); |
| 92 | void SaveDisabledAddOnValues(); | 92 | void SaveDisabledAddOnValues(); |
| 93 | void SaveMiscellaneousValues(); | 93 | void SaveMiscellaneousValues(); |
| 94 | void SavePathValues(); | 94 | void SavePathValues(); |
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index fca9aed5f..6258dcf20 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -147,12 +147,12 @@ | |||
| 147 | <string>Web</string> | 147 | <string>Web</string> |
| 148 | </attribute> | 148 | </attribute> |
| 149 | </widget> | 149 | </widget> |
| 150 | <widget class="ConfigureService" name="serviceTab"> | 150 | <widget class="ConfigureNetwork" name="networkTab"> |
| 151 | <property name="accessibleName"> | 151 | <property name="accessibleName"> |
| 152 | <string>Services</string> | 152 | <string>Network</string> |
| 153 | </property> | 153 | </property> |
| 154 | <attribute name="title"> | 154 | <attribute name="title"> |
| 155 | <string>Services</string> | 155 | <string>Network</string> |
| 156 | </attribute> | 156 | </attribute> |
| 157 | </widget> | 157 | </widget> |
| 158 | </widget> | 158 | </widget> |
| @@ -242,9 +242,9 @@ | |||
| 242 | <container>1</container> | 242 | <container>1</container> |
| 243 | </customwidget> | 243 | </customwidget> |
| 244 | <customwidget> | 244 | <customwidget> |
| 245 | <class>ConfigureService</class> | 245 | <class>ConfigureNetwork</class> |
| 246 | <extends>QWidget</extends> | 246 | <extends>QWidget</extends> |
| 247 | <header>configuration/configure_service.h</header> | 247 | <header>configuration/configure_network.h</header> |
| 248 | <container>1</container> | 248 | <container>1</container> |
| 249 | </customwidget> | 249 | </customwidget> |
| 250 | <customwidget> | 250 | <customwidget> |
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index bc009b6b3..fe4186157 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -67,7 +67,7 @@ void ConfigureDialog::ApplyConfiguration() { | |||
| 67 | ui->audioTab->ApplyConfiguration(); | 67 | ui->audioTab->ApplyConfiguration(); |
| 68 | ui->debugTab->ApplyConfiguration(); | 68 | ui->debugTab->ApplyConfiguration(); |
| 69 | ui->webTab->ApplyConfiguration(); | 69 | ui->webTab->ApplyConfiguration(); |
| 70 | ui->serviceTab->ApplyConfiguration(); | 70 | ui->networkTab->ApplyConfiguration(); |
| 71 | Core::System::GetInstance().ApplySettings(); | 71 | Core::System::GetInstance().ApplySettings(); |
| 72 | Settings::LogSettings(); | 72 | Settings::LogSettings(); |
| 73 | } | 73 | } |
| @@ -103,7 +103,7 @@ Q_DECLARE_METATYPE(QList<QWidget*>); | |||
| 103 | void ConfigureDialog::PopulateSelectionList() { | 103 | void ConfigureDialog::PopulateSelectionList() { |
| 104 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ | 104 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ |
| 105 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, | 105 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, |
| 106 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, | 106 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->networkTab, ui->filesystemTab}}, |
| 107 | {tr("CPU"), {ui->cpuTab}}, | 107 | {tr("CPU"), {ui->cpuTab}}, |
| 108 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, | 108 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, |
| 109 | {tr("Audio"), {ui->audioTab}}, | 109 | {tr("Audio"), {ui->audioTab}}, |
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_network.cpp index 4aa424803..9787d4f1b 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_network.cpp | |||
| @@ -5,9 +5,10 @@ | |||
| 5 | #include <QGraphicsItem> | 5 | #include <QGraphicsItem> |
| 6 | #include <QtConcurrent/QtConcurrent> | 6 | #include <QtConcurrent/QtConcurrent> |
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/core.h" | ||
| 8 | #include "core/hle/service/bcat/backend/boxcat.h" | 9 | #include "core/hle/service/bcat/backend/boxcat.h" |
| 9 | #include "ui_configure_service.h" | 10 | #include "ui_configure_network.h" |
| 10 | #include "yuzu/configuration/configure_service.h" | 11 | #include "yuzu/configuration/configure_network.h" |
| 11 | 12 | ||
| 12 | #ifdef YUZU_ENABLE_BOXCAT | 13 | #ifdef YUZU_ENABLE_BOXCAT |
| 13 | namespace { | 14 | namespace { |
| @@ -35,8 +36,8 @@ QString FormatEventStatusString(const Service::BCAT::EventStatus& status) { | |||
| 35 | } // Anonymous namespace | 36 | } // Anonymous namespace |
| 36 | #endif | 37 | #endif |
| 37 | 38 | ||
| 38 | ConfigureService::ConfigureService(QWidget* parent) | 39 | ConfigureNetwork::ConfigureNetwork(QWidget* parent) |
| 39 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureService>()) { | 40 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()) { |
| 40 | ui->setupUi(this); | 41 | ui->setupUi(this); |
| 41 | 42 | ||
| 42 | ui->bcat_source->addItem(QStringLiteral("None")); | 43 | ui->bcat_source->addItem(QStringLiteral("None")); |
| @@ -47,29 +48,42 @@ ConfigureService::ConfigureService(QWidget* parent) | |||
| 47 | ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat")); | 48 | ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat")); |
| 48 | #endif | 49 | #endif |
| 49 | 50 | ||
| 51 | ui->network_interface->addItem(QStringLiteral("None")); | ||
| 52 | for (const auto& interface : Network::GetAvailableNetworkInterfaces()) { | ||
| 53 | ui->network_interface->addItem(QString::fromStdString(interface.name)); | ||
| 54 | } | ||
| 55 | |||
| 50 | connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 56 | connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
| 51 | &ConfigureService::OnBCATImplChanged); | 57 | &ConfigureNetwork::OnBCATImplChanged); |
| 52 | 58 | ||
| 53 | this->SetConfiguration(); | 59 | this->SetConfiguration(); |
| 54 | } | 60 | } |
| 55 | 61 | ||
| 56 | ConfigureService::~ConfigureService() = default; | 62 | ConfigureNetwork::~ConfigureNetwork() = default; |
| 57 | 63 | ||
| 58 | void ConfigureService::ApplyConfiguration() { | 64 | void ConfigureNetwork::ApplyConfiguration() { |
| 59 | Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString(); | 65 | Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString(); |
| 66 | Settings::values.network_interface = ui->network_interface->currentText().toStdString(); | ||
| 60 | } | 67 | } |
| 61 | 68 | ||
| 62 | void ConfigureService::RetranslateUi() { | 69 | void ConfigureNetwork::RetranslateUi() { |
| 63 | ui->retranslateUi(this); | 70 | ui->retranslateUi(this); |
| 64 | } | 71 | } |
| 65 | 72 | ||
| 66 | void ConfigureService::SetConfiguration() { | 73 | void ConfigureNetwork::SetConfiguration() { |
| 74 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | ||
| 75 | |||
| 67 | const int index = | 76 | const int index = |
| 68 | ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue())); | 77 | ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue())); |
| 69 | ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); | 78 | ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); |
| 79 | |||
| 80 | const std::string& network_interface = Settings::values.network_interface.GetValue(); | ||
| 81 | |||
| 82 | ui->network_interface->setCurrentText(QString::fromStdString(network_interface)); | ||
| 83 | ui->network_interface->setEnabled(runtime_lock); | ||
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { | 86 | std::pair<QString, QString> ConfigureNetwork::BCATDownloadEvents() { |
| 73 | #ifdef YUZU_ENABLE_BOXCAT | 87 | #ifdef YUZU_ENABLE_BOXCAT |
| 74 | std::optional<std::string> global; | 88 | std::optional<std::string> global; |
| 75 | std::map<std::string, Service::BCAT::EventStatus> map; | 89 | std::map<std::string, Service::BCAT::EventStatus> map; |
| @@ -114,7 +128,7 @@ std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { | |||
| 114 | #endif | 128 | #endif |
| 115 | } | 129 | } |
| 116 | 130 | ||
| 117 | void ConfigureService::OnBCATImplChanged() { | 131 | void ConfigureNetwork::OnBCATImplChanged() { |
| 118 | #ifdef YUZU_ENABLE_BOXCAT | 132 | #ifdef YUZU_ENABLE_BOXCAT |
| 119 | const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); | 133 | const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); |
| 120 | ui->bcat_empty_header->setHidden(!boxcat); | 134 | ui->bcat_empty_header->setHidden(!boxcat); |
| @@ -133,7 +147,7 @@ void ConfigureService::OnBCATImplChanged() { | |||
| 133 | #endif | 147 | #endif |
| 134 | } | 148 | } |
| 135 | 149 | ||
| 136 | void ConfigureService::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) { | 150 | void ConfigureNetwork::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) { |
| 137 | #ifdef YUZU_ENABLE_BOXCAT | 151 | #ifdef YUZU_ENABLE_BOXCAT |
| 138 | const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); | 152 | const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); |
| 139 | if (boxcat) { | 153 | if (boxcat) { |
diff --git a/src/yuzu/configuration/configure_service.h b/src/yuzu/configuration/configure_network.h index f5c1b703a..d4ef33fbf 100644 --- a/src/yuzu/configuration/configure_service.h +++ b/src/yuzu/configuration/configure_network.h | |||
| @@ -8,16 +8,18 @@ | |||
| 8 | #include <QFutureWatcher> | 8 | #include <QFutureWatcher> |
| 9 | #include <QWidget> | 9 | #include <QWidget> |
| 10 | 10 | ||
| 11 | #include "core/network/network_interface.h" | ||
| 12 | |||
| 11 | namespace Ui { | 13 | namespace Ui { |
| 12 | class ConfigureService; | 14 | class ConfigureNetwork; |
| 13 | } | 15 | } |
| 14 | 16 | ||
| 15 | class ConfigureService : public QWidget { | 17 | class ConfigureNetwork : public QWidget { |
| 16 | Q_OBJECT | 18 | Q_OBJECT |
| 17 | 19 | ||
| 18 | public: | 20 | public: |
| 19 | explicit ConfigureService(QWidget* parent = nullptr); | 21 | explicit ConfigureNetwork(QWidget* parent = nullptr); |
| 20 | ~ConfigureService() override; | 22 | ~ConfigureNetwork() override; |
| 21 | 23 | ||
| 22 | void ApplyConfiguration(); | 24 | void ApplyConfiguration(); |
| 23 | void RetranslateUi(); | 25 | void RetranslateUi(); |
| @@ -29,6 +31,6 @@ private: | |||
| 29 | void OnBCATImplChanged(); | 31 | void OnBCATImplChanged(); |
| 30 | void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string); | 32 | void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string); |
| 31 | 33 | ||
| 32 | std::unique_ptr<Ui::ConfigureService> ui; | 34 | std::unique_ptr<Ui::ConfigureNetwork> ui; |
| 33 | QFutureWatcher<std::pair<QString, QString>> watcher{this}; | 35 | QFutureWatcher<std::pair<QString, QString>> watcher{this}; |
| 34 | }; | 36 | }; |
diff --git a/src/yuzu/configuration/configure_service.ui b/src/yuzu/configuration/configure_network.ui index 9668dd557..5f9b7e97b 100644 --- a/src/yuzu/configuration/configure_service.ui +++ b/src/yuzu/configuration/configure_network.ui | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <ui version="4.0"> | 2 | <ui version="4.0"> |
| 3 | <class>ConfigureService</class> | 3 | <class>ConfigureNetwork</class> |
| 4 | <widget class="QWidget" name="ConfigureService"> | 4 | <widget class="QWidget" name="ConfigureNetwork"> |
| 5 | <property name="geometry"> | 5 | <property name="geometry"> |
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| @@ -17,21 +17,37 @@ | |||
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 18 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 19 | <item> | 19 | <item> |
| 20 | <widget class="QGroupBox" name="groupBox_2"> | ||
| 21 | <property name="title"> | ||
| 22 | <string>General</string> | ||
| 23 | </property> | ||
| 24 | <layout class="QGridLayout" name="gridLayout_2"> | ||
| 25 | <item row="1" column="1"> | ||
| 26 | <widget class="QComboBox" name="network_interface"/> | ||
| 27 | </item> | ||
| 28 | <item row="1" column="0"> | ||
| 29 | <widget class="QLabel" name="label_4"> | ||
| 30 | <property name="text"> | ||
| 31 | <string>Network Interface</string> | ||
| 32 | </property> | ||
| 33 | </widget> | ||
| 34 | </item> | ||
| 35 | </layout> | ||
| 36 | </widget> | ||
| 37 | </item> | ||
| 38 | <item> | ||
| 20 | <widget class="QGroupBox" name="groupBox"> | 39 | <widget class="QGroupBox" name="groupBox"> |
| 21 | <property name="title"> | 40 | <property name="title"> |
| 22 | <string>BCAT</string> | 41 | <string>BCAT</string> |
| 23 | </property> | 42 | </property> |
| 24 | <layout class="QGridLayout" name="gridLayout"> | 43 | <layout class="QGridLayout" name="gridLayout"> |
| 25 | <item row="1" column="1" colspan="2"> | 44 | <item row="3" column="0"> |
| 26 | <widget class="QLabel" name="label_2"> | 45 | <widget class="QLabel" name="bcat_empty_header"> |
| 27 | <property name="maximumSize"> | ||
| 28 | <size> | ||
| 29 | <width>260</width> | ||
| 30 | <height>16777215</height> | ||
| 31 | </size> | ||
| 32 | </property> | ||
| 33 | <property name="text"> | 46 | <property name="text"> |
| 34 | <string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string> | 47 | <string/> |
| 48 | </property> | ||
| 49 | <property name="alignment"> | ||
| 50 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 35 | </property> | 51 | </property> |
| 36 | <property name="wordWrap"> | 52 | <property name="wordWrap"> |
| 37 | <bool>true</bool> | 53 | <bool>true</bool> |
| @@ -51,11 +67,8 @@ | |||
| 51 | </property> | 67 | </property> |
| 52 | </widget> | 68 | </widget> |
| 53 | </item> | 69 | </item> |
| 54 | <item row="3" column="1" colspan="2"> | 70 | <item row="1" column="1" colspan="2"> |
| 55 | <widget class="QLabel" name="bcat_empty_label"> | 71 | <widget class="QLabel" name="label_2"> |
| 56 | <property name="enabled"> | ||
| 57 | <bool>true</bool> | ||
| 58 | </property> | ||
| 59 | <property name="maximumSize"> | 72 | <property name="maximumSize"> |
| 60 | <size> | 73 | <size> |
| 61 | <width>260</width> | 74 | <width>260</width> |
| @@ -63,10 +76,7 @@ | |||
| 63 | </size> | 76 | </size> |
| 64 | </property> | 77 | </property> |
| 65 | <property name="text"> | 78 | <property name="text"> |
| 66 | <string/> | 79 | <string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string> |
| 67 | </property> | ||
| 68 | <property name="alignment"> | ||
| 69 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||
| 70 | </property> | 80 | </property> |
| 71 | <property name="wordWrap"> | 81 | <property name="wordWrap"> |
| 72 | <bool>true</bool> | 82 | <bool>true</bool> |
| @@ -86,8 +96,17 @@ | |||
| 86 | <item row="0" column="1" colspan="2"> | 96 | <item row="0" column="1" colspan="2"> |
| 87 | <widget class="QComboBox" name="bcat_source"/> | 97 | <widget class="QComboBox" name="bcat_source"/> |
| 88 | </item> | 98 | </item> |
| 89 | <item row="3" column="0"> | 99 | <item row="3" column="1" colspan="2"> |
| 90 | <widget class="QLabel" name="bcat_empty_header"> | 100 | <widget class="QLabel" name="bcat_empty_label"> |
| 101 | <property name="enabled"> | ||
| 102 | <bool>true</bool> | ||
| 103 | </property> | ||
| 104 | <property name="maximumSize"> | ||
| 105 | <size> | ||
| 106 | <width>260</width> | ||
| 107 | <height>16777215</height> | ||
| 108 | </size> | ||
| 109 | </property> | ||
| 91 | <property name="text"> | 110 | <property name="text"> |
| 92 | <string/> | 111 | <string/> |
| 93 | </property> | 112 | </property> |