summaryrefslogtreecommitdiff
path: root/src/yuzu
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu')
-rw-r--r--src/yuzu/applets/qt_controller.cpp52
-rw-r--r--src/yuzu/applets/qt_controller.h4
-rw-r--r--src/yuzu/configuration/configure_input.cpp59
-rw-r--r--src/yuzu/configuration/configure_input.h7
-rw-r--r--src/yuzu/configuration/configure_input_player.h5
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
-rw-r--r--src/yuzu/game_list.cpp26
-rw-r--r--src/yuzu/game_list.h10
-rw-r--r--src/yuzu/game_list_worker.cpp102
-rw-r--r--src/yuzu/game_list_worker.h35
-rw-r--r--src/yuzu/main.cpp2
11 files changed, 201 insertions, 103 deletions
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index ca0e14fad..515cb7ce6 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -155,18 +155,27 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
UpdateBorderColor(i);
connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) {
- if (checked) {
- // Hide eventual error message about number of controllers
- ui->labelError->setVisible(false);
- for (std::size_t index = 0; index <= i; ++index) {
- connected_controller_checkboxes[index]->setChecked(checked);
- }
- } else {
- for (std::size_t index = i; index < NUM_PLAYERS; ++index) {
- connected_controller_checkboxes[index]->setChecked(checked);
- }
+ // Reconnect current controller if it was the last one checked
+ // (player number was reduced by more than one)
+ const bool reconnect_first = !checked && i < player_groupboxes.size() - 1 &&
+ player_groupboxes[i + 1]->isChecked();
+
+ // Ensures that connecting a controller changes the number of players
+ if (connected_controller_checkboxes[i]->isChecked() != checked) {
+ // Ensures that the players are always connected in sequential order
+ PropagatePlayerNumberChanged(i, checked, reconnect_first);
}
});
+ connect(connected_controller_checkboxes[i], &QCheckBox::clicked, [this, i](bool checked) {
+ // Reconnect current controller if it was the last one checked
+ // (player number was reduced by more than one)
+ const bool reconnect_first = !checked &&
+ i < connected_controller_checkboxes.size() - 1 &&
+ connected_controller_checkboxes[i + 1]->isChecked();
+
+ // Ensures that the players are always connected in sequential order
+ PropagatePlayerNumberChanged(i, checked, reconnect_first);
+ });
connect(emulated_controllers[i], qOverload<int>(&QComboBox::currentIndexChanged),
[this, i](int) {
@@ -668,6 +677,29 @@ void QtControllerSelectorDialog::UpdateDockedState(bool is_handheld) {
}
}
+void QtControllerSelectorDialog::PropagatePlayerNumberChanged(size_t player_index, bool checked,
+ bool reconnect_current) {
+ connected_controller_checkboxes[player_index]->setChecked(checked);
+ // Hide eventual error message about number of controllers
+ ui->labelError->setVisible(false);
+
+ if (checked) {
+ // Check all previous buttons when checked
+ if (player_index > 0) {
+ PropagatePlayerNumberChanged(player_index - 1, checked);
+ }
+ } else {
+ // Unchecked all following buttons when unchecked
+ if (player_index < connected_controller_checkboxes.size() - 1) {
+ PropagatePlayerNumberChanged(player_index + 1, checked);
+ }
+ }
+
+ if (reconnect_current) {
+ connected_controller_checkboxes[player_index]->setCheckState(Qt::Checked);
+ }
+}
+
void QtControllerSelectorDialog::DisableUnsupportedPlayers() {
const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h
index 7f0673d06..e5372495d 100644
--- a/src/yuzu/applets/qt_controller.h
+++ b/src/yuzu/applets/qt_controller.h
@@ -100,6 +100,10 @@ private:
// Updates the console mode.
void UpdateDockedState(bool is_handheld);
+ // Enable preceding controllers or disable following ones
+ void PropagatePlayerNumberChanged(size_t player_index, bool checked,
+ bool reconnect_current = false);
+
// Disables and disconnects unsupported players based on the given parameters.
void DisableUnsupportedPlayers();
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 5a48e388b..3dcad2701 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -101,13 +101,13 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
ui->tabPlayer5, ui->tabPlayer6, ui->tabPlayer7, ui->tabPlayer8,
};
- player_connected = {
+ connected_controller_checkboxes = {
ui->checkboxPlayer1Connected, ui->checkboxPlayer2Connected, ui->checkboxPlayer3Connected,
ui->checkboxPlayer4Connected, ui->checkboxPlayer5Connected, ui->checkboxPlayer6Connected,
ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
};
- std::array<QLabel*, 8> player_connected_labels = {
+ std::array<QLabel*, 8> connected_controller_labels = {
ui->label, ui->label_3, ui->label_4, ui->label_5,
ui->label_6, ui->label_7, ui->label_8, ui->label_9,
};
@@ -115,23 +115,37 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
for (std::size_t i = 0; i < player_tabs.size(); ++i) {
player_tabs[i]->setLayout(new QHBoxLayout(player_tabs[i]));
player_tabs[i]->layout()->addWidget(player_controllers[i]);
- connect(player_connected[i], &QCheckBox::clicked, [this, i](int checked) {
- // Ensures that the controllers are always connected in sequential order
- this->propagateMouseClickOnPlayers(i, checked, true);
+ connect(player_controllers[i], &ConfigureInputPlayer::Connected, [this, i](bool checked) {
+ // Ensures that connecting a controller changes the number of players
+ if (connected_controller_checkboxes[i]->isChecked() != checked) {
+ // Ensures that the players are always connected in sequential order
+ PropagatePlayerNumberChanged(i, checked);
+ }
+ });
+ connect(connected_controller_checkboxes[i], &QCheckBox::clicked, [this, i](bool checked) {
+ // Reconnect current controller if it was the last one checked
+ // (player number was reduced by more than one)
+ const bool reconnect_first = !checked &&
+ i < connected_controller_checkboxes.size() - 1 &&
+ connected_controller_checkboxes[i + 1]->isChecked();
+
+ // Ensures that the players are always connected in sequential order
+ PropagatePlayerNumberChanged(i, checked, reconnect_first);
});
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputDevices, this,
&ConfigureInput::UpdateAllInputDevices);
connect(player_controllers[i], &ConfigureInputPlayer::RefreshInputProfiles, this,
&ConfigureInput::UpdateAllInputProfiles, Qt::QueuedConnection);
- connect(player_connected[i], &QCheckBox::stateChanged, [this, i](int state) {
+ connect(connected_controller_checkboxes[i], &QCheckBox::stateChanged, [this, i](int state) {
+ // Keep activated controllers synced with the "Connected Controllers" checkboxes
player_controllers[i]->ConnectPlayer(state == Qt::Checked);
});
// Remove/hide all the elements that exceed max_players, if applicable.
if (i >= max_players) {
ui->tabWidget->removeTab(static_cast<int>(max_players));
- player_connected[i]->hide();
- player_connected_labels[i]->hide();
+ connected_controller_checkboxes[i]->hide();
+ connected_controller_labels[i]->hide();
}
}
// Only the first player can choose handheld mode so connect the signal just to player 1
@@ -175,28 +189,25 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
LoadConfiguration();
}
-void ConfigureInput::propagateMouseClickOnPlayers(size_t player_index, bool checked, bool origin) {
- // Origin has already been toggled
- if (!origin) {
- player_connected[player_index]->setChecked(checked);
- }
+void ConfigureInput::PropagatePlayerNumberChanged(size_t player_index, bool checked,
+ bool reconnect_current) {
+ connected_controller_checkboxes[player_index]->setChecked(checked);
if (checked) {
// Check all previous buttons when checked
if (player_index > 0) {
- propagateMouseClickOnPlayers(player_index - 1, checked, false);
+ PropagatePlayerNumberChanged(player_index - 1, checked);
}
} else {
// Unchecked all following buttons when unchecked
- if (player_index < player_tabs.size() - 1) {
- // Reconnect current player if it was the last one checked
- // (player number was reduced by more than one)
- if (origin && player_connected[player_index + 1]->checkState() == Qt::Checked) {
- player_connected[player_index]->setCheckState(Qt::Checked);
- }
- propagateMouseClickOnPlayers(player_index + 1, checked, false);
+ if (player_index < connected_controller_checkboxes.size() - 1) {
+ PropagatePlayerNumberChanged(player_index + 1, checked);
}
}
+
+ if (reconnect_current) {
+ connected_controller_checkboxes[player_index]->setCheckState(Qt::Checked);
+ }
}
QList<QWidget*> ConfigureInput::GetSubTabs() const {
@@ -249,17 +260,17 @@ void ConfigureInput::LoadConfiguration() {
}
void ConfigureInput::LoadPlayerControllerIndices() {
- for (std::size_t i = 0; i < player_connected.size(); ++i) {
+ for (std::size_t i = 0; i < connected_controller_checkboxes.size(); ++i) {
if (i == 0) {
auto* handheld =
system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
if (handheld->IsConnected()) {
- player_connected[i]->setChecked(true);
+ connected_controller_checkboxes[i]->setChecked(true);
continue;
}
}
const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(i);
- player_connected[i]->setChecked(controller->IsConnected());
+ connected_controller_checkboxes[i]->setChecked(controller->IsConnected());
}
}
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h
index abb7f7089..136cd3a0a 100644
--- a/src/yuzu/configuration/configure_input.h
+++ b/src/yuzu/configuration/configure_input.h
@@ -56,7 +56,9 @@ private:
void UpdateDockedState(bool is_handheld);
void UpdateAllInputDevices();
void UpdateAllInputProfiles(std::size_t player_index);
- void propagateMouseClickOnPlayers(size_t player_index, bool origin, bool checked);
+ // Enable preceding controllers or disable following ones
+ void PropagatePlayerNumberChanged(size_t player_index, bool checked,
+ bool reconnect_current = false);
/// Load configuration settings.
void LoadConfiguration();
@@ -71,7 +73,8 @@ private:
std::array<ConfigureInputPlayer*, 8> player_controllers;
std::array<QWidget*, 8> player_tabs;
- std::array<QCheckBox*, 8> player_connected;
+ // Checkboxes representing the "Connected Controllers".
+ std::array<QCheckBox*, 8> connected_controller_checkboxes;
ConfigureInputAdvanced* advanced;
Core::System& system;
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h
index d4df43d73..d3255d2b4 100644
--- a/src/yuzu/configuration/configure_input_player.h
+++ b/src/yuzu/configuration/configure_input_player.h
@@ -75,7 +75,7 @@ public:
void ClearAll();
signals:
- /// Emitted when this controller is connected by the user.
+ /// Emitted when this controller is (dis)connected by the user.
void Connected(bool connected);
/// Emitted when the Handheld mode is selected (undocked with dual joycons attached).
void HandheldStateChanged(bool is_handheld);
@@ -183,9 +183,6 @@ private:
/// Stores a pair of "Connected Controllers" combobox index and Controller Type enum.
std::vector<std::pair<int, Core::HID::NpadStyleIndex>> index_controller_type_pairs;
- static constexpr int PLAYER_COUNT = 8;
- std::array<QCheckBox*, PLAYER_COUNT> player_connected_checkbox;
-
/// This will be the the setting function when an input is awaiting configuration.
std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0783a2430..7049c57b6 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -127,7 +127,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons
return list;
}
- if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64BitProcess()) {
+ if (thread.GetOwnerProcess() == nullptr || !thread.GetOwnerProcess()->Is64Bit()) {
return list;
}
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp
index 2bb1a0239..7e7d8e252 100644
--- a/src/yuzu/game_list.cpp
+++ b/src/yuzu/game_list.cpp
@@ -380,7 +380,6 @@ void GameList::UnloadController() {
GameList::~GameList() {
UnloadController();
- emit ShouldCancelWorker();
}
void GameList::SetFilterFocus() {
@@ -397,6 +396,10 @@ void GameList::ClearFilter() {
search_field->clear();
}
+void GameList::WorkerEvent() {
+ current_worker->ProcessEvents(this);
+}
+
void GameList::AddDirEntry(GameListDir* entry_items) {
item_model->invisibleRootItem()->appendRow(entry_items);
tree_view->setExpanded(
@@ -826,28 +829,21 @@ void GameList::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
tree_view->setColumnHidden(COLUMN_SIZE, !UISettings::values.show_size);
tree_view->setColumnHidden(COLUMN_PLAY_TIME, !UISettings::values.show_play_time);
- // Before deleting rows, cancel the worker so that it is not using them
- emit ShouldCancelWorker();
+ // Cancel any existing worker.
+ current_worker.reset();
// Delete any rows that might already exist if we're repopulating
item_model->removeRows(0, item_model->rowCount());
search_field->clear();
- GameListWorker* worker =
- new GameListWorker(vfs, provider, game_dirs, compatibility_list, play_time_manager, system);
+ current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, compatibility_list,
+ play_time_manager, system);
- connect(worker, &GameListWorker::EntryReady, this, &GameList::AddEntry, Qt::QueuedConnection);
- connect(worker, &GameListWorker::DirEntryReady, this, &GameList::AddDirEntry,
- Qt::QueuedConnection);
- connect(worker, &GameListWorker::Finished, this, &GameList::DonePopulating,
+ // Get events from the worker as data becomes available
+ connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameList::WorkerEvent,
Qt::QueuedConnection);
- // Use DirectConnection here because worker->Cancel() is thread-safe and we want it to
- // cancel without delay.
- connect(this, &GameList::ShouldCancelWorker, worker, &GameListWorker::Cancel,
- Qt::DirectConnection);
- QThreadPool::globalInstance()->start(worker);
- current_worker = std::move(worker);
+ QThreadPool::globalInstance()->start(current_worker.get());
}
void GameList::SaveInterfaceLayout() {
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h
index 712570cea..563a3a35b 100644
--- a/src/yuzu/game_list.h
+++ b/src/yuzu/game_list.h
@@ -109,7 +109,6 @@ signals:
void BootGame(const QString& game_path, u64 program_id, std::size_t program_index,
StartGameType type, AmLaunchType launch_type);
void GameChosen(const QString& game_path, const u64 title_id = 0);
- void ShouldCancelWorker();
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,
const std::string& game_path);
void OpenTransferableShaderCacheRequested(u64 program_id);
@@ -138,11 +137,16 @@ private slots:
void OnUpdateThemedIcons();
private:
+ friend class GameListWorker;
+ void WorkerEvent();
+
void AddDirEntry(GameListDir* entry_items);
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
- void ValidateEntry(const QModelIndex& item);
void DonePopulating(const QStringList& watch_list);
+private:
+ void ValidateEntry(const QModelIndex& item);
+
void RefreshGameDirectory();
void ToggleFavorite(u64 program_id);
@@ -165,7 +169,7 @@ private:
QVBoxLayout* layout = nullptr;
QTreeView* tree_view = nullptr;
QStandardItemModel* item_model = nullptr;
- GameListWorker* current_worker = nullptr;
+ std::unique_ptr<GameListWorker> current_worker;
QFileSystemWatcher* watcher = nullptr;
ControllerNavigation* controller_navigation = nullptr;
CompatibilityList compatibility_list;
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp
index 077ced12b..69be21027 100644
--- a/src/yuzu/game_list_worker.cpp
+++ b/src/yuzu/game_list_worker.cpp
@@ -233,10 +233,53 @@ GameListWorker::GameListWorker(FileSys::VirtualFilesystem vfs_,
const PlayTime::PlayTimeManager& play_time_manager_,
Core::System& system_)
: vfs{std::move(vfs_)}, provider{provider_}, game_dirs{game_dirs_},
- compatibility_list{compatibility_list_},
- play_time_manager{play_time_manager_}, system{system_} {}
+ compatibility_list{compatibility_list_}, play_time_manager{play_time_manager_}, system{
+ system_} {
+ // We want the game list to manage our lifetime.
+ setAutoDelete(false);
+}
+
+GameListWorker::~GameListWorker() {
+ this->disconnect();
+ stop_requested.store(true);
+ processing_completed.Wait();
+}
+
+void GameListWorker::ProcessEvents(GameList* game_list) {
+ while (true) {
+ std::function<void(GameList*)> func;
+ {
+ // Lock queue to protect concurrent modification.
+ std::scoped_lock lk(lock);
+
+ // If we can't pop a function, return.
+ if (queued_events.empty()) {
+ return;
+ }
+
+ // Pop a function.
+ func = std::move(queued_events.back());
+ queued_events.pop_back();
+ }
+
+ // Run the function.
+ func(game_list);
+ }
+}
+
+template <typename F>
+void GameListWorker::RecordEvent(F&& func) {
+ {
+ // Lock queue to protect concurrent modification.
+ std::scoped_lock lk(lock);
-GameListWorker::~GameListWorker() = default;
+ // Add the function into the front of the queue.
+ queued_events.emplace_front(std::move(func));
+ }
+
+ // Data now available.
+ emit DataAvailable();
+}
void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
using namespace FileSys;
@@ -284,9 +327,9 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
GetMetadataFromControlNCA(patch, *control, icon, name);
}
- emit EntryReady(MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
- program_id, compatibility_list, play_time_manager, patch),
- parent_dir);
+ auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
+ program_id, compatibility_list, play_time_manager, patch);
+ RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
}
}
@@ -360,11 +403,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
const FileSys::PatchManager patch{id, system.GetFileSystemController(),
system.GetContentProvider()};
- emit EntryReady(MakeGameListEntry(physical_name, name,
- Common::FS::GetSize(physical_name), icon,
- *loader, id, compatibility_list,
- play_time_manager, patch),
- parent_dir);
+ auto entry = MakeGameListEntry(
+ physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
+ id, compatibility_list, play_time_manager, patch);
+
+ RecordEvent(
+ [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
}
} else {
std::vector<u8> icon;
@@ -376,11 +420,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
const FileSys::PatchManager patch{program_id, system.GetFileSystemController(),
system.GetContentProvider()};
- emit EntryReady(MakeGameListEntry(physical_name, name,
- Common::FS::GetSize(physical_name), icon,
- *loader, program_id, compatibility_list,
- play_time_manager, patch),
- parent_dir);
+ auto entry = MakeGameListEntry(
+ physical_name, name, Common::FS::GetSize(physical_name), icon, *loader,
+ program_id, compatibility_list, play_time_manager, patch);
+
+ RecordEvent(
+ [=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
}
}
} else if (is_dir) {
@@ -399,25 +444,34 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
}
void GameListWorker::run() {
+ watch_list.clear();
provider->ClearAllEntries();
+ const auto DirEntryReady = [&](GameListDir* game_list_dir) {
+ RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); });
+ };
+
for (UISettings::GameDir& game_dir : game_dirs) {
+ if (stop_requested) {
+ break;
+ }
+
if (game_dir.path == QStringLiteral("SDMC")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SdmcDir);
- emit DirEntryReady(game_list_dir);
+ DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
} else if (game_dir.path == QStringLiteral("UserNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::UserNandDir);
- emit DirEntryReady(game_list_dir);
+ DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
} else if (game_dir.path == QStringLiteral("SysNAND")) {
auto* const game_list_dir = new GameListDir(game_dir, GameListItemType::SysNandDir);
- emit DirEntryReady(game_list_dir);
+ DirEntryReady(game_list_dir);
AddTitlesToGameList(game_list_dir);
} else {
watch_list.append(game_dir.path);
auto* const game_list_dir = new GameListDir(game_dir);
- emit DirEntryReady(game_list_dir);
+ DirEntryReady(game_list_dir);
ScanFileSystem(ScanTarget::FillManualContentProvider, game_dir.path.toStdString(),
game_dir.deep_scan, game_list_dir);
ScanFileSystem(ScanTarget::PopulateGameList, game_dir.path.toStdString(),
@@ -425,12 +479,6 @@ void GameListWorker::run() {
}
}
- emit Finished(watch_list);
+ RecordEvent([=](GameList* game_list) { game_list->DonePopulating(watch_list); });
processing_completed.Set();
}
-
-void GameListWorker::Cancel() {
- this->disconnect();
- stop_requested.store(true);
- processing_completed.Wait();
-}
diff --git a/src/yuzu/game_list_worker.h b/src/yuzu/game_list_worker.h
index 54dc05e30..d5990fcde 100644
--- a/src/yuzu/game_list_worker.h
+++ b/src/yuzu/game_list_worker.h
@@ -4,6 +4,7 @@
#pragma once
#include <atomic>
+#include <deque>
#include <memory>
#include <string>
@@ -20,6 +21,7 @@ namespace Core {
class System;
}
+class GameList;
class QStandardItem;
namespace FileSys {
@@ -46,24 +48,22 @@ public:
/// Starts the processing of directory tree information.
void run() override;
- /// Tells the worker that it should no longer continue processing. Thread-safe.
- void Cancel();
-
-signals:
+public:
/**
- * The `EntryReady` signal is emitted once an entry has been prepared and is ready
- * to be added to the game list.
- * @param entry_items a list with `QStandardItem`s that make up the columns of the new
- * entry.
+ * Synchronously processes any events queued by the worker.
+ *
+ * AddDirEntry is called on the game list for every discovered directory.
+ * AddEntry is called on the game list for every discovered program.
+ * DonePopulating is called on the game list when processing completes.
*/
- void DirEntryReady(GameListDir* entry_items);
- void EntryReady(QList<QStandardItem*> entry_items, GameListDir* parent_dir);
+ void ProcessEvents(GameList* game_list);
- /**
- * After the worker has traversed the game directory looking for entries, this signal is
- * emitted with a list of folders that should be watched for changes as well.
- */
- void Finished(QStringList watch_list);
+signals:
+ void DataAvailable();
+
+private:
+ template <typename F>
+ void RecordEvent(F&& func);
private:
void AddTitlesToGameList(GameListDir* parent_dir);
@@ -84,8 +84,11 @@ private:
QStringList watch_list;
- Common::Event processing_completed;
+ std::mutex lock;
+ std::condition_variable cv;
+ std::deque<std::function<void(GameList*)>> queued_events;
std::atomic_bool stop_requested = false;
+ Common::Event processing_completed;
Core::System& system;
};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 1431cf2fe..816d804c4 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2019,7 +2019,7 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t
std::filesystem::path{Common::U16StringFromBuffer(filename.utf16(), filename.size())}
.filename());
}
- const bool is_64bit = system->Kernel().ApplicationProcess()->Is64BitProcess();
+ const bool is_64bit = system->Kernel().ApplicationProcess()->Is64Bit();
const auto instruction_set_suffix = is_64bit ? tr("(64-bit)") : tr("(32-bit)");
title_name = tr("%1 %2", "%1 is the title name. %2 indicates if the title is 64-bit or 32-bit")
.arg(QString::fromStdString(title_name), instruction_set_suffix)