summaryrefslogtreecommitdiffstats
path: root/xbmc/games/GameSettings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/games/GameSettings.cpp')
-rw-r--r--xbmc/games/GameSettings.cpp242
1 files changed, 242 insertions, 0 deletions
diff --git a/xbmc/games/GameSettings.cpp b/xbmc/games/GameSettings.cpp
new file mode 100644
index 0000000..acbccdc
--- /dev/null
+++ b/xbmc/games/GameSettings.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2012-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "GameSettings.h"
+
+#include "ServiceBroker.h"
+#include "URL.h"
+#include "events/EventLog.h"
+#include "events/NotificationEvent.h"
+#include "filesystem/File.h"
+#include "settings/Settings.h"
+#include "settings/SettingsComponent.h"
+#include "settings/lib/Setting.h"
+#include "utils/JSONVariantParser.h"
+#include "utils/StringUtils.h"
+#include "utils/Variant.h"
+#include "utils/log.h"
+
+#include <algorithm>
+#include <vector>
+
+using namespace KODI;
+using namespace GAME;
+
+namespace
+{
+const std::string SETTING_GAMES_ENABLE = "gamesgeneral.enable";
+const std::string SETTING_GAMES_SHOW_OSD_HELP = "gamesgeneral.showosdhelp";
+const std::string SETTING_GAMES_ENABLEAUTOSAVE = "gamesgeneral.enableautosave";
+const std::string SETTING_GAMES_ENABLEREWIND = "gamesgeneral.enablerewind";
+const std::string SETTING_GAMES_REWINDTIME = "gamesgeneral.rewindtime";
+const std::string SETTING_GAMES_ACHIEVEMENTS_USERNAME = "gamesachievements.username";
+const std::string SETTING_GAMES_ACHIEVEMENTS_PASSWORD = "gamesachievements.password";
+const std::string SETTING_GAMES_ACHIEVEMENTS_TOKEN = "gamesachievements.token";
+const std::string SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN = "gamesachievements.loggedin";
+
+constexpr auto LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE =
+ "http://retroachievements.org/dorequest.php?r=login&u={}&p={}";
+constexpr auto GET_PATCH_DATA_URL_TEMPLATE =
+ "http://retroachievements.org/dorequest.php?r=patch&u={}&t={}&g=0";
+constexpr auto SUCCESS = "Success";
+constexpr auto TOKEN = "Token";
+} // namespace
+
+CGameSettings::CGameSettings()
+{
+ m_settings = CServiceBroker::GetSettingsComponent()->GetSettings();
+
+ m_settings->RegisterCallback(this, {SETTING_GAMES_ENABLEREWIND, SETTING_GAMES_REWINDTIME,
+ SETTING_GAMES_ACHIEVEMENTS_USERNAME,
+ SETTING_GAMES_ACHIEVEMENTS_PASSWORD,
+ SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN});
+}
+
+CGameSettings::~CGameSettings()
+{
+ m_settings->UnregisterCallback(this);
+}
+
+bool CGameSettings::GamesEnabled()
+{
+ return m_settings->GetBool(SETTING_GAMES_ENABLE);
+}
+
+bool CGameSettings::ShowOSDHelp()
+{
+ return m_settings->GetBool(SETTING_GAMES_SHOW_OSD_HELP);
+}
+
+void CGameSettings::SetShowOSDHelp(bool bShow)
+{
+ if (m_settings->GetBool(SETTING_GAMES_SHOW_OSD_HELP) != bShow)
+ {
+ m_settings->SetBool(SETTING_GAMES_SHOW_OSD_HELP, bShow);
+
+ //! @todo Asynchronous save
+ m_settings->Save();
+ }
+}
+
+void CGameSettings::ToggleGames()
+{
+ m_settings->ToggleBool(SETTING_GAMES_ENABLE);
+}
+
+bool CGameSettings::AutosaveEnabled()
+{
+ return m_settings->GetBool(SETTING_GAMES_ENABLEAUTOSAVE);
+}
+
+bool CGameSettings::RewindEnabled()
+{
+ return m_settings->GetBool(SETTING_GAMES_ENABLEREWIND);
+}
+
+unsigned int CGameSettings::MaxRewindTimeSec()
+{
+ int rewindTimeSec = m_settings->GetInt(SETTING_GAMES_REWINDTIME);
+
+ return static_cast<unsigned int>(std::max(rewindTimeSec, 0));
+}
+
+std::string CGameSettings::GetRAUsername() const
+{
+ return m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME);
+}
+
+std::string CGameSettings::GetRAToken() const
+{
+ return m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN);
+}
+
+void CGameSettings::OnSettingChanged(const std::shared_ptr<const CSetting>& setting)
+{
+ if (setting == nullptr)
+ return;
+
+ const std::string& settingId = setting->GetId();
+
+ if (settingId == SETTING_GAMES_ENABLEREWIND || settingId == SETTING_GAMES_REWINDTIME)
+ {
+ SetChanged();
+ NotifyObservers(ObservableMessageSettingsChanged);
+ }
+ else if (settingId == SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN &&
+ std::dynamic_pointer_cast<const CSettingBool>(setting)->GetValue())
+ {
+ const std::string username = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_USERNAME);
+ const std::string password = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD);
+ std::string token = m_settings->GetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN);
+
+ token = LoginToRA(username, password, std::move(token));
+
+ m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, token);
+
+ if (!token.empty())
+ {
+ m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, true);
+ }
+ else
+ {
+ if (settingId == SETTING_GAMES_ACHIEVEMENTS_PASSWORD)
+ m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_PASSWORD, "");
+ m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, false);
+ }
+
+ m_settings->Save();
+ }
+ else if (settingId == SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN &&
+ !std::dynamic_pointer_cast<const CSettingBool>(setting)->GetValue())
+ {
+ m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, "");
+ m_settings->Save();
+ }
+ else if (settingId == SETTING_GAMES_ACHIEVEMENTS_USERNAME ||
+ settingId == SETTING_GAMES_ACHIEVEMENTS_PASSWORD)
+ {
+ m_settings->SetBool(SETTING_GAMES_ACHIEVEMENTS_LOGGED_IN, false);
+ m_settings->SetString(SETTING_GAMES_ACHIEVEMENTS_TOKEN, "");
+ m_settings->Save();
+ }
+}
+
+std::string CGameSettings::LoginToRA(const std::string& username,
+ const std::string& password,
+ std::string token) const
+{
+ if (username.empty() || password.empty())
+ return token;
+
+ XFILE::CFile request;
+ const CURL loginUrl(
+ StringUtils::Format(LOGIN_TO_RETRO_ACHIEVEMENTS_URL_TEMPLATE, username, password));
+
+ std::vector<uint8_t> response;
+ if (request.LoadFile(loginUrl, response) > 0)
+ {
+ std::string strResponse(response.begin(), response.end());
+ CVariant data(CVariant::VariantTypeObject);
+ if (CJSONVariantParser::Parse(strResponse, data))
+ {
+ if (data[SUCCESS].asBoolean())
+ {
+ token = data[TOKEN].asString();
+ if (!IsAccountVerified(username, token))
+ {
+ token.clear();
+ // "RetroAchievements", "Your account is not verified, please check your emails to complete your sign up"
+ CServiceBroker::GetEventLog()->AddWithNotification(
+ EventPtr(new CNotificationEvent(35264, 35270, EventLevel::Error)));
+ }
+ }
+ else
+ {
+ token.clear();
+
+ // "RetroAchievements", "Incorrect User/Password!"
+ CServiceBroker::GetEventLog()->AddWithNotification(
+ EventPtr(new CNotificationEvent(35264, 35265, EventLevel::Error)));
+ }
+ }
+ else
+ {
+ // "RetroAchievements", "Invalid response from server"
+ CServiceBroker::GetEventLog()->AddWithNotification(
+ EventPtr(new CNotificationEvent(35264, 35267, EventLevel::Error)));
+
+ CLog::Log(LOGERROR, "Invalid server response: {}", strResponse);
+ }
+ }
+ else
+ {
+ // "RetroAchievements", "Failed to contact server"
+ CServiceBroker::GetEventLog()->AddWithNotification(
+ EventPtr(new CNotificationEvent(35264, 35266, EventLevel::Error)));
+ }
+ return token;
+}
+
+bool CGameSettings::IsAccountVerified(const std::string& username, const std::string& token) const
+{
+ XFILE::CFile request;
+ const CURL getPatchFileUrl(StringUtils::Format(GET_PATCH_DATA_URL_TEMPLATE, username, token));
+ std::vector<uint8_t> response;
+ if (request.LoadFile(getPatchFileUrl, response) > 0)
+ {
+ std::string strResponse(response.begin(), response.end());
+ CVariant data(CVariant::VariantTypeObject);
+
+ if (CJSONVariantParser::Parse(strResponse, data))
+ {
+ return data[SUCCESS].asBoolean();
+ }
+ }
+
+ return false;
+}