From a538301891312b756828e220e735110d9484a411 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Wed, 22 Jul 2020 15:28:26 +0200 Subject: [PATCH] Android: Hook up global settings to the new config system --- .../settings/model/AdHocBooleanSetting.java | 57 ++++++ .../settings/model/BooleanSetting.java | 28 ++- .../features/settings/model/FloatSetting.java | 28 ++- .../features/settings/model/IntSetting.java | 28 ++- .../features/settings/model/NativeConfig.java | 36 ++++ .../features/settings/model/Settings.java | 17 +- .../settings/model/StringSetting.java | 28 ++- .../model/view/LogCheckBoxSetting.java | 4 +- .../features/settings/ui/SettingsAdapter.java | 4 +- Source/Android/jni/CMakeLists.txt | 1 + Source/Android/jni/NativeConfig.cpp | 163 ++++++++++++++++++ 11 files changed, 373 insertions(+), 21 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java create mode 100644 Source/Android/jni/NativeConfig.cpp diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java new file mode 100644 index 0000000000..b7a06d1419 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/AdHocBooleanSetting.java @@ -0,0 +1,57 @@ +package org.dolphinemu.dolphinemu.features.settings.model; + +public class AdHocBooleanSetting extends AbstractLegacySetting implements AbstractBooleanSetting +{ + private final boolean mDefaultValue; + + public AdHocBooleanSetting(String file, String section, String key, boolean defaultValue) + { + super(file, section, key); + mDefaultValue = defaultValue; + + if (!NativeConfig.isSettingSaveable(file, section, key)) + { + throw new IllegalArgumentException("File/section/key is unknown or legacy"); + } + } + + @Override + public boolean delete(Settings settings) + { + if (!settings.isGameSpecific()) + { + return NativeConfig.deleteKey(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey); + } + else + { + return settings.getSection(mFile, mSection).delete(mKey); + } + } + + @Override + public boolean getBoolean(Settings settings) + { + if (!settings.isGameSpecific()) + { + return NativeConfig.getBoolean(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, + mDefaultValue); + } + else + { + return settings.getSection(mFile, mSection).getBoolean(mKey, mDefaultValue); + } + } + + @Override + public void setBoolean(Settings settings, boolean newValue) + { + if (!settings.isGameSpecific()) + { + NativeConfig.setBoolean(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, newValue); + } + else + { + settings.getSection(mFile, mSection).setBoolean(mKey, newValue); + } + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java index 0d3f853120..fedfd1144c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/BooleanSetting.java @@ -110,18 +110,40 @@ public enum BooleanSetting implements AbstractBooleanSetting @Override public boolean delete(Settings settings) { - return settings.getSection(mFile, mSection).delete(mKey); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.deleteKey(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey); + } + else + { + return settings.getSection(mFile, mSection).delete(mKey); + } } @Override public boolean getBoolean(Settings settings) { - return settings.getSection(mFile, mSection).getBoolean(mKey, mDefaultValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.getBoolean(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, + mDefaultValue); + } + else + { + return settings.getSection(mFile, mSection).getBoolean(mKey, mDefaultValue); + } } @Override public void setBoolean(Settings settings, boolean newValue) { - settings.getSection(mFile, mSection).setBoolean(mKey, newValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + NativeConfig.setBoolean(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, newValue); + } + else + { + settings.getSection(mFile, mSection).setBoolean(mKey, newValue); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java index 2844074da3..c76adcb25d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/FloatSetting.java @@ -23,18 +23,40 @@ public enum FloatSetting implements AbstractFloatSetting @Override public boolean delete(Settings settings) { - return settings.getSection(mFile, mSection).delete(mKey); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.deleteKey(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey); + } + else + { + return settings.getSection(mFile, mSection).delete(mKey); + } } @Override public float getFloat(Settings settings) { - return settings.getSection(mFile, mSection).getFloat(mKey, mDefaultValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.getFloat(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, + mDefaultValue); + } + else + { + return settings.getSection(mFile, mSection).getFloat(mKey, mDefaultValue); + } } @Override public void setFloat(Settings settings, float newValue) { - settings.getSection(mFile, mSection).setFloat(mKey, newValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + NativeConfig.setFloat(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, newValue); + } + else + { + settings.getSection(mFile, mSection).setFloat(mKey, newValue); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java index 09ba84f118..c7b89a79d9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/IntSetting.java @@ -50,18 +50,40 @@ public enum IntSetting implements AbstractIntSetting @Override public boolean delete(Settings settings) { - return settings.getSection(mFile, mSection).delete(mKey); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.deleteKey(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey); + } + else + { + return settings.getSection(mFile, mSection).delete(mKey); + } } @Override public int getInt(Settings settings) { - return settings.getSection(mFile, mSection).getInt(mKey, mDefaultValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.getInt(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, + mDefaultValue); + } + else + { + return settings.getSection(mFile, mSection).getInt(mKey, mDefaultValue); + } } @Override public void setInt(Settings settings, int newValue) { - settings.getSection(mFile, mSection).setInt(mKey, newValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + NativeConfig.setInt(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, newValue); + } + else + { + settings.getSection(mFile, mSection).setInt(mKey, newValue); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java new file mode 100644 index 0000000000..153e245d94 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/NativeConfig.java @@ -0,0 +1,36 @@ +package org.dolphinemu.dolphinemu.features.settings.model; + +public class NativeConfig +{ + public static final int LAYER_BASE_OR_CURRENT = 0; + public static final int LAYER_LOCAL_GAME = 1; + + public static native boolean isSettingSaveable(String file, String section, String key); + + public static native void save(int layer); + + public static native boolean deleteKey(int layer, String file, String section, String key); + + public static native String getString(int layer, String file, String section, String key, + String defaultValue); + + public static native boolean getBoolean(int layer, String file, String section, String key, + boolean defaultValue); + + public static native int getInt(int layer, String file, String section, String key, + int defaultValue); + + public static native float getFloat(int layer, String file, String section, String key, + float defaultValue); + + public static native void setString(int layer, String file, String section, String key, + String value); + + public static native void setBoolean(int layer, String file, String section, String key, + boolean value); + + public static native void setInt(int layer, String file, String section, String key, int value); + + public static native void setFloat(int layer, String file, String section, String key, + float value); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java index 94dce9fcd0..5a63a3b654 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java @@ -59,7 +59,7 @@ public class Settings private IniFile getGameSpecificFile() { - if (TextUtils.isEmpty(gameId) || mIniFiles.size() != 1) + if (!isGameSpecific() || mIniFiles.size() != 1) throw new IllegalStateException(); return mIniFiles.get(GAME_SETTINGS_PLACEHOLDER_FILE_NAME); @@ -67,7 +67,7 @@ public class Settings public IniFile.Section getSection(String fileName, String sectionName) { - if (TextUtils.isEmpty(gameId)) + if (!isGameSpecific()) { return mIniFiles.get(fileName).getOrCreateSection(sectionName); } @@ -78,6 +78,11 @@ public class Settings } } + public boolean isGameSpecific() + { + return !TextUtils.isEmpty(gameId); + } + public boolean isEmpty() { return mIniFiles.isEmpty(); @@ -87,7 +92,7 @@ public class Settings { mIniFiles = new HashMap<>(); - if (TextUtils.isEmpty(gameId)) + if (!isGameSpecific()) { loadDolphinSettings(view); } @@ -129,7 +134,7 @@ public class Settings public void saveSettings(SettingsActivityView view, Context context) { - if (TextUtils.isEmpty(gameId)) + if (!isGameSpecific()) { if (context != null) Toast.makeText(context, "Saved settings to INI files", Toast.LENGTH_SHORT).show(); @@ -139,6 +144,8 @@ public class Settings SettingsFile.saveFile(entry.getKey(), entry.getValue(), view); } + NativeConfig.save(NativeConfig.LAYER_BASE_OR_CURRENT); + // Notify the native code of the changes NativeLibrary.ReloadConfig(); NativeLibrary.ReloadWiimoteConfig(); @@ -190,7 +197,7 @@ public class Settings // possible to know which lines were added intentionally by the user and which lines were added // unintentionally, which is why we have to delete the whole file in order to fix everything. - if (TextUtils.isEmpty(gameId)) + if (!isGameSpecific()) return false; return getSection(Settings.FILE_DOLPHIN, SECTION_INI_INTERFACE).exists("ThemeName"); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java index 627be71eda..14bf34221c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/StringSetting.java @@ -36,18 +36,40 @@ public enum StringSetting implements AbstractStringSetting @Override public boolean delete(Settings settings) { - return settings.getSection(mFile, mSection).delete(mKey); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.deleteKey(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey); + } + else + { + return settings.getSection(mFile, mSection).delete(mKey); + } } @Override public String getString(Settings settings) { - return settings.getSection(mFile, mSection).getString(mKey, mDefaultValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + return NativeConfig.getString(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, + mDefaultValue); + } + else + { + return settings.getSection(mFile, mSection).getString(mKey, mDefaultValue); + } } @Override public void setString(Settings settings, String newValue) { - settings.getSection(mFile, mSection).setString(mKey, newValue); + if (NativeConfig.isSettingSaveable(mFile, mSection, mKey) && !settings.isGameSpecific()) + { + NativeConfig.setString(NativeConfig.LAYER_BASE_OR_CURRENT, mFile, mSection, mKey, newValue); + } + else + { + settings.getSection(mFile, mSection).setString(mKey, newValue); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogCheckBoxSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogCheckBoxSetting.java index 0f046b40e8..f20be482af 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogCheckBoxSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/view/LogCheckBoxSetting.java @@ -1,6 +1,6 @@ package org.dolphinemu.dolphinemu.features.settings.model.view; -import org.dolphinemu.dolphinemu.features.settings.model.LegacyBooleanSetting; +import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting; import org.dolphinemu.dolphinemu.features.settings.model.Settings; public class LogCheckBoxSetting extends CheckBoxSetting @@ -9,7 +9,7 @@ public class LogCheckBoxSetting extends CheckBoxSetting public LogCheckBoxSetting(String key, int titleId, int descriptionId) { - super(new LegacyBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, key, false), + super(new AdHocBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, key, false), titleId, descriptionId); mKey = key; } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java index 5ba48985a0..01ecfd3ffc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsAdapter.java @@ -13,7 +13,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.dialogs.MotionAlertDialog; -import org.dolphinemu.dolphinemu.features.settings.model.LegacyBooleanSetting; +import org.dolphinemu.dolphinemu.features.settings.model.AdHocBooleanSetting; import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.StringSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.CheckBoxSetting; @@ -335,7 +335,7 @@ public final class SettingsAdapter extends RecyclerView.Adapter entry : SettingsFragmentPresenter.LOG_TYPE_NAMES.entrySet()) { - new LegacyBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, entry.getKey(), + new AdHocBooleanSetting(Settings.FILE_LOGGER, Settings.SECTION_LOGGER_LOGS, entry.getKey(), false).setBoolean(settings, value); } diff --git a/Source/Android/jni/CMakeLists.txt b/Source/Android/jni/CMakeLists.txt index 4e806c455b..e11e8dde76 100644 --- a/Source/Android/jni/CMakeLists.txt +++ b/Source/Android/jni/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(main SHARED GameList/GameFileCache.cpp IniFile.cpp MainAndroid.cpp + NativeConfig.cpp ) target_link_libraries(main diff --git a/Source/Android/jni/NativeConfig.cpp b/Source/Android/jni/NativeConfig.cpp new file mode 100644 index 0000000000..f499885b7d --- /dev/null +++ b/Source/Android/jni/NativeConfig.cpp @@ -0,0 +1,163 @@ +// Copyright 2020 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include + +#include + +#include "Common/Assert.h" +#include "Common/Config/Config.h" +#include "Core/ConfigLoaders/IsSettingSaveable.h" +#include "jni/AndroidCommon/AndroidCommon.h" + +constexpr jint LAYER_BASE_OR_CURRENT = 0; +constexpr jint LAYER_LOCAL_GAME = 1; + +static Config::Location GetLocation(JNIEnv* env, jstring file, jstring section, jstring key) +{ + const std::string decoded_file = GetJString(env, file); + + Config::System system; + if (decoded_file == "Dolphin") + { + system = Config::System::Main; + } + else if (decoded_file == "GFX") + { + system = Config::System::GFX; + } + else if (decoded_file == "Logger") + { + system = Config::System::Logger; + } + else + { + ASSERT(false); + return {}; + } + + return Config::Location{system, GetJString(env, section), GetJString(env, key)}; +} + +static std::shared_ptr GetLayer(jint layer, const Config::Location& location) +{ + switch (layer) + { + case LAYER_BASE_OR_CURRENT: + if (GetActiveLayerForConfig(location) == Config::LayerType::Base) + return Config::GetLayer(Config::LayerType::Base); + else + return Config::GetLayer(Config::LayerType::CurrentRun); + + case LAYER_LOCAL_GAME: + return Config::GetLayer(Config::LayerType::LocalGame); + + default: + ASSERT(false); + return nullptr; + } +} + +template +static T Get(jint layer, const Config::Location& location, T default_value) +{ + return GetLayer(layer, location)->Get(location).value_or(default_value); +} + +template +static void Set(jint layer, const Config::Location& location, T value) +{ + GetLayer(layer, location)->Set(location, value); + Config::InvokeConfigChangedCallbacks(); +} + +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_isSettingSaveable( + JNIEnv* env, jclass obj, jstring file, jstring section, jstring key) +{ + const Config::Location location = GetLocation(env, file, section, key); + return static_cast(ConfigLoaders::IsSettingSaveable(location)); +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_save( + JNIEnv* env, jclass obj, jint layer) +{ + return GetLayer(layer, {})->Save(); +} + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_deleteKey( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key) +{ + const Config::Location location = GetLocation(env, file, section, key); + return static_cast(GetLayer(layer, location)->DeleteKey(location)); +} + +JNIEXPORT jstring JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_getString( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, + jstring default_value) +{ + const Config::Location location = GetLocation(env, file, section, key); + return ToJString(env, Get(layer, location, GetJString(env, default_value))); +} + +JNIEXPORT jboolean JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_getBoolean( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, + jboolean default_value) +{ + const Config::Location location = GetLocation(env, file, section, key); + return static_cast(Get(layer, location, static_cast(default_value))); +} + +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_getInt( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, + jint default_value) +{ + return Get(layer, GetLocation(env, file, section, key), default_value); +} + +JNIEXPORT jfloat JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_getFloat( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, + jfloat default_value) +{ + return Get(layer, GetLocation(env, file, section, key), default_value); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_setString( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, jstring value) +{ + return Set(layer, GetLocation(env, file, section, key), GetJString(env, value)); +} + +JNIEXPORT void JNICALL +Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_setBoolean( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, jboolean value) +{ + return Set(layer, GetLocation(env, file, section, key), static_cast(value)); +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_setInt( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, jint value) +{ + return Set(layer, GetLocation(env, file, section, key), value); +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_settings_model_NativeConfig_setFloat( + JNIEnv* env, jclass obj, jint layer, jstring file, jstring section, jstring key, jfloat value) +{ + return Set(layer, GetLocation(env, file, section, key), value); +} + +#ifdef __cplusplus +} +#endif