From ba2aeb99d67bd31725139a8a09c6f69299d8932a Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 20 Oct 2020 19:40:04 +0200 Subject: [PATCH] Android: Remove hacks for Wii Remote extension setting, round 2 It's still not exactly pretty, but now all the mess is contained in one place and has a proper interface. Fixes https://bugs.dolphin-emu.org/issues/12218. --- .../features/settings/model/Settings.java | 5 - .../settings/model/WiimoteProfileSetting.java | 118 ++++++++++++++++++ .../ui/SettingsFragmentPresenter.java | 32 ++--- .../features/settings/utils/SettingsFile.java | 72 +---------- .../utils/DirectoryInitialization.java | 13 -- 5 files changed, 128 insertions(+), 112 deletions(-) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/WiimoteProfileSetting.java 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 422b97acae..79d29c644d 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 @@ -134,11 +134,6 @@ public class Settings implements Closeable mIniFiles.put(GAME_SETTINGS_PLACEHOLDER_FILE_NAME, ini); } - public void loadWiimoteProfile(String gameId, int padId) - { - SettingsFile.readWiimoteProfile(gameId, getGameSpecificFile(), padId); - } - public void loadSettings(String gameId, int revision, SettingsActivityView view) { mGameId = gameId; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/WiimoteProfileSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/WiimoteProfileSetting.java new file mode 100644 index 0000000000..2e6d2c2eaf --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/WiimoteProfileSetting.java @@ -0,0 +1,118 @@ +package org.dolphinemu.dolphinemu.features.settings.model; + +import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; +import org.dolphinemu.dolphinemu.utils.IniFile; + +import java.io.File; + +// This stuff is pretty ugly. It's a kind of workaround for certain controller settings +// not actually being available as game-specific settings. +// +// Warning: The current implementation of this should only be used for one setting at a time. +// Because each instance of this class keeps an IniFile around in memory, saving one profile +// setting to disk might overwrite changes that were made to other profile settings earlier. +// This system shouldn't be used for new settings anyway since the approach is fundamentally messy. +public class WiimoteProfileSetting implements AbstractStringSetting +{ + private final int mPadID; + + private final String mSection; + private final String mKey; + private final String mDefaultValue; + + private final String mProfileKey; + + private final String mProfile; + private final File mProfileFile; + private final IniFile mProfileIni; + + public WiimoteProfileSetting(String gameID, int padID, String section, String key, + String defaultValue) + { + mPadID = padID; + mSection = section; + mKey = key; + mDefaultValue = defaultValue; + + mProfileKey = SettingsFile.KEY_WIIMOTE_PROFILE + (mPadID + 1); + + mProfile = gameID + "_Wii" + padID; + mProfileFile = SettingsFile.getWiiProfile(mProfile); + mProfileIni = loadProfile(); + } + + @Override + public boolean isOverridden(Settings settings) + { + return isProfileEnabled(settings); + } + + @Override + public boolean isRuntimeEditable() + { + return false; + } + + @Override + public boolean delete(Settings settings) + { + return disableProfile(settings); + } + + @Override + public String getString(Settings settings) + { + if (isProfileEnabled(settings)) + return mProfileIni.getString(mSection, mKey, mDefaultValue); + else + return mDefaultValue; + } + + @Override + public void setString(Settings settings, String newValue) + { + mProfileIni.setString(mSection, mKey, newValue); + + mProfileIni.save(mProfileFile); + enableProfile(settings); + } + + private IniFile loadProfile() + { + IniFile profileIni = new IniFile(); + + if (!profileIni.load(mProfileFile, false)) + { + String defaultWiiProfilePath = DirectoryInitialization.getUserDirectory() + + "/Config/Profiles/Wiimote/WiimoteProfile.ini"; + + profileIni.load(defaultWiiProfilePath, false); + + profileIni.setString(Settings.SECTION_PROFILE, "Device", + "Android/" + (mPadID + 4) + "/Touchscreen"); + } + + return profileIni; + } + + private void enableProfile(Settings settings) + { + getControlsSection(settings).setString(mProfileKey, mProfile); + } + + private boolean disableProfile(Settings settings) + { + return getControlsSection(settings).delete(mProfileKey); + } + + private boolean isProfileEnabled(Settings settings) + { + return mProfile.equals(getControlsSection(settings).getString(mProfileKey, "")); + } + + private IniFile.Section getControlsSection(Settings s) + { + return s.getSection(Settings.GAME_SETTINGS_PLACEHOLDER_FILE_NAME, Settings.SECTION_CONTROLS); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index 711afb82a0..893c0241d0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.features.settings.model.AbstractIntSetting; +import org.dolphinemu.dolphinemu.features.settings.model.AbstractStringSetting; import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting; import org.dolphinemu.dolphinemu.features.settings.model.FloatSetting; import org.dolphinemu.dolphinemu.features.settings.model.IntSetting; @@ -14,6 +15,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.LegacyIntSetting; import org.dolphinemu.dolphinemu.features.settings.model.LegacyStringSetting; import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.StringSetting; +import org.dolphinemu.dolphinemu.features.settings.model.WiimoteProfileSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.CheckBoxSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.RunRunnable; import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker; @@ -33,7 +35,6 @@ import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; import org.dolphinemu.dolphinemu.ui.main.MainPresenter; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.EGLHelper; -import org.dolphinemu.dolphinemu.utils.IniFile; import org.dolphinemu.dolphinemu.utils.Log; import java.io.File; @@ -755,22 +756,21 @@ public final class SettingsFragmentPresenter private void addWiimoteSubSettings(ArrayList sl, int wiimoteNumber) { // Bindings use controller numbers 4-7 (0-3 are GameCube), but the extension setting uses 1-4. - // But game game specific extension settings are saved in their own profile. These profiles + // But game specific extension settings are saved in their own profile. These profiles // do not have any way to specify the controller that is loaded outside of knowing the filename // of the profile that was loaded. - LegacyStringSetting extension; + AbstractStringSetting extension; + final String defaultExtension = "None"; if (mGameID.isEmpty()) { extension = new LegacyStringSetting(Settings.FILE_WIIMOTE, Settings.SECTION_WIIMOTE + (wiimoteNumber - 3), SettingsFile.KEY_WIIMOTE_EXTENSION, - getExtensionValue(wiimoteNumber - 3)); + defaultExtension); } else { - mSettings.loadWiimoteProfile(mGameID, wiimoteNumber - 4); - extension = new LegacyStringSetting(Settings.GAME_SETTINGS_PLACEHOLDER_FILE_NAME, - Settings.SECTION_CONTROLS, SettingsFile.KEY_WIIMOTE_EXTENSION + (wiimoteNumber - 4), - getExtensionValue(wiimoteNumber - 4)); + extension = new WiimoteProfileSetting(mGameID, wiimoteNumber - 4, Settings.SECTION_PROFILE, + SettingsFile.KEY_WIIMOTE_EXTENSION, defaultExtension); } sl.add(new StringSingleChoiceSetting(extension, R.string.wiimote_extensions, 0, @@ -1189,22 +1189,6 @@ public final class SettingsFragmentPresenter } } - private String getExtensionValue(int wiimoteNumber) - { - IniFile.Section section; - if (mGameID.equals("")) // Main settings - { - section = mSettings.getSection(Settings.FILE_WIIMOTE, - Settings.SECTION_WIIMOTE + wiimoteNumber); - } - else // Game settings - { - section = mSettings.getSection(Settings.GAME_SETTINGS_PLACEHOLDER_FILE_NAME, - Settings.SECTION_PROFILE); - } - return section.getString(SettingsFile.KEY_WIIMOTE_EXTENSION, "None"); - } - private static int getLogVerbosityEntries() { // Value obtained from LOG_LEVELS in Common/Logging/Log.h diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java index e5238c460c..b058c6cd3f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java @@ -248,12 +248,6 @@ public final class SettingsFile readFile(getGenericGameSettingsForAllRegions(gameId), ini, view); } - public static void readWiimoteProfile(final String gameId, IniFile ini, final int padId) - { - String profile = gameId + "_Wii" + padId; - readFile(getWiiProfile(profile), ini, null); - } - /** * Saves a given .ini file on disk. * If unsuccessful, outputs an error telling why it failed. @@ -274,69 +268,7 @@ public final class SettingsFile public static void saveCustomGameSettings(final String gameId, IniFile ini) { - IniFile iniCopy = new IniFile(ini); - - // Profile options(wii extension) are not saved, only used to properly display values - iniCopy.deleteSection(Settings.SECTION_PROFILE); - - for (int i = 0; i < 3; i++) - { - String key = SettingsFile.KEY_WIIMOTE_EXTENSION + i; - if (iniCopy.exists(Settings.SECTION_CONTROLS, key)) - { - // Special case. Extension gets saved into a controller profile - String value = iniCopy.getString(Settings.SECTION_CONTROLS, key, ""); - saveCustomWiimoteSetting(gameId, KEY_WIIMOTE_EXTENSION, value, i); - iniCopy.deleteKey(Settings.SECTION_CONTROLS, key); - } - } - - iniCopy.save(getCustomGameSettingsFile(gameId)); - } - - /** - * Saves the wiimote setting in a profile and enables that profile. - * - * @param gameId - * @param key - * @param value - * @param padId - */ - private static void saveCustomWiimoteSetting(final String gameId, final String key, - final String value, final int padId) - { - String profile = gameId + "_Wii" + padId; - String wiiConfigPath = - DirectoryInitialization.getUserDirectory() + "/Config/Profiles/Wiimote/" + - profile + ".ini"; - File wiiProfile = getWiiProfile(profile); - // If it doesn't exist, create it - boolean wiiProfileExists = wiiProfile.exists(); - if (!wiiProfileExists) - { - String defautlWiiProfilePath = - DirectoryInitialization.getUserDirectory() + - "/Config/Profiles/Wiimote/WiimoteProfile.ini"; - DirectoryInitialization.copyFile(defautlWiiProfilePath, wiiConfigPath); - } - - IniFile wiiProfileIni = new IniFile(wiiConfigPath); - - if (!wiiProfileExists) - { - wiiProfileIni.setString(Settings.SECTION_PROFILE, "Device", - "Android/" + (padId + 4) + "/Touchscreen"); - } - - wiiProfileIni.setString(Settings.SECTION_PROFILE, key, value); - wiiProfileIni.save(wiiConfigPath); - - // Enable the profile - File gameSettingsFile = SettingsFile.getCustomGameSettingsFile(gameId); - IniFile gameSettingsIni = new IniFile(gameSettingsFile); - gameSettingsIni.setString(Settings.SECTION_CONTROLS, KEY_WIIMOTE_PROFILE + (padId + 1), - profile); - gameSettingsIni.save(gameSettingsFile); + ini.save(getCustomGameSettingsFile(gameId)); } public static String mapSectionNameFromIni(String generalSectionName) @@ -388,7 +320,7 @@ public final class SettingsFile DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"); } - private static File getWiiProfile(String profile) + public static File getWiiProfile(String profile) { String wiiConfigPath = DirectoryInitialization.getUserDirectory() + "/Config/Profiles/Wiimote/" + diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index 4e293dfc4a..d94a2d63e2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -320,19 +320,6 @@ public final class DirectoryInitialization } } - public static void copyFile(String from, String to) - { - try - { - InputStream in = new FileInputStream(from); - OutputStream out = new FileOutputStream(to); - copyFile(in, out); - } - catch (IOException ignored) - { - } - } - private static void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024];