This file was deleted.

@@ -7,7 +7,9 @@
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.utils.IniFile;

import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -40,79 +42,51 @@
public static final String SECTION_CONTROLS = "Controls";
public static final String SECTION_PROFILE = "Profile";

private static final String DSP_HLE = "0";
private static final String DSP_LLE_RECOMPILER = "1";
private static final String DSP_LLE_INTERPRETER = "2";
private static final int DSP_HLE = 0;
private static final int DSP_LLE_RECOMPILER = 1;
private static final int DSP_LLE_INTERPRETER = 2;

public static final String SECTION_ANALYTICS = "Analytics";

public static final String GAME_SETTINGS_PLACEHOLDER_FILE_NAME = "";

private String gameId;

private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
private static final String[] configFiles = new String[]{SettingsFile.FILE_NAME_DOLPHIN,
SettingsFile.FILE_NAME_GFX, SettingsFile.FILE_NAME_LOGGER,
SettingsFile.FILE_NAME_WIIMOTE};

static
{
configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN,
Arrays
.asList(SECTION_INI_ANDROID, SECTION_INI_GENERAL, SECTION_INI_CORE,
SECTION_INI_INTERFACE,
SECTION_INI_DSP, SECTION_BINDINGS, SECTION_ANALYTICS, SECTION_DEBUG));
configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX,
Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS,
SECTION_STEREOSCOPY));
configFileSectionsMap.put(SettingsFile.FILE_NAME_LOGGER,
Arrays.asList(SECTION_LOGGER_LOGS, SECTION_LOGGER_OPTIONS));
configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE,
Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3,
SECTION_WIIMOTE + 4));
}
private HashMap<String, IniFile> mIniFiles = new HashMap<>();

/**
* A HashMap<String, SettingSection> that constructs a new SettingSection instead of returning null
* when getting a key not already in the map
*/
public static final class SettingsSectionMap extends HashMap<String, SettingSection>
private IniFile getGameSpecificFile()
{
@Override
public SettingSection get(Object key)
{
if (!(key instanceof String))
{
return null;
}

String stringKey = (String) key;
if (TextUtils.isEmpty(gameId) || mIniFiles.size() != 1)
throw new IllegalStateException();

if (!super.containsKey(stringKey))
{
SettingSection section = new SettingSection(stringKey);
super.put(stringKey, section);
return section;
}
return super.get(key);
}
return mIniFiles.get(GAME_SETTINGS_PLACEHOLDER_FILE_NAME);
}

private HashMap<String, SettingSection> sections = new Settings.SettingsSectionMap();

public SettingSection getSection(String sectionName)
public IniFile.Section getSection(String fileName, String sectionName)
{
return sections.get(sectionName);
if (TextUtils.isEmpty(gameId))
{
return mIniFiles.get(fileName).getOrCreateSection(sectionName);
}
else
{
return getGameSpecificFile()
.getOrCreateSection(SettingsFile.mapSectionNameFromIni(sectionName));
}
}

public boolean isEmpty()
{
return sections.isEmpty();
}

public HashMap<String, SettingSection> getSections()
{
return sections;
return mIniFiles.isEmpty();
}

public void loadSettings(SettingsActivityView view)
{
sections = new Settings.SettingsSectionMap();
mIniFiles = new HashMap<>();

if (TextUtils.isEmpty(gameId))
{
@@ -126,46 +100,24 @@ public void loadSettings(SettingsActivityView view)

private void loadDolphinSettings(SettingsActivityView view)
{
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
for (String fileName : configFiles)
{
String fileName = entry.getKey();
sections.putAll(SettingsFile.readFile(fileName, view));
IniFile ini = new IniFile();
SettingsFile.readFile(fileName, ini, view);
mIniFiles.put(fileName, ini);
}
}

private void loadGenericGameSettings(String gameId, SettingsActivityView view)
{
// generic game settings
mergeSections(SettingsFile.readGenericGameSettings(gameId, view));
mergeSections(SettingsFile.readGenericGameSettingsForAllRegions(gameId, view));
}

private void loadCustomGameSettings(String gameId, SettingsActivityView view)
{
// custom game settings
mergeSections(SettingsFile.readCustomGameSettings(gameId, view));
IniFile ini = new IniFile();
SettingsFile.readCustomGameSettings(gameId, ini, view);
mIniFiles.put(GAME_SETTINGS_PLACEHOLDER_FILE_NAME, ini);
}

public void loadWiimoteProfile(String gameId, String padId)
public void loadWiimoteProfile(String gameId, int padId)
{
mergeSections(SettingsFile.readWiimoteProfile(gameId, padId));
}

private void mergeSections(HashMap<String, SettingSection> updatedSections)
{
for (Map.Entry<String, SettingSection> entry : updatedSections.entrySet())
{
if (sections.containsKey(entry.getKey()))
{
SettingSection originalSection = sections.get(entry.getKey());
SettingSection updatedSection = entry.getValue();
originalSection.mergeSection(updatedSection);
}
else
{
sections.put(entry.getKey(), entry.getValue());
}
}
SettingsFile.readWiimoteProfile(gameId, getGameSpecificFile(), padId);
}

public void loadSettings(String gameId, SettingsActivityView view)
@@ -180,52 +132,36 @@ public void saveSettings(SettingsActivityView view, Context context, Set<String>
{
view.showToastMessage("Saved settings to INI files");

for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
for (Map.Entry<String, IniFile> entry : mIniFiles.entrySet())
{
String fileName = entry.getKey();
List<String> sectionNames = entry.getValue();
TreeMap<String, SettingSection> iniSections = new TreeMap<>();
for (String section : sectionNames)
{
iniSections.put(section, sections.get(section));
}

SettingsFile.saveFile(fileName, iniSections, view);
SettingsFile.saveFile(entry.getKey(), entry.getValue(), view);
}

if (modifiedSettings.contains(SettingsFile.KEY_DSP_ENGINE))
{
switch (NativeLibrary
.GetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_ANDROID,
SettingsFile.KEY_DSP_ENGINE, DSP_HLE))
File dolphinFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_DOLPHIN);
IniFile dolphinIni = new IniFile(dolphinFile);

switch (dolphinIni.getInt(Settings.SECTION_INI_ANDROID, SettingsFile.KEY_DSP_ENGINE,
DSP_HLE))
{
case DSP_HLE:
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_CORE,
SettingsFile.KEY_DSP_HLE, "True");
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_DSP,
SettingsFile.KEY_DSP_ENABLE_JIT, "True");
dolphinIni.setBoolean(Settings.SECTION_INI_CORE, SettingsFile.KEY_DSP_HLE, true);
dolphinIni.setBoolean(Settings.SECTION_INI_DSP, SettingsFile.KEY_DSP_ENABLE_JIT, true);
break;

case DSP_LLE_RECOMPILER:
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_CORE,
SettingsFile.KEY_DSP_HLE, "False");
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_DSP,
SettingsFile.KEY_DSP_ENABLE_JIT, "True");
dolphinIni.setBoolean(Settings.SECTION_INI_CORE, SettingsFile.KEY_DSP_HLE, false);
dolphinIni.setBoolean(Settings.SECTION_INI_DSP, SettingsFile.KEY_DSP_ENABLE_JIT, true);
break;

case DSP_LLE_INTERPRETER:
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_CORE,
SettingsFile.KEY_DSP_HLE, "False");
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_DSP,
SettingsFile.KEY_DSP_ENABLE_JIT, "False");
dolphinIni.setBoolean(Settings.SECTION_INI_CORE, SettingsFile.KEY_DSP_HLE, false);
dolphinIni.setBoolean(Settings.SECTION_INI_DSP, SettingsFile.KEY_DSP_ENABLE_JIT, false);
break;
}

dolphinIni.save(dolphinFile);
}

// Notify the native code of the changes
@@ -246,13 +182,16 @@ public void saveSettings(SettingsActivityView view, Context context, Set<String>
{
// custom game settings
view.showToastMessage("Saved settings for " + gameId);
SettingsFile.saveCustomGameSettings(gameId, sections);
SettingsFile.saveCustomGameSettings(gameId, getGameSpecificFile());
}
}

public void clearSettings()
{
sections.clear();
for (String fileName : mIniFiles.keySet())
{
mIniFiles.put(fileName, new IniFile());
}
}

public boolean gameIniContainsJunk()
@@ -278,7 +217,6 @@ public boolean gameIniContainsJunk()
if (TextUtils.isEmpty(gameId))
return false;

SettingSection interfaceSection = sections.get("Interface");
return interfaceSection != null && interfaceSection.getSetting("ThemeName") != null;
return getSection(SettingsFile.FILE_NAME_DOLPHIN, SECTION_INI_INTERFACE).exists("ThemeName");
}
}

This file was deleted.

@@ -1,51 +1,26 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public final class CheckBoxSetting extends SettingsItem
public class CheckBoxSetting extends SettingsItem
{
private boolean mDefaultValue;
protected boolean mDefaultValue;

public CheckBoxSetting(String key, String section, int titleId, int descriptionId,
boolean defaultValue, Setting setting)
public CheckBoxSetting(String file, String section, String key, int titleId, int descriptionId,
boolean defaultValue)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, titleId, descriptionId);
mDefaultValue = defaultValue;
}

public boolean isChecked()
public boolean isChecked(Settings settings)
{
if (getSetting() == null || !(getSetting() instanceof BooleanSetting))
{
return mDefaultValue;
}

BooleanSetting setting = (BooleanSetting) getSetting();
return setting.getValue();
return settings.getSection(getFile(), getSection()).getBoolean(getKey(), mDefaultValue);
}

/**
* Write a value to the backing boolean. If that boolean was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param checked Pretty self explanatory.
* @return null if overwritten successfully; otherwise, a newly created BooleanSetting.
*/
public BooleanSetting setChecked(boolean checked)
public void setChecked(Settings settings, boolean checked)
{
if (getSetting() == null || !(getSetting() instanceof BooleanSetting))
{
BooleanSetting setting = new BooleanSetting(getKey(), getSection(), checked);
setSetting(setting);
return setting;
}
else
{
BooleanSetting setting = (BooleanSetting) getSetting();
setting.setValue(checked);
return null;
}
settings.getSection(getFile(), getSection()).setBoolean(getKey(), checked);
}

@Override
@@ -1,39 +1,23 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public final class FilePicker extends SettingsItem
{
private String mFile;
private String mDefaultValue;
private int mRequestType;

public FilePicker(String file, String key, String section, int titleId, int descriptionId,
String defaultVault, int requestType, Setting setting)
public FilePicker(String file, String section, String key, int titleId, int descriptionId,
String defaultVault, int requestType)
{
super(key, section, setting, titleId, descriptionId);
mFile = file;
super(file, section, key, titleId, descriptionId);
mDefaultValue = defaultVault;
mRequestType = requestType;
}

public String getFile()
public String getSelectedValue(Settings settings)
{
return mFile + ".ini";
}

public String getSelectedValue()
{
if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
return mDefaultValue;
}
else
{
StringSetting setting = (StringSetting) getSetting();
return setting.getValue();
}
return settings.getSection(getFile(), getSection()).getString(getKey(), mDefaultValue);
}

public int getRequestType()
@@ -0,0 +1,26 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public class FloatSliderSetting extends SliderSetting
{
protected float mDefaultValue;

public FloatSliderSetting(String file, String section, String key, int titleId, int descriptionId,
int max, String units, float defaultValue)
{
super(file, section, key, titleId, descriptionId, max, units);
mDefaultValue = defaultValue;
}

public int getSelectedValue(Settings settings)
{
float value = settings.getSection(getFile(), getSection()).getFloat(getKey(), mDefaultValue);
return Math.round(value);
}

public void setSelectedValue(Settings settings, float selection)
{
settings.getSection(getFile(), getSection()).setFloat(getKey(), selection);
}
}
@@ -1,12 +1,10 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Setting;

public final class HeaderSetting extends SettingsItem
{
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId)
public HeaderSetting(String key, int titleId, int descriptionId)
{
super(key, null, setting, titleId, descriptionId);
super(null, null, key, titleId, descriptionId);
}

@Override
@@ -6,29 +6,21 @@
import android.view.KeyEvent;

import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public class InputBindingSetting extends SettingsItem
{
private String gameId;

public InputBindingSetting(String key, String section, int titleId, Setting setting,
String gameId)
public InputBindingSetting(String file, String section, String key, int titleId, String gameId)
{
super(key, section, setting, titleId, 0);
super(file, section, key, titleId, 0);
this.gameId = gameId;
}

public String getValue()
public String getValue(Settings settings)
{
if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
return "";
}

StringSetting setting = (StringSetting) getSetting();
return setting.getValue();
return settings.getSection(getFile(), getSection()).getString(getKey(), "");
}

/**
@@ -37,12 +29,12 @@ public String getValue()
*
* @param keyEvent KeyEvent of this key press.
*/
public void onKeyInput(KeyEvent keyEvent)
public void onKeyInput(Settings settings, KeyEvent keyEvent)
{
InputDevice device = keyEvent.getDevice();
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
setValue(bindStr, uiString);
setValue(settings, bindStr, uiString);
}

/**
@@ -53,23 +45,16 @@ public void onKeyInput(KeyEvent keyEvent)
* @param motionRange MotionRange of the movement
* @param axisDir Either '-' or '+'
*/
public void onMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
char axisDir)
public void onMotionInput(Settings settings, InputDevice device,
InputDevice.MotionRange motionRange, char axisDir)
{
String bindStr =
"Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
setValue(bindStr, uiString);
setValue(settings, bindStr, uiString);
}

/**
* Write a value to the backing string. If that string was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param bind The input that will be bound
* @return null if overwritten successfully; otherwise, a newly created StringSetting.
*/
public StringSetting setValue(String bind, String ui)
public void setValue(Settings settings, String bind, String ui)
{
SharedPreferences
preferences =
@@ -78,23 +63,12 @@ public StringSetting setValue(String bind, String ui)
editor.putString(getKey() + gameId, ui);
editor.apply();

if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
StringSetting setting = new StringSetting(getKey(), getSection(), bind);
setSetting(setting);
return setting;
}
else
{
StringSetting setting = (StringSetting) getSetting();
setting.setValue(bind);
return null;
}
settings.getSection(getFile(), getSection()).setString(getKey(), bind);
}

public void clearValue()
public void clearValue(Settings settings)
{
setValue("", "");
setValue(settings, "", "");
}

@Override
@@ -0,0 +1,25 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public final class IntSliderSetting extends SliderSetting
{
private int mDefaultValue;

public IntSliderSetting(String file, String section, String key, int titleId, int descriptionId,
int max, String units, int defaultValue)
{
super(file, section, key, titleId, descriptionId, max, units);
mDefaultValue = defaultValue;
}

public int getSelectedValue(Settings settings)
{
return settings.getSection(getFile(), getSection()).getInt(getKey(), mDefaultValue);
}

public void setSelectedValue(Settings settings, int selection)
{
settings.getSection(getFile(), getSection()).setInt(getKey(), selection);
}
}
@@ -0,0 +1,25 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;

public final class InvertedCheckBoxSetting extends CheckBoxSetting
{
public InvertedCheckBoxSetting(String file, String section, String key, int titleId,
int descriptionId, boolean defaultValue)
{
super(file, section, key, titleId, descriptionId, !defaultValue);
}

@Override
public boolean isChecked(Settings settings)
{
return !settings.getSection(getFile(), getSection()).getBoolean(getKey(), mDefaultValue);
}

@Override
public void setChecked(Settings settings, boolean checked)
{
settings.getSection(getFile(), getSection()).setBoolean(getKey(), !checked);
}
}
@@ -0,0 +1,25 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Settings;

public final class PercentSliderSetting extends FloatSliderSetting
{
public PercentSliderSetting(String file, String section, String key, int titleId,
int descriptionId, int max, String units, float defaultValue)
{
super(file, section, key, titleId, descriptionId, max, units, defaultValue / 100);
}

@Override
public int getSelectedValue(Settings settings)
{
float value = settings.getSection(getFile(), getSection()).getFloat(getKey(), mDefaultValue);
return Math.round(value * 100);
}

@Override
public void setSelectedValue(Settings settings, float selection)
{
settings.getSection(getFile(), getSection()).setFloat(getKey(), selection / 100);
}
}
@@ -6,62 +6,46 @@

import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.utils.Rumble;

public class RumbleBindingSetting extends InputBindingSetting
{

public RumbleBindingSetting(String key, String section, int titleId, Setting setting,
String gameId)
{
super(key, section, titleId, setting, gameId);
}

@Override
public String getValue()
public RumbleBindingSetting(String file, String section, String key, int titleId, String gameId)
{
if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
return "";
}

StringSetting setting = (StringSetting) getSetting();
return setting.getValue();
super(file, section, key, titleId, gameId);
}

/**
* Just need the device when saving rumble.
*/
@Override
public void onKeyInput(KeyEvent keyEvent)
public void onKeyInput(Settings settings, KeyEvent keyEvent)
{
saveRumble(keyEvent.getDevice());
saveRumble(settings, keyEvent.getDevice());
}

/**
* Just need the device when saving rumble.
*/
@Override
public void onMotionInput(InputDevice device,
InputDevice.MotionRange motionRange,
char axisDir)
public void onMotionInput(Settings settings, InputDevice device,
InputDevice.MotionRange motionRange, char axisDir)
{
saveRumble(device);
saveRumble(settings, device);
}

private void saveRumble(InputDevice device)
private void saveRumble(Settings settings, InputDevice device)
{
Vibrator vibrator = device.getVibrator();
if (vibrator != null && vibrator.hasVibrator())
{
setValue(device.getDescriptor(), device.getName());
setValue(settings, device.getDescriptor(), device.getName());
Rumble.doRumble(vibrator);
}
else
{
setValue("",
setValue(settings, "",
DolphinApplication.getAppContext().getString(R.string.rumble_not_found));
}
}
@@ -1,14 +1,11 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;

/**
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
* Each one corresponds to a {@link Setting} object, so this class's subclasses
* should vaguely correspond to those subclasses. There are a few with multiple analogues
* and a few with none (Headers, for example, do not correspond to anything in the ini
* file.)
* Most of them correspond to a single line in an INI file, but there are a few with multiple
* analogues and a few with none (Headers, for example, do not correspond to anything on disk.)
*/
public abstract class SettingsItem
{
@@ -24,72 +21,58 @@
public static final int TYPE_FILE_PICKER = 9;
public static final int TYPE_CONFIRM_RUNNABLE = 10;

private String mKey;
private String mFile;
private String mSection;

private Setting mSetting;
private String mKey;

private int mNameId;
private int mDescriptionId;

/**
* Base constructor. Takes a key / section name in case the third parameter, the Setting,
* is null; in which case, one can be constructed and saved using the key / section.
* Base constructor.
*
* @param key Identifier for the Setting represented by this Item.
* @param file File to which the Setting belongs.
* @param section Section to which the Setting belongs.
* @param setting A possibly-null backing Setting, to be modified on UI events.
* @param key Identifier for the Setting represented by this Item.
* @param nameId Resource ID for a text string to be displayed as this setting's name.
* @param descriptionId Resource ID for a text string to be displayed as this setting's description.
*/

public SettingsItem(String key, String section, Setting setting, int nameId, int descriptionId)
public SettingsItem(String file, String section, String key, int nameId, int descriptionId)
{
mKey = key;
mFile = file;
mSection = section;
mSetting = setting;
mKey = key;
mNameId = nameId;
mDescriptionId = descriptionId;
}

/**
* @return The identifier for the backing Setting.
* @return The file in which the backing setting belongs.
*/
public String getKey()
public String getFile()
{
return mKey;
return mFile;
}

/**
* @return The header under which the backing Setting belongs.
* @return The header under which the backing setting belongs.
*/
public String getSection()
{
return mSection;
}


/**
* @return The backing Setting, possibly null.
* @return The identifier for the backing setting.
*/
public Setting getSetting()
{
return mSetting;
}

/**
* Replace the backing setting with a new one. Generally used in cases where
* the backing setting is null.
*
* @param setting A non-null Setting.
*/
public void setSetting(Setting setting)
public String getKey()
{
mSetting = setting;
return mKey;
}

/**
* @return A resource ID for a text string representing this Setting's name.
* @return A resource ID for a text string representing this setting's name.
*/
public int getNameId()
{
@@ -1,7 +1,6 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public final class SingleChoiceSetting extends SettingsItem
@@ -12,20 +11,20 @@ public final class SingleChoiceSetting extends SettingsItem
private int mValuesId;
private MenuTag menuTag;

public SingleChoiceSetting(String key, String section, int titleId, int descriptionId,
int choicesId, int valuesId, int defaultValue, Setting setting, MenuTag menuTag)
public SingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, int choicesId, int valuesId, int defaultValue, MenuTag menuTag)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, titleId, descriptionId);
mValuesId = valuesId;
mChoicesId = choicesId;
mDefaultValue = defaultValue;
this.menuTag = menuTag;
}

public SingleChoiceSetting(String key, String section, int titleId, int descriptionId,
int choicesId, int valuesId, int defaultValue, Setting setting)
public SingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, int choicesId, int valuesId, int defaultValue)
{
this(key, section, titleId, descriptionId, choicesId, valuesId, defaultValue, setting, null);
this(file, section, key, titleId, descriptionId, choicesId, valuesId, defaultValue, null);
}

public int getChoicesId()
@@ -38,45 +37,19 @@ public int getValuesId()
return mValuesId;
}

public int getSelectedValue()
public int getSelectedValue(Settings settings)
{
if (getSetting() == null || !(getSetting() instanceof IntSetting))
{
return mDefaultValue;
}
else
{
IntSetting setting = (IntSetting) getSetting();
return setting.getValue();
}
return settings.getSection(getFile(), getSection()).getInt(getKey(), mDefaultValue);
}

public MenuTag getMenuTag()
{
return menuTag;
}

/**
* Write a value to the backing int. If that int was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param selection New value of the int.
* @return null if overwritten successfully otherwise; a newly created IntSetting.
*/
public IntSetting setSelectedValue(int selection)
public void setSelectedValue(Settings settings, int selection)
{
if (getSetting() == null || !(getSetting() instanceof IntSetting))
{
IntSetting setting = new IntSetting(getKey(), getSection(), selection);
setSetting(setting);
return setting;
}
else
{
IntSetting setting = (IntSetting) getSetting();
setting.setValue(selection);
return null;
}
settings.getSection(getFile(), getSection()).setInt(getKey(), selection);
}

@Override
@@ -1,7 +1,6 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public final class SingleChoiceSettingDynamicDescriptions extends SettingsItem
@@ -14,12 +13,11 @@ public final class SingleChoiceSettingDynamicDescriptions extends SettingsItem
private int mDescriptionValuesId;
private MenuTag menuTag;

public SingleChoiceSettingDynamicDescriptions(String key, String section, int titleId,
int descriptionId,
int choicesId, int valuesId, int descriptionChoicesId, int descriptionValuesId,
int defaultValue, Setting setting, MenuTag menuTag)
public SingleChoiceSettingDynamicDescriptions(String file, String section, String key,
int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
int descriptionValuesId, int defaultValue, MenuTag menuTag)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, titleId, descriptionId);
mValuesId = valuesId;
mChoicesId = choicesId;
mDescriptionChoicesId = descriptionChoicesId;
@@ -28,13 +26,12 @@ public SingleChoiceSettingDynamicDescriptions(String key, String section, int ti
this.menuTag = menuTag;
}

public SingleChoiceSettingDynamicDescriptions(String key, String section, int titleId,
int descriptionId,
int choicesId, int valuesId, int descriptionChoicesId, int descriptionValuesId,
int defaultValue, Setting setting)
public SingleChoiceSettingDynamicDescriptions(String file, String section, String key,
int titleId, int descriptionId, int choicesId, int valuesId, int descriptionChoicesId,
int descriptionValuesId, int defaultValue)
{
this(key, section, titleId, descriptionId, choicesId, valuesId, descriptionChoicesId,
descriptionValuesId, defaultValue, setting, null);
this(file, section, key, titleId, descriptionId, choicesId, valuesId, descriptionChoicesId,
descriptionValuesId, defaultValue, null);
}

public int getChoicesId()
@@ -57,45 +54,19 @@ public int getDescriptionValuesId()
return mDescriptionValuesId;
}

public int getSelectedValue()
public int getSelectedValue(Settings settings)
{
if (getSetting() == null || !(getSetting() instanceof IntSetting))
{
return mDefaultValue;
}
else
{
IntSetting setting = (IntSetting) getSetting();
return setting.getValue();
}
return settings.getSection(getFile(), getSection()).getInt(getKey(), mDefaultValue);
}

public MenuTag getMenuTag()
{
return menuTag;
}

/**
* Write a value to the backing int. If that int was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param selection New value of the int.
* @return null if overwritten successfully otherwise; a newly created IntSetting.
*/
public IntSetting setSelectedValue(int selection)
public void setSelectedValue(Settings settings, int selection)
{
if (getSetting() == null || !(getSetting() instanceof IntSetting))
{
IntSetting setting = new IntSetting(getKey(), getSection(), selection);
setSetting(setting);
return setting;
}
else
{
IntSetting setting = (IntSetting) getSetting();
setting.setValue(selection);
return null;
}
settings.getSection(getFile(), getSection()).setInt(getKey(), selection);
}

@Override
@@ -1,117 +1,28 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.FloatSetting;
import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.utils.Log;

public final class SliderSetting extends SettingsItem
public abstract class SliderSetting extends SettingsItem
{
private int mMax;
private int mDefaultValue;

private String mUnits;

public SliderSetting(String key, String section, int titleId, int descriptionId, int max,
String units, int defaultValue, Setting setting)
public SliderSetting(String file, String section, String key, int nameId, int descriptionId,
int max, String units)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, nameId, descriptionId);
mMax = max;
mUnits = units;
mDefaultValue = defaultValue;
}

public abstract int getSelectedValue(Settings settings);

public int getMax()
{
return mMax;
}

public int getSelectedValue()
{
Setting setting = getSetting();

if (setting == null)
{
return mDefaultValue;
}

if (setting instanceof IntSetting)
{
IntSetting intSetting = (IntSetting) setting;
return intSetting.getValue();
}
else if (setting instanceof FloatSetting)
{
FloatSetting floatSetting = (FloatSetting) setting;
if (isPercentSetting())
{
return Math.round(floatSetting.getValue() * 100);
}
else
{
return Math.round(floatSetting.getValue());
}
}
else
{
Log.error("[SliderSetting] Error casting setting type.");
return -1;
}
}

public boolean isPercentSetting()
{
return getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)
|| getKey().equals(SettingsFile.KEY_SPEED_LIMIT);
}

/**
* Write a value to the backing int. If that int was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param selection New value of the int.
* @return null if overwritten successfully otherwise; a newly created IntSetting.
*/
public IntSetting setSelectedValue(int selection)
{
if (getSetting() == null || !(getSetting() instanceof IntSetting))
{
IntSetting setting = new IntSetting(getKey(), getSection(), selection);
setSetting(setting);
return setting;
}
else
{
IntSetting setting = (IntSetting) getSetting();
setting.setValue(selection);
return null;
}
}

/**
* Write a value to the backing float. If that float was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param selection New value of the float.
* @return null if overwritten successfully otherwise; a newly created FloatSetting.
*/
public FloatSetting setSelectedValue(float selection)
{
if (getSetting() == null || !(getSetting() instanceof FloatSetting))
{
FloatSetting setting = new FloatSetting(getKey(), getSection(), selection);
setSetting(setting);
return setting;
}
else
{
FloatSetting setting = (FloatSetting) getSetting();
setting.setValue(selection);
return null;
}
}

public String getUnits()
{
return mUnits;
@@ -1,8 +1,7 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public class StringSingleChoiceSetting extends SettingsItem
@@ -13,37 +12,37 @@ public class StringSingleChoiceSetting extends SettingsItem
private String[] mValuesId;
private MenuTag mMenuTag;

public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId,
String[] choicesId, String[] valuesId, String defaultValue, Setting setting,
public StringSingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, String[] choicesId, String[] valuesId, String defaultValue,
MenuTag menuTag)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, titleId, descriptionId);
mChoicesId = choicesId;
mValuesId = valuesId;
mDefaultValue = defaultValue;
mMenuTag = menuTag;
}

public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId,
String[] choicesId, String[] valuesId, String defaultValue, Setting setting)
public StringSingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, String[] choicesId, String[] valuesId, String defaultValue)
{
this(key, section, titleId, descriptionId, choicesId, valuesId, defaultValue, setting, null);
this(file, section, key, titleId, descriptionId, choicesId, valuesId, defaultValue, null);
}

public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId,
int choicesId, int valuesId, String defaultValue, Setting setting, MenuTag menuTag)
public StringSingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, int choicesId, int valuesId, String defaultValue, MenuTag menuTag)
{
super(key, section, setting, titleId, descriptionId);
super(file, section, key, titleId, descriptionId);
mChoicesId = DolphinApplication.getAppContext().getResources().getStringArray(choicesId);
mValuesId = DolphinApplication.getAppContext().getResources().getStringArray(valuesId);
mDefaultValue = defaultValue;
mMenuTag = menuTag;
}

public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId,
int choicesId, int valuesId, String defaultValue, Setting setting)
public StringSingleChoiceSetting(String file, String section, String key, int titleId,
int descriptionId, int choicesId, int valuesId, String defaultValue)
{
this(key, section, titleId, descriptionId, choicesId, valuesId, defaultValue, setting, null);
this(file, section, key, titleId, descriptionId, choicesId, valuesId, defaultValue, null);
}

public String[] getChoicesId()
@@ -69,22 +68,14 @@ public String getValueAt(int index)
return "";
}

public String getSelectedValue()
public String getSelectedValue(Settings settings)
{
if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
return mDefaultValue;
}
else
{
StringSetting setting = (StringSetting) getSetting();
return setting.getValue();
}
return settings.getSection(getFile(), getSection()).getString(getKey(), mDefaultValue);
}

public int getSelectValueIndex()
public int getSelectValueIndex(Settings settings)
{
String selectedValue = getSelectedValue();
String selectedValue = getSelectedValue(settings);
for (int i = 0; i < mValuesId.length; i++)
{
if (mValuesId[i].equals(selectedValue))
@@ -101,27 +92,9 @@ public MenuTag getMenuTag()
return mMenuTag;
}

/**
* Write a value to the backing int. If that int was previously null,
* initializes a new one and returns it, so it can be added to the Hashmap.
*
* @param selection New value of the int.
* @return null if overwritten successfully otherwise; a newly created IntSetting.
*/
public StringSetting setSelectedValue(String selection)
public void setSelectedValue(Settings settings, String selection)
{
if (getSetting() == null || !(getSetting() instanceof StringSetting))
{
StringSetting setting = new StringSetting(getKey(), getSection(), selection);
setSetting(setting);
return setting;
}
else
{
StringSetting setting = (StringSetting) getSetting();
setting.setValue(selection);
return null;
}
settings.getSection(getFile(), getSection()).setString(getKey(), selection);
}

@Override
@@ -1,15 +1,14 @@
package org.dolphinemu.dolphinemu.features.settings.model.view;

import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;

public final class SubmenuSetting extends SettingsItem
{
private MenuTag mMenuKey;

public SubmenuSetting(String key, Setting setting, int titleId, MenuTag menuKey)
public SubmenuSetting(String key, int titleId, MenuTag menuKey)
{
super(key, null, setting, titleId, 0);
super(null, null, key, titleId, 0);
mMenuKey = menuKey;
}

@@ -15,14 +15,12 @@
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.dialogs.MotionAlertDialog;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.model.FloatSetting;
import org.dolphinemu.dolphinemu.features.settings.model.IntSetting;
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;
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
import org.dolphinemu.dolphinemu.features.settings.model.view.FloatSliderSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.InputBindingSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.RumbleBindingSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting;
@@ -43,7 +41,9 @@
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.IniFile;

import java.io.File;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -151,6 +151,11 @@ public int getItemViewType(int position)
return getItem(position).getType();
}

public Settings getSettings()
{
return mView.getSettings();
}

public void setSettings(ArrayList<SettingsItem> settings)
{
mSettings = settings;
@@ -159,20 +164,9 @@ public void setSettings(ArrayList<SettingsItem> settings)

public void onBooleanClick(CheckBoxSetting item, int position, boolean checked)
{
BooleanSetting setting = item.setChecked(checked);
item.setChecked(getSettings(), checked);
notifyItemChanged(position);

if (setting != null)
{
mView.putSetting(setting);
}

if (item.getKey().equals(SettingsFile.KEY_SKIP_EFB) ||
item.getKey().equals(SettingsFile.KEY_IGNORE_FORMAT))
{
mView.putSetting(new BooleanSetting(item.getKey(), item.getSection(), !checked));
}

mView.onSettingChanged(item.getKey());
}

@@ -201,7 +195,8 @@ public void onStringSingleChoiceClick(StringSingleChoiceSetting item, int positi
R.style.DolphinDialogBase);

builder.setTitle(item.getNameId());
builder.setSingleChoiceItems(item.getChoicesId(), item.getSelectValueIndex(), this);
builder.setSingleChoiceItems(item.getChoicesId(), item.getSelectValueIndex(getSettings()),
this);

mDialog = builder.show();
}
@@ -227,7 +222,7 @@ public void onSliderClick(SliderSetting item, int position)
{
mClickedItem = item;
mClickedPosition = position;
mSeekbarProgress = item.getSelectedValue();
mSeekbarProgress = item.getSelectedValue(getSettings());
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity(),
R.style.DolphinDialogBase);

@@ -261,22 +256,18 @@ public void onSubmenuClick(SubmenuSetting item)

public void onInputBindingClick(final InputBindingSetting item, final int position)
{
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item);
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item, this);
dialog.setTitle(R.string.input_binding);
dialog.setMessage(String.format(mContext.getString(
item instanceof RumbleBindingSetting ?
R.string.input_rumble_description : R.string.input_binding_description),
mContext.getString(item.getNameId())));
dialog.setButton(AlertDialog.BUTTON_NEGATIVE, mContext.getString(R.string.cancel), this);
dialog.setButton(AlertDialog.BUTTON_NEUTRAL, mContext.getString(R.string.clear),
(dialogInterface, i) -> item.clearValue());
(dialogInterface, i) -> item.clearValue(getSettings()));
dialog.setOnDismissListener(dialog1 ->
{
StringSetting setting = new StringSetting(item.getKey(), item.getSection(), item.getValue());
notifyItemChanged(position);

mView.putSetting(setting);

mView.onSettingChanged(item.getKey());
});
dialog.setCanceledOnTouchOutside(false);
@@ -315,53 +306,47 @@ public void onFilePickerFileClick(SettingsItem item)
extensions);
}

public void onFilePickerConfirmation(String file)
public void onFilePickerConfirmation(String selectedFile)
{
FilePicker filePicker = (FilePicker) mClickedItem;

NativeLibrary.SetConfig(filePicker.getFile(), filePicker.getSection(), filePicker.getKey(),
file);
File file = SettingsFile.getSettingsFile(filePicker.getFile());
IniFile ini = new IniFile(file);
ini.setString(filePicker.getSection(), filePicker.getKey(), selectedFile);
ini.save(file);

NativeLibrary.ReloadConfig();

mClickedItem = null;
}

public void resetPaths()
{
StringSetting defaultISO =
new StringSetting(SettingsFile.KEY_DEFAULT_ISO, Settings.SECTION_INI_CORE, "");
StringSetting NANDRootPath =
new StringSetting(SettingsFile.KEY_NAND_ROOT_PATH, Settings.SECTION_INI_GENERAL,
SettingsFragmentPresenter.getDefaultNANDRootPath());
StringSetting dumpPath =
new StringSetting(SettingsFile.KEY_DUMP_PATH, Settings.SECTION_INI_GENERAL,
SettingsFragmentPresenter.getDefaultDumpPath());
StringSetting loadPath =
new StringSetting(SettingsFile.KEY_LOAD_PATH, Settings.SECTION_INI_GENERAL,
SettingsFragmentPresenter.getDefaultLoadPath());
StringSetting resourcePackPath =
new StringSetting(SettingsFile.KEY_RESOURCE_PACK_PATH, Settings.SECTION_INI_GENERAL,
SettingsFragmentPresenter.getDefaultResourcePackPath());
StringSetting sdPath =
new StringSetting(SettingsFile.KEY_WII_SD_CARD_PATH, Settings.SECTION_INI_GENERAL,
SettingsFragmentPresenter.getDefaultSDPath());

mView.putSetting(defaultISO);
mView.putSetting(NANDRootPath);
mView.putSetting(dumpPath);
mView.putSetting(loadPath);
mView.putSetting(resourcePackPath);
mView.putSetting(sdPath);
IniFile.Section coreSection = mView.getSettings().getSection(SettingsFile.FILE_NAME_DOLPHIN,
Settings.SECTION_INI_CORE);
IniFile.Section generalSection = mView.getSettings().getSection(SettingsFile.FILE_NAME_DOLPHIN,
Settings.SECTION_INI_GENERAL);

coreSection.delete(SettingsFile.KEY_DEFAULT_ISO);
generalSection.delete(SettingsFile.KEY_NAND_ROOT_PATH);
generalSection.delete(SettingsFile.KEY_DUMP_PATH);
generalSection.delete(SettingsFile.KEY_LOAD_PATH);
generalSection.delete(SettingsFile.KEY_RESOURCE_PACK_PATH);
generalSection.delete(SettingsFile.KEY_WII_SD_CARD_PATH);

mView.onSettingChanged(null);
}

public void setAllLogTypes(String value)
public void setAllLogTypes(boolean value)
{
IniFile.Section section = mView.getSettings().getSection(SettingsFile.FILE_NAME_LOGGER,
Settings.SECTION_LOGGER_LOGS);

for (Map.Entry<String, String> entry : SettingsFragmentPresenter.LOG_TYPE_NAMES.entrySet())
{
mView.putSetting(new StringSetting(entry.getKey(), Settings.SECTION_LOGGER_LOGS, value));
section.setBoolean(entry.getKey(), value);
}

mView.onSettingChanged(null);
}

@@ -394,17 +379,12 @@ public void onClick(DialogInterface dialog, int which)
SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem;

int value = getValueForSingleChoiceSelection(scSetting, which);
if (scSetting.getSelectedValue() != value)
if (scSetting.getSelectedValue(getSettings()) != value)
mView.onSettingChanged(mClickedItem.getKey());

handleMenuTag(scSetting.getMenuTag(), value);

// Get the backing Setting, which may be null (if for example it was missing from the file)
IntSetting setting = scSetting.setSelectedValue(value);
if (setting != null)
{
mView.putSetting(setting);
}
scSetting.setSelectedValue(getSettings(), value);

closeDialog();
}
@@ -414,68 +394,43 @@ else if (mClickedItem instanceof SingleChoiceSettingDynamicDescriptions)
(SingleChoiceSettingDynamicDescriptions) mClickedItem;

int value = getValueForSingleChoiceDynamicDescriptionsSelection(scSetting, which);
if (scSetting.getSelectedValue() != value)
if (scSetting.getSelectedValue(getSettings()) != value)
mView.onSettingChanged(mClickedItem.getKey());

// Get the backing Setting, which may be null (if for example it was missing from the file)
IntSetting setting = scSetting.setSelectedValue(value);
if (setting != null)
{
mView.putSetting(setting);
}
scSetting.setSelectedValue(getSettings(), value);

closeDialog();
}
else if (mClickedItem instanceof StringSingleChoiceSetting)
{
StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
String value = scSetting.getValueAt(which);
if (!scSetting.getSelectedValue().equals(value))
if (!scSetting.getSelectedValue(getSettings()).equals(value))
mView.onSettingChanged(mClickedItem.getKey());

handleMenuTag(scSetting.getMenuTag(), which);

StringSetting setting = scSetting.setSelectedValue(value);
if (setting != null)
{
mView.putSetting(setting);
}
scSetting.setSelectedValue(getSettings(), value);

closeDialog();
}
else if (mClickedItem instanceof SliderSetting)
else if (mClickedItem instanceof IntSliderSetting)
{
SliderSetting sliderSetting = (SliderSetting) mClickedItem;
if (sliderSetting.getSelectedValue() != mSeekbarProgress)
IntSliderSetting sliderSetting = (IntSliderSetting) mClickedItem;
if (sliderSetting.getSelectedValue(getSettings()) != mSeekbarProgress)
mView.onSettingChanged(mClickedItem.getKey());

if (sliderSetting.isPercentSetting() || sliderSetting.getSetting() instanceof FloatSetting)
{
float value;
sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);

if (sliderSetting.isPercentSetting())
{
value = mSeekbarProgress / 100.0f;
}
else
{
value = (float) mSeekbarProgress;
}
closeDialog();
}
else if (mClickedItem instanceof FloatSliderSetting)
{
FloatSliderSetting sliderSetting = (FloatSliderSetting) mClickedItem;
if (sliderSetting.getSelectedValue(getSettings()) != mSeekbarProgress)
mView.onSettingChanged(mClickedItem.getKey());

FloatSetting setting = sliderSetting.setSelectedValue(value);
if (setting != null)
{
mView.putSetting(setting);
}
}
else
{
IntSetting setting = sliderSetting.setSelectedValue(mSeekbarProgress);
if (setting != null)
{
mView.putSetting(setting);
}
}
sliderSetting.setSelectedValue(getSettings(), mSeekbarProgress);

closeDialog();
}
@@ -532,7 +487,7 @@ private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which

private int getSelectionForSingleChoiceValue(SingleChoiceSetting item)
{
int value = item.getSelectedValue();
int value = item.getSelectedValue(getSettings());
int valuesId = item.getValuesId();

if (valuesId > 0)
@@ -574,7 +529,7 @@ private int getValueForSingleChoiceDynamicDescriptionsSelection(
private int getSelectionForSingleChoiceDynamicDescriptionsValue(
SingleChoiceSettingDynamicDescriptions item)
{
int value = item.getSelectedValue();
int value = item.getSelectedValue(getSettings());
int valuesId = item.getValuesId();

if (valuesId > 0)
@@ -14,7 +14,7 @@
import android.view.ViewGroup;

import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
import org.dolphinemu.dolphinemu.ui.DividerItemDecoration;

@@ -188,9 +188,9 @@ public void showToastMessage(String message)
}

@Override
public void putSetting(Setting setting)
public Settings getSettings()
{
mPresenter.putSetting(setting);
return mPresenter.getSettings();
}

@Override

Large diffs are not rendered by default.

@@ -2,7 +2,6 @@

import androidx.fragment.app.FragmentActivity;

import org.dolphinemu.dolphinemu.features.settings.model.Setting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;

@@ -23,9 +22,9 @@
void onSettingsFileLoaded(Settings settings);

/**
* Pass an ArrayList to the View so that it can be displayed on screen.
* Pass an ArrayList of settings to the View so that it can be displayed on screen.
*
* @param settingsList The result of converting the HashMap to an ArrayList
* @param settingsList The settings to display
*/
void showSettingsList(ArrayList<SettingsItem> settingsList);

@@ -61,11 +60,9 @@
void showToastMessage(String message);

/**
* Have the fragment add a setting to the HashMap.
*
* @param setting The (possibly previously missing) new setting.
* @return The backing settings store.
*/
void putSetting(Setting setting);
Settings getSettings();

/**
* Have the fragment tell the containing Activity that a setting was modified.
@@ -57,7 +57,7 @@ public void bind(SettingsItem item)
mTextSettingDescription.setText("");
}

mCheckbox.setChecked(mItem.isChecked());
mCheckbox.setChecked(mItem.isChecked(getAdapter().getSettings()));
}

@Override
@@ -3,12 +3,13 @@
import android.view.View;
import android.widget.TextView;

import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.view.FilePicker;
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.ui.main.MainPresenter;
import org.dolphinemu.dolphinemu.utils.IniFile;

public final class FilePickerViewHolder extends SettingViewHolder
{
@@ -44,9 +45,10 @@ public void bind(SettingsItem item)
}
else
{
mTextSettingDescription.setText(NativeLibrary
.GetConfig(mFilePicker.getFile(), item.getSection(), item.getKey(),
mFilePicker.getSelectedValue()));
// TODO: Reopening INI files all the time is slow
IniFile ini = new IniFile(SettingsFile.getSettingsFile(mFilePicker.getFile()));
mTextSettingDescription.setText(ini.getString(item.getSection(), item.getKey(),
mFilePicker.getSelectedValue(getAdapter().getSettings())));
}
}

@@ -44,7 +44,7 @@ public void bind(SettingsItem item)
else if (item instanceof SingleChoiceSetting)
{
SingleChoiceSetting setting = (SingleChoiceSetting) item;
int selected = setting.getSelectedValue();
int selected = setting.getSelectedValue(getAdapter().getSettings());
Resources resMgr = mTextSettingDescription.getContext().getResources();
String[] choices = resMgr.getStringArray(setting.getChoicesId());
int[] values = resMgr.getIntArray(setting.getValuesId());
@@ -60,15 +60,15 @@ else if (item instanceof StringSingleChoiceSetting)
{
StringSingleChoiceSetting setting = (StringSingleChoiceSetting) item;
String[] choices = setting.getChoicesId();
int valueIndex = setting.getSelectValueIndex();
int valueIndex = setting.getSelectValueIndex(getAdapter().getSettings());
if (valueIndex != -1)
mTextSettingDescription.setText(choices[valueIndex]);
}
else if (item instanceof SingleChoiceSettingDynamicDescriptions)
{
SingleChoiceSettingDynamicDescriptions setting =
(SingleChoiceSettingDynamicDescriptions) item;
int selected = setting.getSelectedValue();
int selected = setting.getSelectedValue(getAdapter().getSettings());
Resources resMgr = mTextSettingDescription.getContext().getResources();
String[] choices = resMgr.getStringArray(setting.getDescriptionChoicesId());
int[] values = resMgr.getIntArray(setting.getDescriptionValuesId());
@@ -46,8 +46,8 @@ public void bind(SettingsItem item)
else
{
mTextSettingDescription.setText(mContext
.getString(R.string.slider_setting_value, mItem.getSelectedValue(),
mItem.getUnits()));
.getString(R.string.slider_setting_value,
mItem.getSelectedValue(getAdapter().getSettings()), mItem.getUnits()));
}
}

Large diffs are not rendered by default.

@@ -15,7 +15,6 @@
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;

@@ -72,12 +71,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa
showUnpauseEmulationButton();
}

BooleanSetting enableSaveStates =
(BooleanSetting) ((EmulationActivity) getActivity()).getSettings()
.getSection(Settings.SECTION_INI_CORE)
.getSetting(SettingsFile.KEY_ENABLE_SAVE_STATES);
boolean enableSaveStates = ((EmulationActivity) getActivity()).getSettings()
.getSection(SettingsFile.FILE_NAME_DOLPHIN, Settings.SECTION_INI_CORE)
.getBoolean(SettingsFile.KEY_ENABLE_SAVE_STATES, false);

if (enableSaveStates != null && enableSaveStates.getValue())
if (enableSaveStates)
{
options.findViewById(R.id.menu_quicksave).setVisibility(View.VISIBLE);
options.findViewById(R.id.menu_quickload).setVisibility(View.VISIBLE);
@@ -7,6 +7,7 @@
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.utils.IniFile;

import java.io.File;
import java.util.HashSet;
@@ -82,9 +83,10 @@ private void removeNonExistentGameFolders(Context context)
*/
public boolean scanLibrary(Context context)
{
boolean recursiveScan = NativeLibrary
.GetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_GENERAL,
SettingsFile.KEY_RECURSIVE_ISO_PATHS, "False").equals("True");
IniFile dolphinIni =
new IniFile(SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_DOLPHIN));
boolean recursiveScan = dolphinIni.getBoolean(Settings.SECTION_INI_GENERAL,
SettingsFile.KEY_RECURSIVE_ISO_PATHS, false);

removeNonExistentGameFolders(context);

@@ -33,6 +33,7 @@
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.utils.IniFile;

import java.util.ArrayList;
import java.util.HashSet;
@@ -51,9 +52,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
public static final int OVERLAY_WIIMOTE_CLASSIC = 4;
public static final int OVERLAY_NONE = 5;

private static final String DISABLED_GAMECUBE_CONTROLLER = "0";
private static final String EMULATED_GAMECUBE_CONTROLLER = "6";
private static final String GAMECUBE_ADAPTER = "12";
private static final int DISABLED_GAMECUBE_CONTROLLER = 0;
private static final int EMULATED_GAMECUBE_CONTROLLER = 6;
private static final int GAMECUBE_ADAPTER = 12;

private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>();
private final Set<InputOverlayDrawableDpad> overlayDpads = new HashSet<>();
@@ -703,9 +704,11 @@ public void refreshControls()
// Add all the enabled overlay items back to the HashSet.
if (EmulationActivity.isGameCubeGame())
{
switch (NativeLibrary
.GetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_CORE,
SettingsFile.KEY_GCPAD_PLAYER_1, EMULATED_GAMECUBE_CONTROLLER))
IniFile dolphinIni =
new IniFile(SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_DOLPHIN));

switch (dolphinIni.getInt(Settings.SECTION_INI_CORE, SettingsFile.KEY_GCPAD_PLAYER_1,
EMULATED_GAMECUBE_CONTROLLER))
{
case DISABLED_GAMECUBE_CONTROLLER:
if (mIsFirstRun)
@@ -33,9 +33,12 @@
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
import org.dolphinemu.dolphinemu.utils.IniFile;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.StartupHandler;

import java.io.File;

/**
* The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which
* individually display a grid of available games for each Fragment, in a tabbed layout.
@@ -272,24 +275,19 @@ private void setPlatformTabsAndStartGameFileCacheService()
public void onTabSelected(@NonNull TabLayout.Tab tab)
{
super.onTabSelected(tab);
NativeLibrary
.SetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_ANDROID,
SettingsFile.KEY_LAST_PLATFORM_TAB, Integer.toString(tab.getPosition()));

File dolphinFile = SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_DOLPHIN);
IniFile dolphinIni = new IniFile(dolphinFile);
dolphinIni.setInt(Settings.SECTION_INI_ANDROID, SettingsFile.KEY_LAST_PLATFORM_TAB,
tab.getPosition());
dolphinIni.save(dolphinFile);
}
});

String platformTab = NativeLibrary
.GetConfig(SettingsFile.FILE_NAME_DOLPHIN + ".ini", Settings.SECTION_INI_ANDROID,
SettingsFile.KEY_LAST_PLATFORM_TAB, "0");

try
{
mViewPager.setCurrentItem(Integer.parseInt(platformTab));
}
catch (NumberFormatException ex)
{
mViewPager.setCurrentItem(0);
}
IniFile dolphinIni =
new IniFile(SettingsFile.getSettingsFile(SettingsFile.FILE_NAME_DOLPHIN));
mViewPager.setCurrentItem(dolphinIni.getInt(Settings.SECTION_INI_ANDROID,
SettingsFile.KEY_LAST_PLATFORM_TAB, 0));

showGames();
GameFileCacheService.startLoad(this);
@@ -0,0 +1,110 @@
package org.dolphinemu.dolphinemu.utils;

import java.io.File;

// An in-memory copy of an INI file
public class IniFile
{
// This class is non-static to ensure that the IniFile parent does not get garbage collected
// while a section still is accessible. (The finalizer of IniFile deletes the native sections.)
public class Section
{
private long mPointer; // Do not rename or move without editing the native code

private Section(long pointer)
{
mPointer = pointer;
}

public native boolean exists(String key);

public native boolean delete(String key);

public native String getString(String key, String defaultValue);

public native boolean getBoolean(String key, boolean defaultValue);

public native int getInt(String key, int defaultValue);

public native float getFloat(String key, float defaultValue);

public native void setString(String key, String newValue);

public native void setBoolean(String key, boolean newValue);

public native void setInt(String key, int newValue);

public native void setFloat(String key, float newFloat);
}

private long mPointer; // Do not rename or move without editing the native code

public IniFile()
{
mPointer = newIniFile();
}

public IniFile(IniFile other)
{
mPointer = copyIniFile(other);
}

public IniFile(String path)
{
this();
load(path, false);
}

public IniFile(File file)
{
this();
load(file, false);
}

public native boolean load(String path, boolean keepCurrentData);

public boolean load(File file, boolean keepCurrentData)
{
return load(file.getPath(), keepCurrentData);
}

public native boolean save(String path);

public boolean save(File file)
{
return save(file.getPath());
}

public native Section getOrCreateSection(String sectionName);

public native boolean exists(String sectionName);

public native boolean exists(String sectionName, String key);

public native boolean deleteSection(String sectionName);

public native boolean deleteKey(String sectionName, String key);

public native String getString(String sectionName, String key, String defaultValue);

public native boolean getBoolean(String sectionName, String key, boolean defaultValue);

public native int getInt(String sectionName, String key, int defaultValue);

public native float getFloat(String sectionName, String key, float defaultValue);

public native void setString(String sectionName, String key, String newValue);

public native void setBoolean(String sectionName, String key, boolean newValue);

public native void setInt(String sectionName, String key, int newValue);

public native void setFloat(String sectionName, String key, float newValue);

@Override
public native void finalize();

private native long newIniFile();

private native long copyIniFile(IniFile other);
}
@@ -10,7 +10,6 @@

import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;

public class Rumble
@@ -29,15 +28,16 @@ public static void initRumble(EmulationActivity activity)

for (int i = 0; i < 8; i++)
{
StringSetting deviceName =
(StringSetting) activity.getSettings().getSection(Settings.SECTION_BINDINGS)
.getSetting(SettingsFile.KEY_EMU_RUMBLE + i);
if (deviceName != null && !deviceName.getValue().isEmpty())
String deviceName = activity.getSettings()
.getSection(SettingsFile.FILE_NAME_DOLPHIN, Settings.SECTION_BINDINGS)
.getString(SettingsFile.KEY_EMU_RUMBLE + i, "");

if (!deviceName.isEmpty())
{
for (int id : InputDevice.getDeviceIds())
{
InputDevice device = InputDevice.getDevice(id);
if (deviceName.getValue().equals(device.getDescriptor()))
if (deviceName.equals(device.getDescriptor()))
{
Vibrator vib = device.getVibrator();
if (vib != null && vib.hasVibrator())
@@ -30,6 +30,12 @@ static jclass s_linked_hash_map_class;
static jmethodID s_linked_hash_map_init;
static jmethodID s_linked_hash_map_put;

static jclass s_ini_file_class;
static jfieldID s_ini_file_pointer;
static jclass s_ini_file_section_class;
static jfieldID s_ini_file_section_pointer;
static jmethodID s_ini_file_section_constructor;

namespace IDCache
{
JNIEnv* GetEnvForThread()
@@ -89,6 +95,7 @@ jmethodID GetAnalyticsValue()
{
return s_get_analytics_value;
}

jclass GetGameFileClass()
{
return s_game_file_class;
@@ -129,6 +136,31 @@ jmethodID GetLinkedHashMapPut()
return s_linked_hash_map_put;
}

jclass GetIniFileClass()
{
return s_ini_file_class;
}

jfieldID GetIniFilePointer()
{
return s_ini_file_pointer;
}

jclass GetIniFileSectionClass()
{
return s_ini_file_section_class;
}

jfieldID GetIniFileSectionPointer()
{
return s_ini_file_section_pointer;
}

jmethodID GetIniFileSectionConstructor()
{
return s_ini_file_section_constructor;
}

} // namespace IDCache

#ifdef __cplusplus
@@ -150,23 +182,40 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_do_rumble = env->GetStaticMethodID(s_native_library_class, "rumble", "(ID)V");
s_get_update_touch_pointer =
env->GetStaticMethodID(s_native_library_class, "updateTouchPointer", "()V");
env->DeleteLocalRef(native_library_class);

const jclass game_file_class = env->FindClass("org/dolphinemu/dolphinemu/model/GameFile");
s_game_file_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_class));
s_game_file_pointer = env->GetFieldID(game_file_class, "mPointer", "J");
s_game_file_constructor = env->GetMethodID(game_file_class, "<init>", "(J)V");
env->DeleteLocalRef(game_file_class);

const jclass game_file_cache_class =
env->FindClass("org/dolphinemu/dolphinemu/model/GameFileCache");
s_game_file_cache_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_cache_class));
s_game_file_cache_pointer = env->GetFieldID(game_file_cache_class, "mPointer", "J");
env->DeleteLocalRef(game_file_cache_class);

const jclass analytics_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Analytics");
s_analytics_class = reinterpret_cast<jclass>(env->NewGlobalRef(analytics_class));
s_send_analytics_report =
env->GetStaticMethodID(s_analytics_class, "sendReport", "(Ljava/lang/String;[B)V");
s_get_analytics_value = env->GetStaticMethodID(s_analytics_class, "getValue",
"(Ljava/lang/String;)Ljava/lang/String;");
env->DeleteLocalRef(analytics_class);

const jclass ini_file_class = env->FindClass("org/dolphinemu/dolphinemu/utils/IniFile");
s_ini_file_class = reinterpret_cast<jclass>(env->NewGlobalRef(ini_file_class));
s_ini_file_pointer = env->GetFieldID(ini_file_class, "mPointer", "J");
env->DeleteLocalRef(ini_file_class);

const jclass ini_file_section_class =
env->FindClass("org/dolphinemu/dolphinemu/utils/IniFile$Section");
s_ini_file_section_class = reinterpret_cast<jclass>(env->NewGlobalRef(ini_file_section_class));
s_ini_file_section_pointer = env->GetFieldID(ini_file_section_class, "mPointer", "J");
s_ini_file_section_constructor = env->GetMethodID(
ini_file_section_class, "<init>", "(Lorg/dolphinemu/dolphinemu/utils/IniFile;J)V");
env->DeleteLocalRef(ini_file_section_class);

const jclass map_class = env->FindClass("java/util/LinkedHashMap");
s_linked_hash_map_class = reinterpret_cast<jclass>(env->NewGlobalRef(map_class));
@@ -188,6 +237,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved)
env->DeleteGlobalRef(s_game_file_cache_class);
env->DeleteGlobalRef(s_analytics_class);
env->DeleteGlobalRef(s_linked_hash_map_class);
env->DeleteGlobalRef(s_ini_file_class);
env->DeleteGlobalRef(s_ini_file_section_class);
}

#ifdef __cplusplus
@@ -32,4 +32,10 @@ jclass GetLinkedHashMapClass();
jmethodID GetLinkedHashMapInit();
jmethodID GetLinkedHashMapPut();

jclass GetIniFileClass();
jfieldID GetIniFilePointer();
jclass GetIniFileSectionClass();
jfieldID GetIniFileSectionPointer();
jmethodID GetIniFileSectionConstructor();

} // namespace IDCache
@@ -3,6 +3,7 @@ add_library(main SHARED
AndroidCommon/IDCache.cpp
GameList/GameFile.cpp
GameList/GameFileCache.cpp
IniFile.cpp
MainAndroid.cpp
)

@@ -0,0 +1,249 @@
// Copyright 2020 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include <jni.h>

#include "Common/IniFile.h"
#include "jni/AndroidCommon/AndroidCommon.h"
#include "jni/AndroidCommon/IDCache.h"

static IniFile::Section* GetSectionPointer(JNIEnv* env, jobject obj)
{
return reinterpret_cast<IniFile::Section*>(
env->GetLongField(obj, IDCache::GetIniFileSectionPointer()));
}

static IniFile* GetIniFilePointer(JNIEnv* env, jobject obj)
{
return reinterpret_cast<IniFile*>(env->GetLongField(obj, IDCache::GetIniFilePointer()));
}

static jobject SectionToJava(JNIEnv* env, jobject ini_file, IniFile::Section* section)
{
if (!section)
return nullptr;

return env->NewObject(IDCache::GetIniFileSectionClass(), IDCache::GetIniFileSectionConstructor(),
ini_file, reinterpret_cast<jlong>(section));
}

template <typename T>
static T GetInSection(JNIEnv* env, jobject obj, jstring key, T default_value)
{
T result;
GetSectionPointer(env, obj)->Get(GetJString(env, key), &result, default_value);
return result;
}

template <typename T>
static void SetInSection(JNIEnv* env, jobject obj, jstring key, T new_value)
{
GetSectionPointer(env, obj)->Set(GetJString(env, key), new_value);
}

template <typename T>
static T Get(JNIEnv* env, jobject obj, jstring section_name, jstring key, T default_value)
{
T result;
GetIniFilePointer(env, obj)
->GetOrCreateSection(GetJString(env, section_name))
->Get(GetJString(env, key), &result, default_value);
return result;
}

template <typename T>
static void Set(JNIEnv* env, jobject obj, jstring section_name, jstring key, T new_value)
{
GetIniFilePointer(env, obj)
->GetOrCreateSection(GetJString(env, section_name))
->Set(GetJString(env, key), new_value);
}

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_exists(
JNIEnv* env, jobject obj, jstring key)
{
return static_cast<jboolean>(GetSectionPointer(env, obj)->Exists(GetJString(env, key)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_delete(
JNIEnv* env, jobject obj, jstring key)
{
return static_cast<jboolean>(GetSectionPointer(env, obj)->Delete(GetJString(env, key)));
}

JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_getString(
JNIEnv* env, jobject obj, jstring key, jstring default_value)
{
return ToJString(env, GetInSection(env, obj, key, GetJString(env, default_value)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_getBoolean(
JNIEnv* env, jobject obj, jstring key, jboolean default_value)
{
return static_cast<jboolean>(GetInSection(env, obj, key, static_cast<bool>(default_value)));
}

JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_getInt(
JNIEnv* env, jobject obj, jstring key, jint default_value)
{
return GetInSection(env, obj, key, default_value);
}

JNIEXPORT jfloat JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_getFloat(
JNIEnv* env, jobject obj, jstring key, jfloat default_value)
{
return GetInSection(env, obj, key, default_value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_setString(
JNIEnv* env, jobject obj, jstring key, jstring new_value)
{
SetInSection(env, obj, key, GetJString(env, new_value));
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_setBoolean(
JNIEnv* env, jobject obj, jstring key, jboolean new_value)
{
SetInSection(env, obj, key, static_cast<bool>(new_value));
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_setInt(
JNIEnv* env, jobject obj, jstring key, jint new_value)
{
SetInSection(env, obj, key, new_value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_00024Section_setFloat(
JNIEnv* env, jobject obj, jstring key, jfloat new_value)
{
SetInSection(env, obj, key, new_value);
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_load(
JNIEnv* env, jobject obj, jstring path, jboolean keep_current_data)
{
return static_cast<jboolean>(
GetIniFilePointer(env, obj)->Load(GetJString(env, path), keep_current_data));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_save(JNIEnv* env,
jobject obj,
jstring path)
{
return static_cast<jboolean>(GetIniFilePointer(env, obj)->Save(GetJString(env, path)));
}

JNIEXPORT jobject JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_getOrCreateSection(
JNIEnv* env, jobject obj, jstring section_name)
{
return SectionToJava(
env, obj, GetIniFilePointer(env, obj)->GetOrCreateSection(GetJString(env, section_name)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_exists__Ljava_lang_String_2(
JNIEnv* env, jobject obj, jstring section_name)
{
return static_cast<jboolean>(GetIniFilePointer(env, obj)->Exists(GetJString(env, section_name)));
}

JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_utils_IniFile_exists__Ljava_lang_String_2Ljava_lang_String_2(
JNIEnv* env, jobject obj, jstring section_name, jstring key)
{
return static_cast<jboolean>(
GetIniFilePointer(env, obj)->Exists(GetJString(env, section_name), GetJString(env, key)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_deleteSection(
JNIEnv* env, jobject obj, jstring section_name)
{
return static_cast<jboolean>(
GetIniFilePointer(env, obj)->DeleteSection(GetJString(env, section_name)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_deleteKey(
JNIEnv* env, jobject obj, jstring section_name, jstring key)
{
return static_cast<jboolean>(
GetIniFilePointer(env, obj)->DeleteKey(GetJString(env, section_name), GetJString(env, key)));
}

JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_getString(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jstring default_value)
{
return ToJString(env, Get(env, obj, section_name, key, GetJString(env, default_value)));
}

JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_getBoolean(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jboolean default_value)
{
return static_cast<jboolean>(Get(env, obj, section_name, key, static_cast<bool>(default_value)));
}

JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_getInt(JNIEnv* env, jobject obj,
jstring section_name,
jstring key,
jint default_value)
{
return Get(env, obj, section_name, key, default_value);
}

JNIEXPORT jfloat JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_getFloat(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jfloat default_value)
{
return Get(env, obj, section_name, key, default_value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_setString(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jstring new_value)
{
Set(env, obj, section_name, key, GetJString(env, new_value));
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_setBoolean(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jboolean new_value)
{
Set(env, obj, section_name, key, static_cast<bool>(new_value));
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_setInt(JNIEnv* env, jobject obj,
jstring section_name,
jstring key,
jint new_value)
{
Set(env, obj, section_name, key, new_value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_setFloat(
JNIEnv* env, jobject obj, jstring section_name, jstring key, jfloat new_value)
{
Set(env, obj, section_name, key, new_value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_finalize(JNIEnv* env,
jobject obj)
{
delete GetIniFilePointer(env, obj);
}

JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_newIniFile(JNIEnv* env,
jobject obj)
{
return reinterpret_cast<jlong>(new IniFile);
}

JNIEXPORT jlong JNICALL Java_org_dolphinemu_dolphinemu_utils_IniFile_copyIniFile(JNIEnv* env,
jobject obj,
jobject other)
{
return reinterpret_cast<jlong>(new IniFile(*GetIniFilePointer(env, other)));
}

#ifdef __cplusplus
}
#endif
@@ -213,10 +213,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenSh
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_eglBindAPI(JNIEnv* env,
jobject obj,
jint api);
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(
JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetConfig(
JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jValue);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetFilename(JNIEnv* env,
jobject obj,
jstring jFile);
@@ -355,129 +351,6 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_eglBindAPI(J
eglBindAPI(api);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_InitGameIni(JNIEnv* env,
jobject obj,
jstring jGameID)
{
// Initialize an empty INI file
IniFile ini;
std::string gameid = GetJString(env, jGameID);

__android_log_print(ANDROID_LOG_DEBUG, "InitGameIni", "Initializing base game config file");
ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
}

JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserSetting(
JNIEnv* env, jobject obj, jstring jGameID, jstring jSection, jstring jKey)
{
IniFile ini;
std::string gameid = GetJString(env, jGameID);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);

ini = SConfig::LoadGameIni(gameid, 0);
std::string value;

ini.GetOrCreateSection(section)->Get(key, &value, "-1");

return ToJString(env, value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_NewGameIniFile(JNIEnv* env,
jobject obj)
{
s_ini = IniFile();
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadGameIniFile(JNIEnv* env,
jobject obj,
jstring jGameID)
{
std::string gameid = GetJString(env, jGameID);
s_ini.Load(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveGameIniFile(JNIEnv* env,
jobject obj,
jstring jGameID)
{
std::string gameid = GetJString(env, jGameID);
s_ini.Save(File::GetUserPath(D_GAMESETTINGS_IDX) + gameid + ".ini");
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserSetting(
JNIEnv* env, jobject obj, jstring jGameID, jstring jSection, jstring jKey, jstring jValue)
{
std::string gameid = GetJString(env, jGameID);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
std::string val = GetJString(env, jValue);

if (val != "-1")
{
s_ini.GetOrCreateSection(section)->Set(key, val);
}
else
{
s_ini.GetOrCreateSection(section)->Delete(key);
}
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfileSetting(
JNIEnv* env, jobject obj, jstring jProfile, jstring jSection, jstring jKey, jstring jValue)
{
IniFile ini;
std::string profile = GetJString(env, jProfile);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
std::string val = GetJString(env, jValue);

ini.Load(File::GetUserPath(D_CONFIG_IDX) + "Profiles/Wiimote/" + profile + ".ini");

if (val != "-1")
{
ini.GetOrCreateSection(section)->Set(key, val);
}
else
{
ini.GetOrCreateSection(section)->Delete(key);
}

ini.Save(File::GetUserPath(D_CONFIG_IDX) + "Profiles/Wiimote/" + profile + ".ini");
}

JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(
JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault)
{
IniFile ini;
std::string file = GetJString(env, jFile);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
std::string defaultValue = GetJString(env, jDefault);

ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
std::string value;

ini.GetOrCreateSection(section)->Get(key, &value, defaultValue);

return ToJString(env, value);
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetConfig(
JNIEnv* env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jValue)
{
IniFile ini;
std::string file = GetJString(env, jFile);
std::string section = GetJString(env, jSection);
std::string key = GetJString(env, jKey);
std::string value = GetJString(env, jValue);

ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string(file));

ini.GetOrCreateSection(section)->Set(key, value);
ini.Save(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
}

JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JNIEnv* env,
jobject obj,
jint slot,