Compare commits
22 Commits
android-21
...
android-22
Author | SHA1 | Date | |
---|---|---|---|
bfe34d6ee8 | |||
3d21af61db | |||
74f5e1dcf5 | |||
f75119322d | |||
a8956d3ff0 | |||
2f5941e899 | |||
a4b147f525 | |||
4240f2d56b | |||
ffe3984353 | |||
ec734cb06c | |||
8292ba7ad6 | |||
2e65616761 | |||
07aa1a99fa | |||
6524f20de4 | |||
a0f7f2b309 | |||
ecea5ef757 | |||
a1ce45b0b1 | |||
9ba9780a96 | |||
73e7a259fd | |||
2cc5c517cf | |||
c0775e74ec | |||
3acf35bb98 |
@ -322,6 +322,10 @@ if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak 6 CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_arm64)
|
||||
find_package(oaknut 2.0.1 CONFIG)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
find_package(dynarmic 6.4.0 CONFIG)
|
||||
endif()
|
||||
|
@ -1,7 +1,12 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`a407f9bf5`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`aad4b0d6f`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12760](https://github.com/yuzu-emu/yuzu-android//pull/12760) | [`817d91623`](https://github.com/yuzu-emu/yuzu-android//pull/12760/files) | am: rewrite for multiprocess support | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12858](https://github.com/yuzu-emu/yuzu-android//pull/12858) | [`5510b3197`](https://github.com/yuzu-emu/yuzu-android//pull/12858/files) | internal_network: only poll for accept on blocking sockets | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12864](https://github.com/yuzu-emu/yuzu-android//pull/12864) | [`9ed82a280`](https://github.com/yuzu-emu/yuzu-android//pull/12864/files) | Small time fixes | [Kelebek1](https://github.com/Kelebek1/) | Yes |
|
||||
| [12867](https://github.com/yuzu-emu/yuzu-android//pull/12867) | [`a97ecc237`](https://github.com/yuzu-emu/yuzu-android//pull/12867/files) | aoc: fix DLC listing | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12868](https://github.com/yuzu-emu/yuzu-android//pull/12868) | [`e8be665f1`](https://github.com/yuzu-emu/yuzu-android//pull/12868/files) | settings: Allow audio sink, input, and output to be set per game | [t895](https://github.com/t895/) | Yes |
|
||||
| [12869](https://github.com/yuzu-emu/yuzu-android//pull/12869) | [`acd46c9bd`](https://github.com/yuzu-emu/yuzu-android//pull/12869/files) | SMMU: A set of different fixes. | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
5
externals/CMakeLists.txt
vendored
5
externals/CMakeLists.txt
vendored
@ -14,16 +14,17 @@ set(BUILD_SHARED_LIBS OFF)
|
||||
# Skip install rules for all externals
|
||||
set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
|
||||
# xbyak
|
||||
# Xbyak (also used by Dynarmic, so needs to be added first)
|
||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||
add_subdirectory(xbyak)
|
||||
endif()
|
||||
|
||||
# Dynarmic
|
||||
# Oaknut (also used by Dynarmic, so needs to be added first)
|
||||
if (ARCHITECTURE_arm64 AND NOT TARGET merry::oaknut)
|
||||
add_subdirectory(oaknut)
|
||||
endif()
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||
add_subdirectory(dynarmic)
|
||||
|
@ -261,7 +261,7 @@ object NativeLibrary {
|
||||
/**
|
||||
* Begins emulation.
|
||||
*/
|
||||
external fun run(path: String?, programIndex: Int = 0)
|
||||
external fun run(path: String?, programIndex: Int, frontendInitiated: Boolean)
|
||||
|
||||
// Surface Handling
|
||||
external fun surfaceChanged(surf: Surface?)
|
||||
|
@ -927,7 +927,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
emulationThread.join()
|
||||
emulationThread = Thread({
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||
NativeLibrary.run(gamePath, programIndex)
|
||||
NativeLibrary.run(gamePath, programIndex, false)
|
||||
}, "NativeEmulation")
|
||||
emulationThread.start()
|
||||
}
|
||||
@ -981,7 +981,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
State.STOPPED -> {
|
||||
emulationThread = Thread({
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.")
|
||||
NativeLibrary.run(gamePath, programIndex)
|
||||
NativeLibrary.run(gamePath, programIndex, true)
|
||||
}, "NativeEmulation")
|
||||
emulationThread.start()
|
||||
}
|
||||
|
@ -219,7 +219,8 @@ void EmulationSession::SetAppletId(int applet_id) {
|
||||
}
|
||||
|
||||
Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string& filepath,
|
||||
const std::size_t program_index) {
|
||||
const std::size_t program_index,
|
||||
const bool frontend_initiated) {
|
||||
std::scoped_lock lock(m_mutex);
|
||||
|
||||
// Create the render window.
|
||||
@ -251,6 +252,8 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string
|
||||
// Load the ROM.
|
||||
Service::AM::FrontendAppletParameters params{
|
||||
.applet_id = static_cast<Service::AM::AppletId>(m_applet_id),
|
||||
.launch_type = frontend_initiated ? Service::AM::LaunchType::FrontendInitiated
|
||||
: Service::AM::LaunchType::ApplicationInitiated,
|
||||
.program_index = static_cast<s32>(program_index),
|
||||
};
|
||||
m_load_result = m_system.Load(EmulationSession::GetInstance().Window(), filepath, params);
|
||||
@ -447,7 +450,8 @@ u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) {
|
||||
}
|
||||
|
||||
static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||
const size_t program_index = 0) {
|
||||
const size_t program_index,
|
||||
const bool frontend_initiated) {
|
||||
MicroProfileOnThreadCreate("EmuThread");
|
||||
SCOPE_EXIT({ MicroProfileShutdown(); });
|
||||
|
||||
@ -460,7 +464,8 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath,
|
||||
|
||||
SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); });
|
||||
|
||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index);
|
||||
jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath, program_index,
|
||||
frontend_initiated);
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
return result;
|
||||
}
|
||||
@ -757,10 +762,12 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj
|
||||
}
|
||||
|
||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path,
|
||||
jint j_program_index) {
|
||||
jint j_program_index,
|
||||
jboolean j_frontend_initiated) {
|
||||
const std::string path = GetJString(env, j_path);
|
||||
|
||||
const Core::SystemResultStatus result{RunEmulation(path, j_program_index)};
|
||||
const Core::SystemResultStatus result{
|
||||
RunEmulation(path, j_program_index, j_frontend_initiated)};
|
||||
if (result != Core::SystemResultStatus::Success) {
|
||||
env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(),
|
||||
IDCache::GetExitEmulationActivity(), static_cast<int>(result));
|
||||
|
@ -47,7 +47,8 @@ public:
|
||||
void InitializeSystem(bool reload);
|
||||
void SetAppletId(int applet_id);
|
||||
Core::SystemResultStatus InitializeEmulation(const std::string& filepath,
|
||||
const std::size_t program_index = 0);
|
||||
const std::size_t program_index,
|
||||
const bool frontend_initiated);
|
||||
|
||||
bool IsHandheldOnly();
|
||||
void SetDeviceType([[maybe_unused]] int index, int type);
|
||||
|
@ -134,12 +134,12 @@ struct Values {
|
||||
Linkage linkage{};
|
||||
|
||||
// Audio
|
||||
Setting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_output_device_id{linkage, "auto", "output_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
Setting<std::string> audio_input_device_id{linkage, "auto", "input_device", Category::Audio,
|
||||
Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioEngine> sink_id{linkage, AudioEngine::Auto, "output_engine",
|
||||
Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_output_device_id{
|
||||
linkage, "auto", "output_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<std::string> audio_input_device_id{
|
||||
linkage, "auto", "input_device", Category::Audio, Specialization::RuntimeList};
|
||||
SwitchableSetting<AudioMode, true> sound_index{
|
||||
linkage, AudioMode::Stereo, AudioMode::Mono, AudioMode::Surround,
|
||||
"sound_index", Category::SystemAudio, Specialization::Default, true,
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <bit>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@ -181,24 +182,28 @@ private:
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
static constexpr size_t subentries = 8 / sizeof(u8);
|
||||
using CounterType = u8;
|
||||
using CounterAtomicType = std::atomic_uint8_t;
|
||||
static constexpr size_t subentries = 8 / sizeof(CounterType);
|
||||
static constexpr size_t subentries_mask = subentries - 1;
|
||||
static constexpr size_t subentries_shift =
|
||||
std::countr_zero(sizeof(u64)) - std::countr_zero(sizeof(CounterType));
|
||||
class CounterEntry final {
|
||||
public:
|
||||
CounterEntry() = default;
|
||||
|
||||
std::atomic_uint8_t& Count(std::size_t page) {
|
||||
CounterAtomicType& Count(std::size_t page) {
|
||||
return values[page & subentries_mask];
|
||||
}
|
||||
|
||||
const std::atomic_uint8_t& Count(std::size_t page) const {
|
||||
const CounterAtomicType& Count(std::size_t page) const {
|
||||
return values[page & subentries_mask];
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<std::atomic_uint8_t, subentries> values{};
|
||||
std::array<CounterAtomicType, subentries> values{};
|
||||
};
|
||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(u8),
|
||||
static_assert(sizeof(CounterEntry) == subentries * sizeof(CounterType),
|
||||
"CounterEntry should be 8 bytes!");
|
||||
|
||||
static constexpr size_t num_counter_entries =
|
||||
|
@ -213,8 +213,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
||||
Asid asid, bool track) {
|
||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size, Asid asid,
|
||||
bool track) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||
@ -519,22 +519,36 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
||||
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
||||
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
||||
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
||||
auto* memory_device_inter = registered_processes[asid.id];
|
||||
const auto release_pending = [&] {
|
||||
if (uncache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||
uncache_bytes, false);
|
||||
uncache_bytes = 0;
|
||||
}
|
||||
if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||
cache_bytes, true);
|
||||
cache_bytes = 0;
|
||||
}
|
||||
};
|
||||
for (; page != page_end; ++page) {
|
||||
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
||||
CounterAtomicType& count = cached_pages->at(page >> subentries_shift).Count(page);
|
||||
auto [asid_2, vpage] = ExtractCPUBacking(page);
|
||||
vpage >>= Memory::YUZU_PAGEBITS;
|
||||
|
||||
if (delta > 0) {
|
||||
ASSERT_MSG(count.load(std::memory_order::relaxed) < std::numeric_limits<u8>::max(),
|
||||
"Count may overflow!");
|
||||
} else if (delta < 0) {
|
||||
ASSERT_MSG(count.load(std::memory_order::relaxed) > 0, "Count may underflow!");
|
||||
} else {
|
||||
ASSERT_MSG(false, "Delta must be non-zero!");
|
||||
if (vpage == 0) [[unlikely]] {
|
||||
release_pending();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (asid.id != asid_2.id) [[unlikely]] {
|
||||
release_pending();
|
||||
memory_device_inter = registered_processes[asid_2.id];
|
||||
}
|
||||
|
||||
// Adds or subtracts 1, as count is a unsigned 8-bit value
|
||||
count.fetch_add(static_cast<u8>(delta), std::memory_order_release);
|
||||
count.fetch_add(static_cast<CounterType>(delta), std::memory_order_release);
|
||||
|
||||
// Assume delta is either -1 or 1
|
||||
if (count.load(std::memory_order::relaxed) == 0) {
|
||||
@ -553,20 +567,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
}
|
||||
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||
} else if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS,
|
||||
cache_bytes, true);
|
||||
cache_bytes = 0;
|
||||
}
|
||||
vpage++;
|
||||
}
|
||||
if (uncache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
||||
false);
|
||||
}
|
||||
if (cache_bytes > 0) {
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
}
|
||||
release_pending();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
@ -207,7 +207,7 @@ void Error::Execute() {
|
||||
|
||||
void Error::DisplayCompleted() {
|
||||
complete = true;
|
||||
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>()));
|
||||
PushOutData(std::make_shared<IStorage>(system, std::vector<u8>(0x1000)));
|
||||
Exit();
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ void AOC_U::ListAddOnContent(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count,
|
||||
process_id);
|
||||
|
||||
const auto current = system.GetApplicationProcessProgramID();
|
||||
const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID());
|
||||
|
||||
std::vector<u32> out;
|
||||
const auto& disabled = Settings::values.disabled_addons[current];
|
||||
|
@ -122,14 +122,14 @@ struct RequestLayout {
|
||||
u32 domain_interface_count;
|
||||
};
|
||||
|
||||
template <ArgumentType Type1, ArgumentType Type2, typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetArgumentRawDataSize() {
|
||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetInRawDataSize() {
|
||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||
return static_cast<u32>(DataOffset);
|
||||
} else {
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == Type1 || ArgumentTraits<ArgType>::Type == Type2) {
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InData || ArgumentTraits<ArgType>::Type == ArgumentType::InProcessId) {
|
||||
constexpr size_t ArgAlign = alignof(ArgType);
|
||||
constexpr size_t ArgSize = sizeof(ArgType);
|
||||
|
||||
@ -138,9 +138,33 @@ constexpr u32 GetArgumentRawDataSize() {
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
|
||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
return GetInRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
} else {
|
||||
return GetArgumentRawDataSize<Type1, Type2, MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
return GetInRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename MethodArguments, size_t PrevAlign = 1, size_t DataOffset = 0, size_t ArgIndex = 0>
|
||||
constexpr u32 GetOutRawDataSize() {
|
||||
if constexpr (ArgIndex >= std::tuple_size_v<MethodArguments>) {
|
||||
return static_cast<u32>(DataOffset);
|
||||
} else {
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||
using RawArgType = typename ArgType::Type;
|
||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||
|
||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
|
||||
return GetOutRawDataSize<MethodArguments, ArgAlign, ArgEnd, ArgIndex + 1>();
|
||||
} else {
|
||||
return GetOutRawDataSize<MethodArguments, PrevAlign, DataOffset, ArgIndex + 1>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -165,7 +189,7 @@ constexpr RequestLayout GetNonDomainReplyInLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = 0,
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = 0,
|
||||
};
|
||||
}
|
||||
@ -175,7 +199,7 @@ constexpr RequestLayout GetDomainReplyInLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::InCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = 0,
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::InData, ArgumentType::InProcessId, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetInRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::InInterface, MethodArguments>(),
|
||||
};
|
||||
}
|
||||
@ -185,7 +209,7 @@ constexpr RequestLayout GetNonDomainReplyOutLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>() + GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = 0,
|
||||
};
|
||||
}
|
||||
@ -195,7 +219,7 @@ constexpr RequestLayout GetDomainReplyOutLayout() {
|
||||
return RequestLayout{
|
||||
.copy_handle_count = GetArgumentTypeCount<ArgumentType::OutCopyHandle, MethodArguments>(),
|
||||
.move_handle_count = GetArgumentTypeCount<ArgumentType::OutMoveHandle, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetArgumentRawDataSize<ArgumentType::OutData, ArgumentType::OutData, MethodArguments>(),
|
||||
.cmif_raw_data_size = GetOutRawDataSize<MethodArguments>(),
|
||||
.domain_interface_count = GetArgumentTypeCount<ArgumentType::OutInterface, MethodArguments>(),
|
||||
};
|
||||
}
|
||||
@ -259,7 +283,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
||||
|
||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex + 1, InBufferIndex, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
// Clear the existing data.
|
||||
std::memset(&std::get<ArgIndex>(args), 0, BufferSize);
|
||||
@ -300,7 +324,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
|
||||
|
||||
return ReadInArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, HandleIndex, InBufferIndex + 1, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
// Clear the existing data.
|
||||
std::memset(&std::get<ArgIndex>(args).raw, 0, BufferSize);
|
||||
@ -337,13 +361,15 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
||||
using ArgType = std::tuple_element_t<ArgIndex, MethodArguments>;
|
||||
|
||||
if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutData) {
|
||||
constexpr size_t ArgAlign = alignof(ArgType);
|
||||
constexpr size_t ArgSize = sizeof(ArgType);
|
||||
using RawArgType = decltype(std::get<ArgIndex>(args).raw);
|
||||
constexpr size_t ArgAlign = alignof(RawArgType);
|
||||
constexpr size_t ArgSize = sizeof(RawArgType);
|
||||
|
||||
static_assert(PrevAlign <= ArgAlign, "Output argument is not ordered by alignment");
|
||||
static_assert(!RawDataFinished, "All output interface arguments must appear after raw data");
|
||||
static_assert(!std::is_pointer_v<ArgType>, "Output raw data must not be a pointer");
|
||||
static_assert(std::is_trivially_copyable_v<decltype(std::get<ArgIndex>(args).raw)>, "Output raw data must be trivially copyable");
|
||||
static_assert(!std::is_pointer_v<RawArgType>, "Output raw data must not be a pointer");
|
||||
static_assert(std::is_trivially_copyable_v<RawArgType>, "Output raw data must be trivially copyable");
|
||||
|
||||
constexpr size_t ArgOffset = Common::AlignUp(DataOffset, ArgAlign);
|
||||
constexpr size_t ArgEnd = ArgOffset + ArgSize;
|
||||
@ -368,7 +394,7 @@ void WriteOutArgument(bool is_domain, CallArguments& args, u8* raw_data, HLERequ
|
||||
|
||||
return WriteOutArgument<MethodArguments, CallArguments, PrevAlign, DataOffset, OutBufferIndex, RawDataFinished, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
|
||||
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::OutLargeData) {
|
||||
constexpr size_t BufferSize = sizeof(ArgType);
|
||||
constexpr size_t BufferSize = sizeof(typename ArgType::Type);
|
||||
|
||||
ASSERT(ctx.CanWriteBuffer(OutBufferIndex));
|
||||
if constexpr (ArgType::Attr & BufferAttr_HipcAutoSelect) {
|
||||
|
@ -197,32 +197,27 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(
|
||||
|
||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time, InRule rule) {
|
||||
const Service::PSC::Time::CalendarTime& calendar_time,
|
||||
InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_wrapped_service->ToPosixTime(out_count, out_times, out_times_count, calendar_time, rule));
|
||||
R_RETURN(m_wrapped_service->ToPosixTime(out_count, out_times, calendar_time, rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time) {
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(
|
||||
Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
const Service::PSC::Time::CalendarTime& calendar_time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, out_times_count,
|
||||
calendar_time));
|
||||
R_RETURN(m_wrapped_service->ToPosixTimeWithMyRule(out_count, out_times, calendar_time));
|
||||
}
|
||||
|
||||
} // namespace Service::Glue::Time
|
||||
|
@ -68,12 +68,10 @@ public:
|
||||
Out<Service::PSC::Time::CalendarTime> out_calendar_time,
|
||||
Out<Service::PSC::Time::CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, Service::PSC::Time::CalendarTime& calendar_time,
|
||||
InRule rule);
|
||||
const Service::PSC::Time::CalendarTime& calendar_time, InRule rule);
|
||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count,
|
||||
Service::PSC::Time::CalendarTime& calendar_time);
|
||||
const Service::PSC::Time::CalendarTime& calendar_time);
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/hid/hid_server.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/memory.h"
|
||||
@ -153,7 +154,7 @@ IHidServer::IHidServer(Core::System& system_, std::shared_ptr<ResourceManager> r
|
||||
{104, &IHidServer::DeactivateNpad, "DeactivateNpad"},
|
||||
{106, &IHidServer::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
|
||||
{107, &IHidServer::DisconnectNpad, "DisconnectNpad"},
|
||||
{108, &IHidServer::GetPlayerLedPattern, "GetPlayerLedPattern"},
|
||||
{108, C<&IHidServer::GetPlayerLedPattern>, "GetPlayerLedPattern"},
|
||||
{109, &IHidServer::ActivateNpadWithRevision, "ActivateNpadWithRevision"},
|
||||
{120, &IHidServer::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
|
||||
{121, &IHidServer::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
|
||||
@ -1136,19 +1137,39 @@ void IHidServer::DisconnectNpad(HLERequestContext& ctx) {
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IHidServer::GetPlayerLedPattern(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||
|
||||
Core::HID::LedPattern pattern{0, 0, 0, 0};
|
||||
auto controller = GetResourceManager()->GetNpad();
|
||||
const auto result = controller->GetLedPattern(npad_id, pattern);
|
||||
|
||||
Result IHidServer::GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||
Core::HID::NpadIdType npad_id) {
|
||||
LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(result);
|
||||
rb.Push(pattern.raw);
|
||||
switch (npad_id) {
|
||||
case Core::HID::NpadIdType::Player1:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player2:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 0, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player3:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player4:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 1, 1, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player5:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 0, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player6:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 0};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player7:
|
||||
*out_led_pattern = Core::HID::LedPattern{1, 0, 1, 1};
|
||||
R_SUCCEED();
|
||||
case Core::HID::NpadIdType::Player8:
|
||||
*out_led_pattern = Core::HID::LedPattern{0, 1, 1, 0};
|
||||
R_SUCCEED();
|
||||
default:
|
||||
*out_led_pattern = Core::HID::LedPattern{0, 0, 0, 0};
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
void IHidServer::ActivateNpadWithRevision(HLERequestContext& ctx) {
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
@ -66,7 +68,8 @@ private:
|
||||
void DeactivateNpad(HLERequestContext& ctx);
|
||||
void AcquireNpadStyleSetUpdateEventHandle(HLERequestContext& ctx);
|
||||
void DisconnectNpad(HLERequestContext& ctx);
|
||||
void GetPlayerLedPattern(HLERequestContext& ctx);
|
||||
Result GetPlayerLedPattern(Out<Core::HID::LedPattern> out_led_pattern,
|
||||
Core::HID::NpadIdType npad_id);
|
||||
void ActivateNpadWithRevision(HLERequestContext& ctx);
|
||||
void SetNpadJoyHoldType(HLERequestContext& ctx);
|
||||
void GetNpadJoyHoldType(HLERequestContext& ctx);
|
||||
|
@ -83,7 +83,9 @@ SessionId Container::OpenSession(Kernel::KProcess* process) {
|
||||
|
||||
// Check if this memory block is heap.
|
||||
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
||||
if (svc_mem_info.size > region_size) {
|
||||
if (region_start + region_size == svc_mem_info.base_address) {
|
||||
region_size += svc_mem_info.size;
|
||||
} else if (svc_mem_info.size > region_size) {
|
||||
region_size = svc_mem_info.size;
|
||||
region_start = svc_mem_info.base_address;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ struct fmt::formatter<Service::PSC::Time::SteadyClockTimePoint> : fmt::formatter
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SteadyClockTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "time_point={}", time_point.time_point);
|
||||
return fmt::format_to(ctx.out(), "[time_point={}]", time_point.time_point);
|
||||
}
|
||||
};
|
||||
|
||||
@ -197,7 +197,7 @@ template <>
|
||||
struct fmt::formatter<Service::PSC::Time::SystemClockContext> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::SystemClockContext& context, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "offset={} steady_time_point={}", context.offset,
|
||||
return fmt::format_to(ctx.out(), "[offset={} steady_time_point={}]", context.offset,
|
||||
context.steady_time_point.time_point);
|
||||
}
|
||||
};
|
||||
@ -206,8 +206,9 @@ template <>
|
||||
struct fmt::formatter<Service::PSC::Time::CalendarTime> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarTime& calendar, FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "{}/{}/{} {}:{}:{}", calendar.day, calendar.month,
|
||||
calendar.year, calendar.hour, calendar.minute, calendar.second);
|
||||
return fmt::format_to(ctx.out(), "[{:02}/{:02}/{:04} {:02}:{:02}:{:02}]", calendar.day,
|
||||
calendar.month, calendar.year, calendar.hour, calendar.minute,
|
||||
calendar.second);
|
||||
}
|
||||
};
|
||||
|
||||
@ -217,7 +218,7 @@ struct fmt::formatter<Service::PSC::Time::CalendarAdditionalInfo>
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::CalendarAdditionalInfo& additional,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(), "weekday={} yearday={} name={} is_dst={} ut_offset={}",
|
||||
return fmt::format_to(ctx.out(), "[weekday={} yearday={} name={} is_dst={} ut_offset={}]",
|
||||
additional.day_of_week, additional.day_of_year,
|
||||
additional.name.data(), additional.is_dst, additional.ut_offset);
|
||||
}
|
||||
@ -227,8 +228,7 @@ template <>
|
||||
struct fmt::formatter<Service::PSC::Time::LocationName> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::LocationName& name, FormatContext& ctx) const {
|
||||
std::string_view n{name.data(), name.size()};
|
||||
return formatter<string_view>::format(n, ctx);
|
||||
return formatter<string_view>::format(name.data(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@ -236,8 +236,7 @@ template <>
|
||||
struct fmt::formatter<Service::PSC::Time::RuleVersion> : fmt::formatter<fmt::string_view> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Service::PSC::Time::RuleVersion& version, FormatContext& ctx) const {
|
||||
std::string_view v{version.data(), version.size()};
|
||||
return formatter<string_view>::format(v, ctx);
|
||||
return formatter<string_view>::format(version.data(), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
@ -247,10 +246,11 @@ struct fmt::formatter<Service::PSC::Time::ClockSnapshot> : fmt::formatter<fmt::s
|
||||
auto format(const Service::PSC::Time::ClockSnapshot& snapshot, FormatContext& ctx) const {
|
||||
return fmt::format_to(
|
||||
ctx.out(),
|
||||
"user_context={} network_context={} user_time={} network_time={} user_calendar_time={} "
|
||||
"[user_context={} network_context={} user_time={} network_time={} "
|
||||
"user_calendar_time={} "
|
||||
"network_calendar_time={} user_calendar_additional_time={} "
|
||||
"network_calendar_additional_time={} steady_clock_time_point={} location={} "
|
||||
"is_automatic_correction_enabled={} type={}",
|
||||
"is_automatic_correction_enabled={} type={}]",
|
||||
snapshot.user_context, snapshot.network_context, snapshot.user_time,
|
||||
snapshot.network_time, snapshot.user_calendar_time, snapshot.network_calendar_time,
|
||||
snapshot.user_calendar_additional_time, snapshot.network_calendar_additional_time,
|
||||
@ -266,7 +266,7 @@ struct fmt::formatter<Service::PSC::Time::ContinuousAdjustmentTimePoint>
|
||||
auto format(const Service::PSC::Time::ContinuousAdjustmentTimePoint& time_point,
|
||||
FormatContext& ctx) const {
|
||||
return fmt::format_to(ctx.out(),
|
||||
"rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}",
|
||||
"[rtc_offset={} diff_scale={} shift_amount={} lower={} upper={}]",
|
||||
time_point.rtc_offset, time_point.diff_scale, time_point.shift_amount,
|
||||
time_point.lower, time_point.upper);
|
||||
}
|
||||
|
@ -120,11 +120,8 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c
|
||||
context, context.steady_time_point.clock_source_id.RawString(), accuracy);
|
||||
|
||||
// TODO this is a hack! The network clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
if (context == Service::PSC::Time::SystemClockContext{}) {
|
||||
m_local_system_clock.GetContext(context);
|
||||
}
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock.
|
||||
m_local_system_clock.GetContext(context);
|
||||
|
||||
m_network_system_clock.SetContextWriter(m_network_system_context_writer);
|
||||
m_network_system_clock.Initialize(context, accuracy);
|
||||
@ -138,13 +135,6 @@ Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correctio
|
||||
LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}",
|
||||
automatic_correction, time_point, time_point.clock_source_id.RawString());
|
||||
|
||||
// TODO this is a hack! The user clock should be updated independently, from the ntc service
|
||||
// and maybe elsewhere. We do not do that, so fix the clock to the local clock on first boot
|
||||
// to avoid it being stuck at 0.
|
||||
if (time_point == Service::PSC::Time::SteadyClockTimePoint{}) {
|
||||
m_local_system_clock.GetCurrentTimePoint(time_point);
|
||||
}
|
||||
|
||||
m_user_system_clock.SetAutomaticCorrection(automatic_correction);
|
||||
m_user_system_clock.SetTimePointAndSignal(time_point);
|
||||
m_user_system_clock.SetInitialized();
|
||||
|
@ -140,11 +140,11 @@ Result TimeZone::ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary)
|
||||
R_RETURN(ParseBinaryImpl(out_rule, binary));
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule) {
|
||||
Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, rule, -1);
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, rule, -1);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res == ResultTimeZoneNotFound) {
|
||||
@ -158,10 +158,10 @@ Result TimeZone::ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_t
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||
u32 out_times_count, CalendarTime& calendar) {
|
||||
size_t out_times_max_count, const CalendarTime& calendar) {
|
||||
std::scoped_lock l{m_mutex};
|
||||
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_count, calendar, m_my_rule, -1);
|
||||
auto res = ToPosixTimeImpl(out_count, out_times, out_times_max_count, calendar, m_my_rule, -1);
|
||||
|
||||
if (res != ResultSuccess) {
|
||||
if (res == ResultTimeZoneNotFound) {
|
||||
@ -212,20 +212,23 @@ Result TimeZone::ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst) {
|
||||
Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times,
|
||||
size_t out_times_max_count, const CalendarTime& calendar,
|
||||
const Tz::Rule& rule, s32 is_dst) {
|
||||
R_TRY(ValidateRule(rule));
|
||||
|
||||
calendar.month -= 1;
|
||||
calendar.year -= 1900;
|
||||
CalendarTime local_calendar{calendar};
|
||||
|
||||
local_calendar.month -= 1;
|
||||
local_calendar.year -= 1900;
|
||||
|
||||
Tz::CalendarTimeInternal internal{
|
||||
.tm_sec = calendar.second,
|
||||
.tm_min = calendar.minute,
|
||||
.tm_hour = calendar.hour,
|
||||
.tm_mday = calendar.day,
|
||||
.tm_mon = calendar.month,
|
||||
.tm_year = calendar.year,
|
||||
.tm_sec = local_calendar.second,
|
||||
.tm_min = local_calendar.minute,
|
||||
.tm_hour = local_calendar.hour,
|
||||
.tm_mday = local_calendar.day,
|
||||
.tm_mon = local_calendar.month,
|
||||
.tm_year = local_calendar.year,
|
||||
.tm_wday = 0,
|
||||
.tm_yday = 0,
|
||||
.tm_isdst = is_dst,
|
||||
@ -243,9 +246,9 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o
|
||||
R_RETURN(ResultTimeZoneNotFound);
|
||||
}
|
||||
|
||||
if (internal.tm_sec != calendar.second || internal.tm_min != calendar.minute ||
|
||||
internal.tm_hour != calendar.hour || internal.tm_mday != calendar.day ||
|
||||
internal.tm_mon != calendar.month || internal.tm_year != calendar.year) {
|
||||
if (internal.tm_sec != local_calendar.second || internal.tm_min != local_calendar.minute ||
|
||||
internal.tm_hour != local_calendar.hour || internal.tm_mday != local_calendar.day ||
|
||||
internal.tm_mon != local_calendar.month || internal.tm_year != local_calendar.year) {
|
||||
R_RETURN(ResultTimeZoneNotFound);
|
||||
}
|
||||
|
||||
@ -254,7 +257,7 @@ Result TimeZone::ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 o
|
||||
}
|
||||
|
||||
out_times[0] = time;
|
||||
if (out_times_count < 2) {
|
||||
if (out_times_max_count < 2) {
|
||||
out_count = 1;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
@ -38,18 +38,18 @@ public:
|
||||
CalendarAdditionalInfo& calendar_additional, s64 time);
|
||||
Result ParseBinary(LocationName& name, std::span<const u8> binary);
|
||||
Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar);
|
||||
Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule);
|
||||
Result ToPosixTimeWithMyRule(u32& out_count, std::span<s64> out_times,
|
||||
size_t out_times_max_count, const CalendarTime& calendar);
|
||||
|
||||
private:
|
||||
Result ParseBinaryImpl(Tz::Rule& out_rule, std::span<const u8> binary);
|
||||
Result ToCalendarTimeImpl(CalendarTime& out_calendar_time,
|
||||
CalendarAdditionalInfo& out_additional_info, s64 time,
|
||||
const Tz::Rule& rule);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, u32 out_times_count,
|
||||
CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
||||
Result ToPosixTimeImpl(u32& out_count, std::span<s64> out_times, size_t out_times_max_count,
|
||||
const CalendarTime& calendar, const Tz::Rule& rule, s32 is_dst);
|
||||
|
||||
bool m_initialized{};
|
||||
std::recursive_mutex m_mutex;
|
||||
|
@ -138,32 +138,28 @@ Result TimeZoneService::ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_
|
||||
|
||||
Result TimeZoneService::ToPosixTime(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time,
|
||||
InRule rule) {
|
||||
const CalendarTime& calendar_time, InRule rule) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTime(*out_count, out_times, *out_times_count, calendar_time, *rule));
|
||||
m_time_zone.ToPosixTime(*out_count, out_times, out_times.size(), calendar_time, *rule));
|
||||
}
|
||||
|
||||
Result TimeZoneService::ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count,
|
||||
CalendarTime& calendar_time) {
|
||||
const CalendarTime& calendar_time) {
|
||||
SCOPE_EXIT({
|
||||
LOG_DEBUG(Service_Time,
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} "
|
||||
"out_times_count={}",
|
||||
calendar_time, *out_count, out_times[0], out_times[1], *out_times_count);
|
||||
"called. calendar_time={} out_count={} out_times[0]={} out_times[1]={} ",
|
||||
calendar_time, *out_count, out_times[0], out_times[1]);
|
||||
});
|
||||
|
||||
R_RETURN(
|
||||
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, *out_times_count, calendar_time));
|
||||
m_time_zone.ToPosixTimeWithMyRule(*out_count, out_times, out_times.size(), calendar_time));
|
||||
}
|
||||
|
||||
} // namespace Service::PSC::Time
|
||||
|
@ -50,10 +50,10 @@ public:
|
||||
Result ToCalendarTimeWithMyRule(Out<CalendarTime> out_calendar_time,
|
||||
Out<CalendarAdditionalInfo> out_additional_info, s64 time);
|
||||
Result ToPosixTime(Out<u32> out_count, OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time, InRule rule);
|
||||
const CalendarTime& calendar_time, InRule rule);
|
||||
Result ToPosixTimeWithMyRule(Out<u32> out_count,
|
||||
OutArray<s64, BufferAttr_HipcPointer> out_times,
|
||||
Out<u32> out_times_count, CalendarTime& calendar_time);
|
||||
const CalendarTime& calendar_time);
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
|
@ -25,7 +25,7 @@
|
||||
namespace Service::Set {
|
||||
|
||||
namespace {
|
||||
constexpr u32 SETTINGS_VERSION{2u};
|
||||
constexpr u32 SETTINGS_VERSION{3u};
|
||||
constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't');
|
||||
struct SettingsHeader {
|
||||
u64 magic;
|
||||
|
@ -24,6 +24,7 @@ enum class Errno : u32 {
|
||||
CONNRESET = 104,
|
||||
NOTCONN = 107,
|
||||
TIMEDOUT = 110,
|
||||
CONNREFUSED = 111,
|
||||
INPROGRESS = 115,
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,8 @@ Errno Translate(Network::Errno value) {
|
||||
return Errno::MFILE;
|
||||
case Network::Errno::PIPE:
|
||||
return Errno::PIPE;
|
||||
case Network::Errno::CONNREFUSED:
|
||||
return Errno::CONNREFUSED;
|
||||
case Network::Errno::NOTCONN:
|
||||
return Errno::NOTCONN;
|
||||
case Network::Errno::TIMEDOUT:
|
||||
|
@ -693,20 +693,23 @@ std::pair<SocketBase::AcceptResult, Errno> Socket::Accept() {
|
||||
sockaddr_in addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
|
||||
std::vector<WSAPOLLFD> host_pollfds{
|
||||
WSAPOLLFD{fd, POLLIN, 0},
|
||||
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
|
||||
};
|
||||
const bool wait_for_accept = !is_non_blocking;
|
||||
if (wait_for_accept) {
|
||||
std::vector<WSAPOLLFD> host_pollfds{
|
||||
WSAPOLLFD{fd, POLLIN, 0},
|
||||
WSAPOLLFD{GetInterruptSocket(), POLLIN, 0},
|
||||
};
|
||||
|
||||
while (true) {
|
||||
const int pollres =
|
||||
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
|
||||
if (host_pollfds[1].revents != 0) {
|
||||
// Interrupt signaled before a client could be accepted, break
|
||||
return {AcceptResult{}, Errno::AGAIN};
|
||||
}
|
||||
if (pollres > 0) {
|
||||
break;
|
||||
while (true) {
|
||||
const int pollres =
|
||||
WSAPoll(host_pollfds.data(), static_cast<ULONG>(host_pollfds.size()), -1);
|
||||
if (host_pollfds[1].revents != 0) {
|
||||
// Interrupt signaled before a client could be accepted, break
|
||||
return {AcceptResult{}, Errno::AGAIN};
|
||||
}
|
||||
if (pollres > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,6 +916,7 @@ Errno Socket::SetRcvTimeo(u32 value) {
|
||||
|
||||
Errno Socket::SetNonBlock(bool enable) {
|
||||
if (EnableNonBlock(fd, enable)) {
|
||||
is_non_blocking = enable;
|
||||
return Errno::SUCCESS;
|
||||
}
|
||||
return GetAndLogLastError();
|
||||
|
@ -166,6 +166,9 @@ public:
|
||||
bool IsOpened() const override;
|
||||
|
||||
void HandleProxyPacket(const ProxyPacket& packet) override;
|
||||
|
||||
private:
|
||||
bool is_non_blocking = false;
|
||||
};
|
||||
|
||||
std::pair<s32, Errno> Poll(std::vector<PollFD>& poll_fds, s32 timeout);
|
||||
|
@ -1091,20 +1091,6 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
|
||||
[&] { rasterizer = true; });
|
||||
if (rasterizer) {
|
||||
impl->InvalidateGPUMemory(ptr, size);
|
||||
|
||||
const auto type = impl->current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type();
|
||||
if (type == Common::PageType::RasterizerCachedMemory) {
|
||||
// Check if device mapped. If not, this bugged and we can unmark.
|
||||
DAddr addr{};
|
||||
Common::ScratchBuffer<u32> buffer;
|
||||
impl->gpu_device_memory->ApplyOpOnPointer(ptr, buffer,
|
||||
[&](DAddr address) { addr = address; });
|
||||
|
||||
if (addr == 0) {
|
||||
LOG_ERROR(HW_Memory, "Fixing unmapped cached region {:#x}", GetInteger(vaddr));
|
||||
impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -422,7 +422,10 @@ struct NpadPowerInfo {
|
||||
static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size");
|
||||
|
||||
struct LedPattern {
|
||||
explicit LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||
LedPattern() {
|
||||
raw = 0;
|
||||
}
|
||||
LedPattern(u64 light1, u64 light2, u64 light3, u64 light4) {
|
||||
position1.Assign(light1);
|
||||
position2.Assign(light2);
|
||||
position3.Assign(light3);
|
||||
|
@ -956,17 +956,6 @@ Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1,
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
|
||||
if (!IsNpadIdValid(npad_id)) {
|
||||
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
|
||||
return ResultInvalidNpadId;
|
||||
}
|
||||
const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
|
||||
const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device;
|
||||
pattern = controller->GetLedPattern();
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||
Core::HID::NpadIdType npad_id) const {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
@ -97,8 +97,6 @@ public:
|
||||
Result ResetIsSixAxisSensorDeviceNewlyAssigned(
|
||||
u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle);
|
||||
|
||||
Result GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
|
||||
|
||||
Result IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
|
||||
Core::HID::NpadIdType npad_id) const;
|
||||
Result EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
|
||||
|
@ -243,12 +243,10 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
|
||||
const u64 size_in_bytes{Tegra::Texture::CalculateSize(
|
||||
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
|
||||
const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
|
||||
if (host_ptr != nullptr) {
|
||||
const std::span<const u8> input_data(host_ptr, size_in_bytes);
|
||||
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
|
||||
framebuffer.width, framebuffer.height, 1,
|
||||
block_height_log2, 0);
|
||||
}
|
||||
const std::span<const u8> input_data(host_ptr, size_in_bytes);
|
||||
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
|
||||
framebuffer.width, framebuffer.height, 1, block_height_log2,
|
||||
0);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));
|
||||
|
@ -230,11 +230,9 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
|
||||
const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
|
||||
framebuffer.stride, framebuffer.height,
|
||||
1, block_height_log2, 0)};
|
||||
if (host_ptr != nullptr) {
|
||||
Tegra::Texture::UnswizzleTexture(
|
||||
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
|
||||
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
|
||||
}
|
||||
Tegra::Texture::UnswizzleTexture(
|
||||
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
|
||||
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
|
||||
|
||||
const VkBufferImageCopy copy{
|
||||
.bufferOffset = image_offset,
|
||||
|
@ -1431,7 +1431,7 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA
|
||||
}
|
||||
}
|
||||
};
|
||||
ForEachSparseImageInRegion(gpu_addr, size_bytes, region_check_gpu);
|
||||
ForEachSparseImageInRegion(channel_state->gpu_memory.GetID(), gpu_addr, size_bytes, region_check_gpu);
|
||||
|
||||
bool can_rescale = info.rescaleable;
|
||||
bool any_rescaled = false;
|
||||
@ -1842,7 +1842,7 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
||||
if (!storage_id) {
|
||||
return;
|
||||
}
|
||||
auto& gpu_page_table = gpu_page_table_storage[*storage_id];
|
||||
auto& gpu_page_table = gpu_page_table_storage[*storage_id * 2];
|
||||
ForEachGPUPage(gpu_addr, size,
|
||||
[this, &gpu_page_table, &images, gpu_addr, size, func](u64 page) {
|
||||
const auto it = gpu_page_table.find(page);
|
||||
@ -1882,11 +1882,17 @@ void TextureCache<P>::ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, s
|
||||
|
||||
template <class P>
|
||||
template <typename Func>
|
||||
void TextureCache<P>::ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func) {
|
||||
void TextureCache<P>::ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size,
|
||||
Func&& func) {
|
||||
using FuncReturn = typename std::invoke_result<Func, ImageId, Image&>::type;
|
||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||
boost::container::small_vector<ImageId, 8> images;
|
||||
ForEachGPUPage(gpu_addr, size, [this, &images, gpu_addr, size, func](u64 page) {
|
||||
auto storage_id = getStorageID(as_id);
|
||||
if (!storage_id) {
|
||||
return;
|
||||
}
|
||||
auto& sparse_page_table = gpu_page_table_storage[*storage_id * 2 + 1];
|
||||
ForEachGPUPage(gpu_addr, size, [this, &sparse_page_table, &images, gpu_addr, size, func](u64 page) {
|
||||
const auto it = sparse_page_table.find(page);
|
||||
if (it == sparse_page_table.end()) {
|
||||
if constexpr (BOOL_BREAK) {
|
||||
@ -1989,7 +1995,7 @@ void TextureCache<P>::RegisterImage(ImageId image_id) {
|
||||
});
|
||||
sparse_views.emplace(image_id, std::move(sparse_maps));
|
||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes,
|
||||
[this, image_id](u64 page) { sparse_page_table[page].push_back(image_id); });
|
||||
[this, image_id](u64 page) { (*channel_state->sparse_page_table)[page].push_back(image_id); });
|
||||
}
|
||||
|
||||
template <class P>
|
||||
@ -2042,7 +2048,7 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) {
|
||||
return;
|
||||
}
|
||||
ForEachGPUPage(image.gpu_addr, image.guest_size_bytes, [this, &clear_page_table](u64 page) {
|
||||
clear_page_table(page, sparse_page_table);
|
||||
clear_page_table(page, (*channel_state->sparse_page_table));
|
||||
});
|
||||
auto it = sparse_views.find(image_id);
|
||||
ASSERT(it != sparse_views.end());
|
||||
@ -2496,13 +2502,15 @@ void TextureCache<P>::CreateChannel(struct Tegra::Control::ChannelState& channel
|
||||
const auto it = channel_map.find(channel.bind_id);
|
||||
auto* this_state = &channel_storage[it->second];
|
||||
const auto& this_as_ref = address_spaces[channel.memory_manager->GetID()];
|
||||
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id];
|
||||
this_state->gpu_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2];
|
||||
this_state->sparse_page_table = &gpu_page_table_storage[this_as_ref.storage_id * 2 + 1];
|
||||
}
|
||||
|
||||
/// Bind a channel for execution.
|
||||
template <class P>
|
||||
void TextureCache<P>::OnGPUASRegister([[maybe_unused]] size_t map_id) {
|
||||
gpu_page_table_storage.emplace_back();
|
||||
gpu_page_table_storage.emplace_back();
|
||||
}
|
||||
|
||||
} // namespace VideoCommon
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
std::unordered_map<TSCEntry, SamplerId> samplers;
|
||||
|
||||
TextureCacheGPUMap* gpu_page_table;
|
||||
TextureCacheGPUMap* sparse_page_table;
|
||||
};
|
||||
|
||||
template <class P>
|
||||
@ -357,7 +358,7 @@ private:
|
||||
void ForEachImageInRegionGPU(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||
|
||||
template <typename Func>
|
||||
void ForEachSparseImageInRegion(GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||
void ForEachSparseImageInRegion(size_t as_id, GPUVAddr gpu_addr, size_t size, Func&& func);
|
||||
|
||||
/// Iterates over all the images in a region calling func
|
||||
template <typename Func>
|
||||
@ -431,7 +432,6 @@ private:
|
||||
std::unordered_map<RenderTargets, FramebufferId> framebuffers;
|
||||
|
||||
std::unordered_map<u64, std::vector<ImageMapId>, Common::IdentityHash<u64>> page_table;
|
||||
std::unordered_map<u64, std::vector<ImageId>, Common::IdentityHash<u64>> sparse_page_table;
|
||||
std::unordered_map<ImageId, boost::container::small_vector<ImageViewId, 16>> sparse_views;
|
||||
|
||||
DAddr virtual_invalid_space{};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <QComboBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "audio_core/sink/sink.h"
|
||||
#include "audio_core/sink/sink_details.h"
|
||||
@ -67,19 +68,99 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
|
||||
|
||||
hold.emplace(std::pair{setting->Id(), widget});
|
||||
|
||||
auto global_sink_match = [this] {
|
||||
return static_cast<Settings::AudioEngine>(sink_combo_box->currentIndex()) ==
|
||||
Settings::values.sink_id.GetValue(true);
|
||||
};
|
||||
if (setting->Id() == Settings::values.sink_id.Id()) {
|
||||
// TODO (lat9nq): Let the system manage sink_id
|
||||
sink_combo_box = widget->combobox;
|
||||
InitializeAudioSinkComboBox();
|
||||
|
||||
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&ConfigureAudio::UpdateAudioDevices);
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&ConfigureAudio::UpdateAudioDevices);
|
||||
} else {
|
||||
restore_sink_button = ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||
Settings::values.sink_id.UsingGlobal(), widget);
|
||||
widget->layout()->addWidget(restore_sink_button);
|
||||
connect(restore_sink_button, &QAbstractButton::clicked, [this](bool) {
|
||||
Settings::values.sink_id.SetGlobal(true);
|
||||
const int sink_index = static_cast<int>(Settings::values.sink_id.GetValue());
|
||||
sink_combo_box->setCurrentIndex(sink_index);
|
||||
ConfigureAudio::UpdateAudioDevices(sink_index);
|
||||
Settings::values.audio_output_device_id.SetGlobal(true);
|
||||
Settings::values.audio_input_device_id.SetGlobal(true);
|
||||
restore_sink_button->setVisible(false);
|
||||
});
|
||||
connect(sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this, global_sink_match](const int slot) {
|
||||
Settings::values.sink_id.SetGlobal(false);
|
||||
Settings::values.audio_output_device_id.SetGlobal(false);
|
||||
Settings::values.audio_input_device_id.SetGlobal(false);
|
||||
|
||||
restore_sink_button->setVisible(true);
|
||||
restore_sink_button->setEnabled(true);
|
||||
output_device_combo_box->setCurrentIndex(0);
|
||||
restore_output_device_button->setVisible(true);
|
||||
restore_output_device_button->setEnabled(global_sink_match());
|
||||
input_device_combo_box->setCurrentIndex(0);
|
||||
restore_input_device_button->setVisible(true);
|
||||
restore_input_device_button->setEnabled(global_sink_match());
|
||||
ConfigureAudio::UpdateAudioDevices(slot);
|
||||
});
|
||||
}
|
||||
} else if (setting->Id() == Settings::values.audio_output_device_id.Id()) {
|
||||
// Keep track of output (and input) device comboboxes to populate them with system
|
||||
// devices, which are determined at run time
|
||||
output_device_combo_box = widget->combobox;
|
||||
|
||||
if (!Settings::IsConfiguringGlobal()) {
|
||||
restore_output_device_button =
|
||||
ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||
Settings::values.audio_output_device_id.UsingGlobal(), widget);
|
||||
restore_output_device_button->setEnabled(global_sink_match());
|
||||
restore_output_device_button->setVisible(
|
||||
!Settings::values.audio_output_device_id.UsingGlobal());
|
||||
widget->layout()->addWidget(restore_output_device_button);
|
||||
connect(restore_output_device_button, &QAbstractButton::clicked, [this](bool) {
|
||||
Settings::values.audio_output_device_id.SetGlobal(true);
|
||||
SetOutputDevicesFromDeviceID();
|
||||
restore_output_device_button->setVisible(false);
|
||||
});
|
||||
connect(output_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this, global_sink_match](int) {
|
||||
if (updating_devices) {
|
||||
return;
|
||||
}
|
||||
Settings::values.audio_output_device_id.SetGlobal(false);
|
||||
restore_output_device_button->setVisible(true);
|
||||
restore_output_device_button->setEnabled(global_sink_match());
|
||||
});
|
||||
}
|
||||
} else if (setting->Id() == Settings::values.audio_input_device_id.Id()) {
|
||||
input_device_combo_box = widget->combobox;
|
||||
|
||||
if (!Settings::IsConfiguringGlobal()) {
|
||||
restore_input_device_button =
|
||||
ConfigurationShared::Widget::CreateRestoreGlobalButton(
|
||||
Settings::values.audio_input_device_id.UsingGlobal(), widget);
|
||||
widget->layout()->addWidget(restore_input_device_button);
|
||||
connect(restore_input_device_button, &QAbstractButton::clicked, [this](bool) {
|
||||
Settings::values.audio_input_device_id.SetGlobal(true);
|
||||
SetInputDevicesFromDeviceID();
|
||||
restore_input_device_button->setVisible(false);
|
||||
});
|
||||
connect(input_device_combo_box, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
[this, global_sink_match](int) {
|
||||
if (updating_devices) {
|
||||
return;
|
||||
}
|
||||
Settings::values.audio_input_device_id.SetGlobal(false);
|
||||
restore_input_device_button->setVisible(true);
|
||||
restore_input_device_button->setEnabled(global_sink_match());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,16 +170,13 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
|
||||
}
|
||||
|
||||
void ConfigureAudio::SetConfiguration() {
|
||||
if (!Settings::IsConfiguringGlobal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetOutputSinkFromSinkID();
|
||||
|
||||
// The device list cannot be pre-populated (nor listed) until the output sink is known.
|
||||
UpdateAudioDevices(sink_combo_box->currentIndex());
|
||||
|
||||
SetAudioDevicesFromDeviceID();
|
||||
SetOutputDevicesFromDeviceID();
|
||||
SetInputDevicesFromDeviceID();
|
||||
}
|
||||
|
||||
void ConfigureAudio::SetOutputSinkFromSinkID() {
|
||||
@ -116,8 +194,8 @@ void ConfigureAudio::SetOutputSinkFromSinkID() {
|
||||
sink_combo_box->setCurrentIndex(new_sink_index);
|
||||
}
|
||||
|
||||
void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
||||
int new_device_index = -1;
|
||||
void ConfigureAudio::SetOutputDevicesFromDeviceID() {
|
||||
int new_device_index = 0;
|
||||
|
||||
const QString output_device_id =
|
||||
QString::fromStdString(Settings::values.audio_output_device_id.GetValue());
|
||||
@ -129,8 +207,10 @@ void ConfigureAudio::SetAudioDevicesFromDeviceID() {
|
||||
}
|
||||
|
||||
output_device_combo_box->setCurrentIndex(new_device_index);
|
||||
}
|
||||
|
||||
new_device_index = -1;
|
||||
void ConfigureAudio::SetInputDevicesFromDeviceID() {
|
||||
int new_device_index = 0;
|
||||
const QString input_device_id =
|
||||
QString::fromStdString(Settings::values.audio_input_device_id.GetValue());
|
||||
for (int index = 0; index < input_device_combo_box->count(); index++) {
|
||||
@ -149,15 +229,12 @@ void ConfigureAudio::ApplyConfiguration() {
|
||||
apply_func(is_powered_on);
|
||||
}
|
||||
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
Settings::values.sink_id.LoadString(
|
||||
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
||||
Settings::values.audio_output_device_id.SetValue(
|
||||
output_device_combo_box->itemText(output_device_combo_box->currentIndex())
|
||||
.toStdString());
|
||||
Settings::values.audio_input_device_id.SetValue(
|
||||
input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
|
||||
}
|
||||
Settings::values.sink_id.LoadString(
|
||||
sink_combo_box->itemText(sink_combo_box->currentIndex()).toStdString());
|
||||
Settings::values.audio_output_device_id.SetValue(
|
||||
output_device_combo_box->itemText(output_device_combo_box->currentIndex()).toStdString());
|
||||
Settings::values.audio_input_device_id.SetValue(
|
||||
input_device_combo_box->itemText(input_device_combo_box->currentIndex()).toStdString());
|
||||
}
|
||||
|
||||
void ConfigureAudio::changeEvent(QEvent* event) {
|
||||
@ -169,6 +246,7 @@ void ConfigureAudio::changeEvent(QEvent* event) {
|
||||
}
|
||||
|
||||
void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
||||
updating_devices = true;
|
||||
output_device_combo_box->clear();
|
||||
output_device_combo_box->addItem(QString::fromUtf8(AudioCore::Sink::auto_device_name));
|
||||
|
||||
@ -183,6 +261,7 @@ void ConfigureAudio::UpdateAudioDevices(int sink_index) {
|
||||
for (const auto& device : AudioCore::Sink::GetDeviceListForSink(sink_id, true)) {
|
||||
input_device_combo_box->addItem(QString::fromStdString(device));
|
||||
}
|
||||
updating_devices = false;
|
||||
}
|
||||
|
||||
void ConfigureAudio::InitializeAudioSinkComboBox() {
|
||||
|
@ -45,7 +45,8 @@ private:
|
||||
void UpdateAudioDevices(int sink_index);
|
||||
|
||||
void SetOutputSinkFromSinkID();
|
||||
void SetAudioDevicesFromDeviceID();
|
||||
void SetOutputDevicesFromDeviceID();
|
||||
void SetInputDevicesFromDeviceID();
|
||||
|
||||
void Setup(const ConfigurationShared::Builder& builder);
|
||||
|
||||
@ -55,7 +56,11 @@ private:
|
||||
|
||||
std::vector<std::function<void(bool)>> apply_funcs{};
|
||||
|
||||
bool updating_devices = false;
|
||||
QComboBox* sink_combo_box;
|
||||
QPushButton* restore_sink_button;
|
||||
QComboBox* output_device_combo_box;
|
||||
QPushButton* restore_output_device_button;
|
||||
QComboBox* input_device_combo_box;
|
||||
QPushButton* restore_input_device_button;
|
||||
};
|
||||
|
Reference in New Issue
Block a user