HostInterface: Make SetUserDirectory() overridable by frontends
This commit is contained in:
parent
11e8a91e30
commit
e7640d5367
|
@ -49,14 +49,7 @@ static std::string GetRelativePath(const std::string& path, const char* new_file
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HostInterface::HostInterface()
|
HostInterface::HostInterface() = default;
|
||||||
{
|
|
||||||
SetUserDirectory();
|
|
||||||
CreateUserDirectorySubdirectories();
|
|
||||||
m_game_list = std::make_unique<GameList>();
|
|
||||||
m_game_list->SetCacheFilename(GetGameListCacheFileName());
|
|
||||||
m_game_list->SetDatabaseFilename(GetGameListDatabaseFileName());
|
|
||||||
}
|
|
||||||
|
|
||||||
HostInterface::~HostInterface()
|
HostInterface::~HostInterface()
|
||||||
{
|
{
|
||||||
|
@ -64,6 +57,21 @@ HostInterface::~HostInterface()
|
||||||
Assert(!m_system && !m_audio_stream && !m_display);
|
Assert(!m_system && !m_audio_stream && !m_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HostInterface::Initialize()
|
||||||
|
{
|
||||||
|
SetUserDirectory();
|
||||||
|
InitializeUserDirectory();
|
||||||
|
m_game_list = std::make_unique<GameList>();
|
||||||
|
m_game_list->SetCacheFilename(GetGameListCacheFileName());
|
||||||
|
m_game_list->SetDatabaseFilename(GetGameListDatabaseFileName());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostInterface::Shutdown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterface::CreateAudioStream()
|
void HostInterface::CreateAudioStream()
|
||||||
{
|
{
|
||||||
m_audio_stream = CreateAudioStream(m_settings.audio_backend);
|
m_audio_stream = CreateAudioStream(m_settings.audio_backend);
|
||||||
|
@ -660,7 +668,10 @@ void HostInterface::SetUserDirectory()
|
||||||
m_user_directory = StringUtil::StdStringFromFormat("%s/Library/Application Support/DuckStation", home_path);
|
m_user_directory = StringUtil::StdStringFromFormat("%s/Library/Application Support/DuckStation", home_path);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostInterface::InitializeUserDirectory()
|
||||||
|
{
|
||||||
Log_InfoPrintf("User directory: \"%s\"", m_user_directory.c_str());
|
Log_InfoPrintf("User directory: \"%s\"", m_user_directory.c_str());
|
||||||
|
|
||||||
if (m_user_directory.empty())
|
if (m_user_directory.empty())
|
||||||
|
@ -673,13 +684,6 @@ void HostInterface::SetUserDirectory()
|
||||||
Log_ErrorPrintf("Failed to create user directory \"%s\".", m_user_directory.c_str());
|
Log_ErrorPrintf("Failed to create user directory \"%s\".", m_user_directory.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change to the user directory so that all default/relative paths in the config are after this.
|
|
||||||
if (!FileSystem::SetWorkingDirectory(m_user_directory.c_str()))
|
|
||||||
Log_ErrorPrintf("Failed to set working directory to '%s'", m_user_directory.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HostInterface::CreateUserDirectorySubdirectories()
|
|
||||||
{
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("bios").c_str(), false);
|
result &= FileSystem::CreateDirectory(GetUserDirectoryRelativePath("bios").c_str(), false);
|
||||||
|
|
|
@ -44,6 +44,12 @@ public:
|
||||||
/// Access to emulated system.
|
/// Access to emulated system.
|
||||||
ALWAYS_INLINE System* GetSystem() const { return m_system.get(); }
|
ALWAYS_INLINE System* GetSystem() const { return m_system.get(); }
|
||||||
|
|
||||||
|
/// Initializes the emulator frontend.
|
||||||
|
virtual bool Initialize();
|
||||||
|
|
||||||
|
/// Shuts down the emulator frontend.
|
||||||
|
virtual void Shutdown();
|
||||||
|
|
||||||
bool BootSystem(const SystemBootParameters& parameters);
|
bool BootSystem(const SystemBootParameters& parameters);
|
||||||
void PauseSystem(bool paused);
|
void PauseSystem(bool paused);
|
||||||
void ResetSystem();
|
void ResetSystem();
|
||||||
|
@ -149,7 +155,8 @@ protected:
|
||||||
virtual void OnControllerTypeChanged(u32 slot);
|
virtual void OnControllerTypeChanged(u32 slot);
|
||||||
virtual void DrawImGuiWindows();
|
virtual void DrawImGuiWindows();
|
||||||
|
|
||||||
void SetUserDirectory();
|
/// Sets the base path for the user directory. Can be overridden by platform/frontend/command line.
|
||||||
|
virtual void SetUserDirectory();
|
||||||
|
|
||||||
/// Ensures all subdirectories of the user directory are created.
|
/// Ensures all subdirectories of the user directory are created.
|
||||||
void CreateUserDirectorySubdirectories();
|
void CreateUserDirectorySubdirectories();
|
||||||
|
@ -231,6 +238,7 @@ protected:
|
||||||
std::mutex m_osd_messages_lock;
|
std::mutex m_osd_messages_lock;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void InitializeUserDirectory();
|
||||||
void CreateAudioStream();
|
void CreateAudioStream();
|
||||||
bool SaveState(const char* filename);
|
bool SaveState(const char* filename);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "qthostinterface.h"
|
#include "qthostinterface.h"
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
static void InitLogging()
|
static void InitLogging()
|
||||||
|
@ -34,11 +35,22 @@ int main(int argc, char* argv[])
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<QtHostInterface> host_interface = std::make_unique<QtHostInterface>();
|
std::unique_ptr<QtHostInterface> host_interface = std::make_unique<QtHostInterface>();
|
||||||
|
if (!host_interface->Initialize())
|
||||||
|
{
|
||||||
|
host_interface->Shutdown();
|
||||||
|
QMessageBox::critical(nullptr, QObject::tr("DuckStation Error"),
|
||||||
|
QObject::tr("Failed to initialize host interface. Cannot continue."), QMessageBox::Ok);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<MainWindow> window = std::make_unique<MainWindow>(host_interface.get());
|
std::unique_ptr<MainWindow> window = std::make_unique<MainWindow>(host_interface.get());
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
host_interface->refreshGameList();
|
host_interface->refreshGameList();
|
||||||
|
|
||||||
return app.exec();
|
int result = app.exec();
|
||||||
|
|
||||||
|
window.reset();
|
||||||
|
host_interface->Shutdown();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,36 +29,58 @@ Log_SetChannel(QtHostInterface);
|
||||||
#include "d3d11displaywidget.h"
|
#include "d3d11displaywidget.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QtHostInterface::QtHostInterface(QObject* parent)
|
QtHostInterface::QtHostInterface(QObject* parent) : QObject(parent), CommonHostInterface()
|
||||||
: QObject(parent), CommonHostInterface(),
|
|
||||||
m_qsettings(QString::fromStdString(GetSettingsFileName()), QSettings::IniFormat)
|
|
||||||
{
|
{
|
||||||
qRegisterMetaType<SystemBootParameters>();
|
qRegisterMetaType<SystemBootParameters>();
|
||||||
|
|
||||||
// TODO: This probably should wait until the thread finishes initializing.
|
|
||||||
loadSettings();
|
|
||||||
createThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHostInterface::~QtHostInterface()
|
QtHostInterface::~QtHostInterface()
|
||||||
{
|
{
|
||||||
Assert(!m_display_widget);
|
Assert(!m_display_widget);
|
||||||
stopThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtHostInterface::Initialize()
|
bool QtHostInterface::Initialize()
|
||||||
|
{
|
||||||
|
createThread();
|
||||||
|
return m_worker_thread->waitForInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::Shutdown()
|
||||||
|
{
|
||||||
|
stopThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtHostInterface::initializeOnThread()
|
||||||
{
|
{
|
||||||
if (!CommonHostInterface::Initialize())
|
if (!CommonHostInterface::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// make sure the controllers have been detected
|
||||||
if (m_controller_interface)
|
if (m_controller_interface)
|
||||||
m_controller_interface->PollEvents();
|
m_controller_interface->PollEvents();
|
||||||
|
|
||||||
|
// no need to lock here because the main thread is waiting for us
|
||||||
|
m_qsettings = std::make_unique<QSettings>(QString::fromStdString(GetSettingsFileName()), QSettings::IniFormat);
|
||||||
|
QtSettingsInterface si(m_qsettings.get());
|
||||||
|
|
||||||
|
// check settings validity
|
||||||
|
const QSettings::Status settings_status = m_qsettings->status();
|
||||||
|
if (settings_status != QSettings::NoError)
|
||||||
|
{
|
||||||
|
m_qsettings->clear();
|
||||||
|
SetDefaultSettings(si);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load in settings
|
||||||
|
CheckSettings(si);
|
||||||
|
m_settings.Load(si);
|
||||||
|
|
||||||
|
// bind buttons/axises
|
||||||
updateInputMap();
|
updateInputMap();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::Shutdown()
|
void QtHostInterface::shutdownOnThread()
|
||||||
{
|
{
|
||||||
CommonHostInterface::Shutdown();
|
CommonHostInterface::Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -101,19 +123,19 @@ bool QtHostInterface::ConfirmMessage(const char* message)
|
||||||
QVariant QtHostInterface::getSettingValue(const QString& name, const QVariant& default_value)
|
QVariant QtHostInterface::getSettingValue(const QString& name, const QVariant& default_value)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||||
return m_qsettings.value(name, default_value);
|
return m_qsettings->value(name, default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::putSettingValue(const QString& name, const QVariant& value)
|
void QtHostInterface::putSettingValue(const QString& name, const QVariant& value)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||||
m_qsettings.setValue(name, value);
|
m_qsettings->setValue(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::removeSettingValue(const QString& name)
|
void QtHostInterface::removeSettingValue(const QString& name)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||||
m_qsettings.remove(name);
|
m_qsettings->remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::setDefaultSettings()
|
void QtHostInterface::setDefaultSettings()
|
||||||
|
@ -125,7 +147,7 @@ void QtHostInterface::setDefaultSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||||
QtSettingsInterface si(m_qsettings);
|
QtSettingsInterface si(m_qsettings.get());
|
||||||
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
||||||
CommonHostInterface::UpdateInputMap(si);
|
CommonHostInterface::UpdateInputMap(si);
|
||||||
}
|
}
|
||||||
|
@ -139,12 +161,12 @@ void QtHostInterface::applySettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> guard(m_qsettings_mutex);
|
||||||
QtSettingsInterface si(m_qsettings);
|
QtSettingsInterface si(m_qsettings.get());
|
||||||
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
UpdateSettings([this, &si]() { m_settings.Load(si); });
|
||||||
CommonHostInterface::UpdateInputMap(si);
|
CommonHostInterface::UpdateInputMap(si);
|
||||||
|
|
||||||
// detect when render-to-main flag changes
|
// detect when render-to-main flag changes
|
||||||
const bool render_to_main = m_qsettings.value("Main/RenderToMainWindow", true).toBool();
|
const bool render_to_main = m_qsettings->value("Main/RenderToMainWindow", true).toBool();
|
||||||
if (m_system && m_display_widget && !m_is_fullscreen && render_to_main != m_is_rendering_to_main)
|
if (m_system && m_display_widget && !m_is_fullscreen && render_to_main != m_is_rendering_to_main)
|
||||||
{
|
{
|
||||||
m_is_rendering_to_main = render_to_main;
|
m_is_rendering_to_main = render_to_main;
|
||||||
|
@ -152,30 +174,12 @@ void QtHostInterface::applySettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHostInterface::loadSettings()
|
|
||||||
{
|
|
||||||
// no need to lock here because the emu thread doesn't exist yet
|
|
||||||
QtSettingsInterface si(m_qsettings);
|
|
||||||
|
|
||||||
const QSettings::Status settings_status = m_qsettings.status();
|
|
||||||
if (settings_status != QSettings::NoError)
|
|
||||||
{
|
|
||||||
m_qsettings.clear();
|
|
||||||
SetDefaultSettings(si);
|
|
||||||
}
|
|
||||||
|
|
||||||
CheckSettings(si);
|
|
||||||
m_settings.Load(si);
|
|
||||||
|
|
||||||
// input map update is done on the emu thread
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool invalidate_database /* = false */)
|
void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool invalidate_database /* = false */)
|
||||||
{
|
{
|
||||||
Assert(!isOnWorkerThread());
|
Assert(!isOnWorkerThread());
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
||||||
QtSettingsInterface si(m_qsettings);
|
QtSettingsInterface si(m_qsettings.get());
|
||||||
m_game_list->SetSearchDirectoriesFromSettings(si);
|
m_game_list->SetSearchDirectoriesFromSettings(si);
|
||||||
|
|
||||||
QtProgressCallback progress(m_main_window);
|
QtProgressCallback progress(m_main_window);
|
||||||
|
@ -434,7 +438,7 @@ void QtHostInterface::updateInputMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
std::lock_guard<std::recursive_mutex> lock(m_qsettings_mutex);
|
||||||
QtSettingsInterface si(m_qsettings);
|
QtSettingsInterface si(m_qsettings.get());
|
||||||
CommonHostInterface::UpdateInputMap(si);
|
CommonHostInterface::UpdateInputMap(si);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -757,8 +761,7 @@ void QtHostInterface::threadEntryPoint()
|
||||||
m_worker_thread_event_loop = new QEventLoop();
|
m_worker_thread_event_loop = new QEventLoop();
|
||||||
|
|
||||||
// set up controller interface and immediate poll to pick up the controller attached events
|
// set up controller interface and immediate poll to pick up the controller attached events
|
||||||
if (!Initialize())
|
m_worker_thread->setInitResult(initializeOnThread());
|
||||||
Panic("Failed to initialize host interface");
|
|
||||||
|
|
||||||
// TODO: Event which flags the thread as ready
|
// TODO: Event which flags the thread as ready
|
||||||
while (!m_shutdown_flag.load())
|
while (!m_shutdown_flag.load())
|
||||||
|
@ -784,7 +787,7 @@ void QtHostInterface::threadEntryPoint()
|
||||||
m_controller_interface->PollEvents();
|
m_controller_interface->PollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
Shutdown();
|
shutdownOnThread();
|
||||||
|
|
||||||
delete m_worker_thread_event_loop;
|
delete m_worker_thread_event_loop;
|
||||||
m_worker_thread_event_loop = nullptr;
|
m_worker_thread_event_loop = nullptr;
|
||||||
|
@ -820,3 +823,15 @@ void QtHostInterface::Thread::run()
|
||||||
{
|
{
|
||||||
m_parent->threadEntryPoint();
|
m_parent->threadEntryPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QtHostInterface::Thread::setInitResult(bool result)
|
||||||
|
{
|
||||||
|
m_init_result.store(result);
|
||||||
|
m_init_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QtHostInterface::Thread::waitForInit()
|
||||||
|
{
|
||||||
|
m_init_event.Wait();
|
||||||
|
return m_init_result.load();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "core/host_interface.h"
|
#include "core/host_interface.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
|
#include "common/event.h"
|
||||||
#include "frontend-common/common_host_interface.h"
|
#include "frontend-common/common_host_interface.h"
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
@ -151,24 +152,30 @@ private:
|
||||||
Thread(QtHostInterface* parent);
|
Thread(QtHostInterface* parent);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
|
void setInitResult(bool result);
|
||||||
|
bool waitForInit();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QtHostInterface* m_parent;
|
QtHostInterface* m_parent;
|
||||||
|
std::atomic_bool m_init_result{ false };
|
||||||
|
Common::Event m_init_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
void loadSettings();
|
|
||||||
void createBackgroundControllerPollTimer();
|
void createBackgroundControllerPollTimer();
|
||||||
void destroyBackgroundControllerPollTimer();
|
void destroyBackgroundControllerPollTimer();
|
||||||
|
|
||||||
void createThread();
|
void createThread();
|
||||||
void stopThread();
|
void stopThread();
|
||||||
void threadEntryPoint();
|
void threadEntryPoint();
|
||||||
|
bool initializeOnThread();
|
||||||
|
void shutdownOnThread();
|
||||||
void renderDisplay();
|
void renderDisplay();
|
||||||
void wakeThread();
|
void wakeThread();
|
||||||
|
|
||||||
QSettings m_qsettings;
|
std::unique_ptr<QSettings> m_qsettings;
|
||||||
std::recursive_mutex m_qsettings_mutex;
|
std::recursive_mutex m_qsettings_mutex;
|
||||||
|
|
||||||
MainWindow* m_main_window = nullptr;
|
MainWindow* m_main_window = nullptr;
|
||||||
|
|
|
@ -7,18 +7,18 @@ static QString GetFullKey(const char* section, const char* key)
|
||||||
return QStringLiteral("%1/%2").arg(section, key);
|
return QStringLiteral("%1/%2").arg(section, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtSettingsInterface::QtSettingsInterface(QSettings& settings) : m_settings(settings) {}
|
QtSettingsInterface::QtSettingsInterface(QSettings* settings) : m_settings(settings) {}
|
||||||
|
|
||||||
QtSettingsInterface::~QtSettingsInterface() = default;
|
QtSettingsInterface::~QtSettingsInterface() = default;
|
||||||
|
|
||||||
void QtSettingsInterface::Clear()
|
void QtSettingsInterface::Clear()
|
||||||
{
|
{
|
||||||
m_settings.clear();
|
m_settings->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int QtSettingsInterface::GetIntValue(const char* section, const char* key, int default_value /*= 0*/)
|
int QtSettingsInterface::GetIntValue(const char* section, const char* key, int default_value /*= 0*/)
|
||||||
{
|
{
|
||||||
QVariant value = m_settings.value(GetFullKey(section, key));
|
QVariant value = m_settings->value(GetFullKey(section, key));
|
||||||
if (!value.isValid())
|
if (!value.isValid())
|
||||||
return default_value;
|
return default_value;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ int QtSettingsInterface::GetIntValue(const char* section, const char* key, int d
|
||||||
|
|
||||||
float QtSettingsInterface::GetFloatValue(const char* section, const char* key, float default_value /*= 0.0f*/)
|
float QtSettingsInterface::GetFloatValue(const char* section, const char* key, float default_value /*= 0.0f*/)
|
||||||
{
|
{
|
||||||
QVariant value = m_settings.value(GetFullKey(section, key));
|
QVariant value = m_settings->value(GetFullKey(section, key));
|
||||||
if (!value.isValid())
|
if (!value.isValid())
|
||||||
return default_value;
|
return default_value;
|
||||||
|
|
||||||
|
@ -46,40 +46,40 @@ float QtSettingsInterface::GetFloatValue(const char* section, const char* key, f
|
||||||
|
|
||||||
bool QtSettingsInterface::GetBoolValue(const char* section, const char* key, bool default_value /*= false*/)
|
bool QtSettingsInterface::GetBoolValue(const char* section, const char* key, bool default_value /*= false*/)
|
||||||
{
|
{
|
||||||
QVariant value = m_settings.value(GetFullKey(section, key));
|
QVariant value = m_settings->value(GetFullKey(section, key));
|
||||||
return value.isValid() ? value.toBool() : default_value;
|
return value.isValid() ? value.toBool() : default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string QtSettingsInterface::GetStringValue(const char* section, const char* key,
|
std::string QtSettingsInterface::GetStringValue(const char* section, const char* key,
|
||||||
const char* default_value /*= ""*/)
|
const char* default_value /*= ""*/)
|
||||||
{
|
{
|
||||||
QVariant value = m_settings.value(GetFullKey(section, key));
|
QVariant value = m_settings->value(GetFullKey(section, key));
|
||||||
return value.isValid() ? value.toString().toStdString() : std::string(default_value);
|
return value.isValid() ? value.toString().toStdString() : std::string(default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSettingsInterface::SetIntValue(const char* section, const char* key, int value)
|
void QtSettingsInterface::SetIntValue(const char* section, const char* key, int value)
|
||||||
{
|
{
|
||||||
m_settings.setValue(GetFullKey(section, key), QVariant(value));
|
m_settings->setValue(GetFullKey(section, key), QVariant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSettingsInterface::SetFloatValue(const char* section, const char* key, float value)
|
void QtSettingsInterface::SetFloatValue(const char* section, const char* key, float value)
|
||||||
{
|
{
|
||||||
m_settings.setValue(GetFullKey(section, key), QString::number(value));
|
m_settings->setValue(GetFullKey(section, key), QString::number(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSettingsInterface::SetBoolValue(const char* section, const char* key, bool value)
|
void QtSettingsInterface::SetBoolValue(const char* section, const char* key, bool value)
|
||||||
{
|
{
|
||||||
m_settings.setValue(GetFullKey(section, key), QVariant(value));
|
m_settings->setValue(GetFullKey(section, key), QVariant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSettingsInterface::SetStringValue(const char* section, const char* key, const char* value)
|
void QtSettingsInterface::SetStringValue(const char* section, const char* key, const char* value)
|
||||||
{
|
{
|
||||||
m_settings.setValue(GetFullKey(section, key), QVariant(value));
|
m_settings->setValue(GetFullKey(section, key), QVariant(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> QtSettingsInterface::GetStringList(const char* section, const char* key)
|
std::vector<std::string> QtSettingsInterface::GetStringList(const char* section, const char* key)
|
||||||
{
|
{
|
||||||
QVariant value = m_settings.value(GetFullKey(section, key));
|
QVariant value = m_settings->value(GetFullKey(section, key));
|
||||||
if (value.type() == QVariant::String)
|
if (value.type() == QVariant::String)
|
||||||
return {value.toString().toStdString()};
|
return {value.toString().toStdString()};
|
||||||
else if (value.type() != QVariant::StringList)
|
else if (value.type() != QVariant::StringList)
|
||||||
|
@ -99,7 +99,7 @@ void QtSettingsInterface::SetStringList(const char* section, const char* key,
|
||||||
QString full_key = GetFullKey(section, key);
|
QString full_key = GetFullKey(section, key);
|
||||||
if (items.empty())
|
if (items.empty())
|
||||||
{
|
{
|
||||||
m_settings.remove(full_key);
|
m_settings->remove(full_key);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,28 +108,28 @@ void QtSettingsInterface::SetStringList(const char* section, const char* key,
|
||||||
std::transform(items.begin(), items.end(), std::back_inserter(sl), [](const std::string_view& sv) {
|
std::transform(items.begin(), items.end(), std::back_inserter(sl), [](const std::string_view& sv) {
|
||||||
return QString::fromLocal8Bit(sv.data(), static_cast<int>(sv.size()));
|
return QString::fromLocal8Bit(sv.data(), static_cast<int>(sv.size()));
|
||||||
});
|
});
|
||||||
m_settings.setValue(full_key, sl);
|
m_settings->setValue(full_key, sl);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtSettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
|
bool QtSettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
|
||||||
{
|
{
|
||||||
QString full_key = GetFullKey(section, key);
|
QString full_key = GetFullKey(section, key);
|
||||||
QVariant var = m_settings.value(full_key);
|
QVariant var = m_settings->value(full_key);
|
||||||
QStringList sl = var.toStringList();
|
QStringList sl = var.toStringList();
|
||||||
if (sl.removeAll(item) == 0)
|
if (sl.removeAll(item) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sl.isEmpty())
|
if (sl.isEmpty())
|
||||||
m_settings.remove(full_key);
|
m_settings->remove(full_key);
|
||||||
else
|
else
|
||||||
m_settings.setValue(full_key, sl);
|
m_settings->setValue(full_key, sl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtSettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
|
bool QtSettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
|
||||||
{
|
{
|
||||||
QString full_key = GetFullKey(section, key);
|
QString full_key = GetFullKey(section, key);
|
||||||
QVariant var = m_settings.value(full_key);
|
QVariant var = m_settings->value(full_key);
|
||||||
|
|
||||||
QStringList sl = (var.type() == QVariant::StringList) ? var.toStringList() : QStringList();
|
QStringList sl = (var.type() == QVariant::StringList) ? var.toStringList() : QStringList();
|
||||||
QString qitem(item);
|
QString qitem(item);
|
||||||
|
@ -137,11 +137,11 @@ bool QtSettingsInterface::AddToStringList(const char* section, const char* key,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sl.push_back(qitem);
|
sl.push_back(qitem);
|
||||||
m_settings.setValue(full_key, sl);
|
m_settings->setValue(full_key, sl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtSettingsInterface::DeleteValue(const char* section, const char* key)
|
void QtSettingsInterface::DeleteValue(const char* section, const char* key)
|
||||||
{
|
{
|
||||||
m_settings.remove(GetFullKey(section, key));
|
m_settings->remove(GetFullKey(section, key));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ class QSettings;
|
||||||
class QtSettingsInterface : public SettingsInterface
|
class QtSettingsInterface : public SettingsInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QtSettingsInterface(QSettings& settings);
|
QtSettingsInterface(QSettings* settings);
|
||||||
~QtSettingsInterface();
|
~QtSettingsInterface();
|
||||||
|
|
||||||
void Clear() override;
|
void Clear() override;
|
||||||
|
@ -29,5 +29,5 @@ public:
|
||||||
void DeleteValue(const char* section, const char* key) override;
|
void DeleteValue(const char* section, const char* key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSettings& m_settings;
|
QSettings* m_settings;
|
||||||
};
|
};
|
|
@ -37,9 +37,10 @@ static int Run(int argc, char* argv[])
|
||||||
|
|
||||||
// create display and host interface
|
// create display and host interface
|
||||||
std::unique_ptr<SDLHostInterface> host_interface = SDLHostInterface::Create();
|
std::unique_ptr<SDLHostInterface> host_interface = SDLHostInterface::Create();
|
||||||
if (!host_interface)
|
if (!host_interface->Initialize())
|
||||||
{
|
{
|
||||||
Panic("Failed to create host interface");
|
host_interface->Shutdown();
|
||||||
|
Panic("Failed to initialize host interface");
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +62,7 @@ static int Run(int argc, char* argv[])
|
||||||
host_interface->Run();
|
host_interface->Run();
|
||||||
|
|
||||||
// done
|
// done
|
||||||
|
host_interface->Shutdown();
|
||||||
host_interface.reset();
|
host_interface.reset();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -31,6 +31,8 @@ public:
|
||||||
|
|
||||||
void SetVSync(bool enabled) override;
|
void SetVSync(bool enabled) override;
|
||||||
|
|
||||||
|
void Render() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* GetGLSLVersionString() const;
|
const char* GetGLSLVersionString() const;
|
||||||
std::string GetGLSLVersionHeader() const;
|
std::string GetGLSLVersionHeader() const;
|
||||||
|
@ -39,7 +41,6 @@ private:
|
||||||
bool CreateImGuiContext();
|
bool CreateImGuiContext();
|
||||||
bool CreateGLResources();
|
bool CreateGLResources();
|
||||||
|
|
||||||
void Render() override;
|
|
||||||
void RenderDisplay();
|
void RenderDisplay();
|
||||||
|
|
||||||
SDL_Window* m_window = nullptr;
|
SDL_Window* m_window = nullptr;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "sdl_host_interface.h"
|
#include "sdl_host_interface.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/byte_stream.h"
|
#include "common/byte_stream.h"
|
||||||
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/controller.h"
|
#include "core/controller.h"
|
||||||
|
@ -30,17 +31,7 @@ SDLHostInterface::SDLHostInterface()
|
||||||
m_run_later_event_id = SDL_RegisterEvents(1);
|
m_run_later_event_id = SDL_RegisterEvents(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLHostInterface::~SDLHostInterface()
|
SDLHostInterface::~SDLHostInterface() = default;
|
||||||
{
|
|
||||||
if (m_display)
|
|
||||||
{
|
|
||||||
DestroyDisplay();
|
|
||||||
ImGui::DestroyContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_window)
|
|
||||||
DestroySDLWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
float SDLHostInterface::GetDPIScaleFactor(SDL_Window* window)
|
float SDLHostInterface::GetDPIScaleFactor(SDL_Window* window)
|
||||||
{
|
{
|
||||||
|
@ -292,30 +283,55 @@ void SDLHostInterface::SetFullscreen(bool enabled)
|
||||||
|
|
||||||
std::unique_ptr<SDLHostInterface> SDLHostInterface::Create()
|
std::unique_ptr<SDLHostInterface> SDLHostInterface::Create()
|
||||||
{
|
{
|
||||||
std::unique_ptr<SDLHostInterface> intf = std::make_unique<SDLHostInterface>();
|
return std::make_unique<SDLHostInterface>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLHostInterface::Initialize()
|
||||||
|
{
|
||||||
|
if (!HostInterface::Initialize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Change to the user directory so that all default/relative paths in the config are after this.
|
||||||
|
if (!FileSystem::SetWorkingDirectory(m_user_directory.c_str()))
|
||||||
|
Log_ErrorPrintf("Failed to set working directory to '%s'", m_user_directory.c_str());
|
||||||
|
|
||||||
// Settings need to be loaded prior to creating the window for OpenGL bits.
|
// Settings need to be loaded prior to creating the window for OpenGL bits.
|
||||||
INISettingsInterface si(intf->GetSettingsFileName());
|
INISettingsInterface si(GetSettingsFileName());
|
||||||
intf->m_settings_copy.Load(si);
|
m_settings_copy.Load(si);
|
||||||
intf->m_settings = intf->m_settings_copy;
|
m_settings = m_settings_copy;
|
||||||
intf->m_fullscreen = intf->m_settings_copy.start_fullscreen;
|
m_fullscreen = m_settings_copy.start_fullscreen;
|
||||||
|
|
||||||
if (!intf->CreateSDLWindow())
|
if (!CreateSDLWindow())
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to create SDL window");
|
Log_ErrorPrintf("Failed to create SDL window");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
intf->CreateImGuiContext();
|
CreateImGuiContext();
|
||||||
if (!intf->CreateDisplay())
|
if (!CreateDisplay())
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Failed to create host display");
|
Log_ErrorPrintf("Failed to create host display");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return intf;
|
void SDLHostInterface::Shutdown()
|
||||||
|
{
|
||||||
|
DestroySystem();
|
||||||
|
|
||||||
|
if (m_display)
|
||||||
|
{
|
||||||
|
DestroyDisplay();
|
||||||
|
ImGui::DestroyContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_window)
|
||||||
|
DestroySDLWindow();
|
||||||
|
|
||||||
|
HostInterface::Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLHostInterface::ReportError(const char* message)
|
void SDLHostInterface::ReportError(const char* message)
|
||||||
|
@ -356,7 +372,7 @@ bool SDLHostInterface::ConfirmMessage(const char* message)
|
||||||
void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
{
|
{
|
||||||
ImGui_ImplSDL2_ProcessEvent(event);
|
ImGui_ImplSDL2_ProcessEvent(event);
|
||||||
//g_sdl_controller_interface.ProcessSDLEvent(event);
|
// g_sdl_controller_interface.ProcessSDLEvent(event);
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
|
@ -388,7 +404,7 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event)
|
||||||
|
|
||||||
case SDL_CONTROLLERDEVICEADDED:
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
//g_sdl_controller_interface.SetDefaultBindings();
|
// g_sdl_controller_interface.SetDefaultBindings();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_CONTROLLERBUTTONDOWN:
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
@ -1425,7 +1441,7 @@ void SDLHostInterface::Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//g_sdl_controller_interface.UpdateControllerRumble();
|
// g_sdl_controller_interface.UpdateControllerRumble();
|
||||||
|
|
||||||
// rendering
|
// rendering
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,6 +29,9 @@ public:
|
||||||
void ReportMessage(const char* message) override;
|
void ReportMessage(const char* message) override;
|
||||||
bool ConfirmMessage(const char* message) override;
|
bool ConfirmMessage(const char* message) override;
|
||||||
|
|
||||||
|
bool Initialize();
|
||||||
|
void Shutdown() override;
|
||||||
|
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "common_host_interface.h"
|
#include "common_host_interface.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/audio_stream.h"
|
#include "common/audio_stream.h"
|
||||||
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "controller_interface.h"
|
#include "controller_interface.h"
|
||||||
|
@ -21,6 +22,13 @@ CommonHostInterface::~CommonHostInterface() = default;
|
||||||
|
|
||||||
bool CommonHostInterface::Initialize()
|
bool CommonHostInterface::Initialize()
|
||||||
{
|
{
|
||||||
|
if (!HostInterface::Initialize())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Change to the user directory so that all default/relative paths in the config are after this.
|
||||||
|
if (!FileSystem::SetWorkingDirectory(m_user_directory.c_str()))
|
||||||
|
Log_ErrorPrintf("Failed to set working directory to '%s'", m_user_directory.c_str());
|
||||||
|
|
||||||
RegisterGeneralHotkeys();
|
RegisterGeneralHotkeys();
|
||||||
RegisterGraphicsHotkeys();
|
RegisterGraphicsHotkeys();
|
||||||
RegisterSaveStateHotkeys();
|
RegisterSaveStateHotkeys();
|
||||||
|
@ -41,8 +49,12 @@ bool CommonHostInterface::Initialize()
|
||||||
|
|
||||||
void CommonHostInterface::Shutdown()
|
void CommonHostInterface::Shutdown()
|
||||||
{
|
{
|
||||||
|
HostInterface::Shutdown();
|
||||||
|
|
||||||
m_system.reset();
|
m_system.reset();
|
||||||
m_audio_stream.reset();
|
m_audio_stream.reset();
|
||||||
|
if (m_display)
|
||||||
|
ReleaseHostDisplay();
|
||||||
|
|
||||||
if (m_controller_interface)
|
if (m_controller_interface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,8 +33,8 @@ public:
|
||||||
|
|
||||||
using HotkeyInfoList = std::vector<HotkeyInfo>;
|
using HotkeyInfoList = std::vector<HotkeyInfo>;
|
||||||
|
|
||||||
virtual bool Initialize();
|
virtual bool Initialize() override;
|
||||||
virtual void Shutdown();
|
virtual void Shutdown() override;
|
||||||
|
|
||||||
/// Returns a list of all available hotkeys.
|
/// Returns a list of all available hotkeys.
|
||||||
ALWAYS_INLINE const HotkeyInfoList& GetHotkeyInfoList() const { return m_hotkeys; }
|
ALWAYS_INLINE const HotkeyInfoList& GetHotkeyInfoList() const { return m_hotkeys; }
|
||||||
|
|
Loading…
Reference in New Issue