Merge pull request #329 from lioncash/master

[Android] Decouple a large amount of preference handling functionality from the MainMenuActivity in the Android front-end. Along with numerous simplifications/optimizations.
This commit is contained in:
Squarepusher 2013-10-09 07:18:03 -07:00
commit 2ee352c795
25 changed files with 853 additions and 699 deletions

View File

@ -2,11 +2,11 @@
package="org.retroarch"
android:versionCode="25"
android:versionName="0.9.9.7" >
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="17" />
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
@ -15,34 +15,34 @@
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:hasCode="true">
<activity android:name=".browser.CoreSelection"></activity>
<activity android:name=".browser.HistorySelection"></activity>
<activity android:name=".browser.DisplayRefreshRateTest"></activity>
<activity android:name=".browser.RefreshRateSetOS"></activity>
<activity android:name=".browser.CoreSelection"/>
<activity android:name=".browser.HistorySelection"/>
<activity android:name=".browser.DisplayRefreshRateTest"/>
<activity android:name=".browser.RefreshRateSetOS"/>
<activity android:name=".browser.MainMenuActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".browser.ReportIME"></activity>
<activity android:name=".browser.IMEActivity"></activity>
<activity android:name=".browser.HelpActivity"></activity>
<activity android:name=".browser.FileWrapper"></activity>
<activity android:name=".browser.DirectoryActivity"></activity>
<activity android:name=".browser.ROMActivity"></activity>
<activity android:name=".browser.RetroTVMode"></activity>
<activity android:name=".browser.ShaderActivity"></activity>
<activity android:name=".browser.OverlayActivity"></activity>
<activity android:name=".browser.ROMDirActivity"></activity>
<activity android:name=".browser.SRMDirActivity"></activity>
<activity android:name=".browser.StateDirActivity"></activity>
<activity android:name=".browser.SystemDirActivity"></activity>
<activity android:name=".browser.ReportIME"/>
<activity android:name=".browser.IMEActivity"/>
<activity android:name=".browser.HelpActivity"/>
<activity android:name=".browser.FileWrapper"/>
<activity android:name=".browser.RetroTVMode"/>
<activity android:name=".browser.diractivities.DirectoryActivity"/>
<activity android:name=".browser.diractivities.ROMActivity"/>
<activity android:name=".browser.diractivities.ROMDirActivity"/>
<activity android:name=".browser.diractivities.ShaderActivity"/>
<activity android:name=".browser.diractivities.OverlayActivity"/>
<activity android:name=".browser.diractivities.SRMDirActivity"/>
<activity android:name=".browser.diractivities.StateDirActivity"/>
<activity android:name=".browser.diractivities.SystemDirActivity"/>
<activity android:name=".browser.RetroActivity" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
<meta-data android:name="android.app.lib_name" android:value="retroarch-activity" />
<meta-data android:name="android.app.func_name" android:value="ANativeActivity_onCreate" />
<meta-data android:name="android.app.lib_name" android:value="retroarch-activity" />
<meta-data android:name="android.app.func_name" android:value="ANativeActivity_onCreate" />
</activity>
</application>
</manifest>

View File

@ -14,7 +14,7 @@
</PreferenceScreen>
<PreferenceScreen android:title="@string/load_game">
<intent
android:targetClass="org.retroarch.browser.ROMActivity"
android:targetClass="org.retroarch.browser.diractivities.ROMActivity"
android:targetPackage="org.retroarch" />
</PreferenceScreen>
<PreferenceScreen android:title="@string/load_game_history">
@ -91,7 +91,7 @@
android:title="@string/glsl_shader"
android:dependency="video_shader_enable" >
<intent
android:targetClass="org.retroarch.browser.ShaderActivity"
android:targetClass="org.retroarch.browser.diractivities.ShaderActivity"
android:targetPackage="org.retroarch" />
</Preference>
</PreferenceCategory>
@ -206,10 +206,10 @@
android:title="@string/input_overlay"
android:dependency="input_overlay_enable" >
<intent
android:targetClass="org.retroarch.browser.OverlayActivity"
android:targetClass="org.retroarch.browser.diractivities.OverlayActivity"
android:targetPackage="org.retroarch" />
</Preference>
<org.retroarch.browser.SeekbarPreference
<org.retroarch.browser.preferences.SeekbarPreference
android:summary="@string/overlay_opacity_desc"
android:title="@string/overlay_opacity"
android:key="input_overlay_opacity"
@ -219,208 +219,208 @@
<PreferenceScreen
android:title="@string/player_1_custom_binds"
android:dependency="input_autodetect_enable" >
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_up_btn"
android:title="@string/up_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_down_btn"
android:title="@string/down_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_left_btn"
android:title="@string/left_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_right_btn"
android:title="@string/right_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_a_btn"
android:title="@string/a_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_b_btn"
android:title="@string/b_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_x_btn"
android:title="@string/x_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_y_btn"
android:title="@string/y_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_start_btn"
android:title="@string/start_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_select_btn"
android:title="@string/select_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_l_btn"
android:title="@string/l1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_r_btn"
android:title="@string/r1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_l2_btn"
android:title="@string/l2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_r2_btn"
android:title="@string/r2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_l3_btn"
android:title="@string/l3_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player1_r3_btn"
android:title="@string/r3_button" />
</PreferenceScreen>
<PreferenceScreen
android:title="@string/player_2_custom_binds"
android:dependency="input_autodetect_enable" >
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_up_btn"
android:title="@string/up_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_down_btn"
android:title="@string/down_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_left_btn"
android:title="@string/left_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_right_btn"
android:title="@string/right_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_a_btn"
android:title="@string/a_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_b_btn"
android:title="@string/b_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_x_btn"
android:title="@string/x_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_y_btn"
android:title="@string/y_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_start_btn"
android:title="@string/start_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_select_btn"
android:title="@string/select_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_l_btn"
android:title="@string/l1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_r_btn"
android:title="@string/r1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_l2_btn"
android:title="@string/l2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_r2_btn"
android:title="@string/r2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_l3_btn"
android:title="@string/l3_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player2_r3_btn"
android:title="@string/r3_button" />
</PreferenceScreen>
<PreferenceScreen
android:title="@string/player_3_custom_binds"
android:dependency="input_autodetect_enable" >
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_up_btn"
android:title="@string/up_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_down_btn"
android:title="@string/down_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_left_btn"
android:title="@string/left_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_right_btn"
android:title="@string/right_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_a_btn"
android:title="@string/a_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_b_btn"
android:title="@string/b_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_x_btn"
android:title="@string/x_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_y_btn"
android:title="@string/y_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_start_btn"
android:title="@string/start_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_select_btn"
android:title="@string/select_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_l_btn"
android:title="@string/l1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_r_btn"
android:title="@string/r1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_l2_btn"
android:title="@string/l2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_r2_btn"
android:title="@string/r2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_l3_btn"
android:title="@string/l3_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player3_r3_btn"
android:title="@string/r3_button" />
</PreferenceScreen>
<PreferenceScreen
android:title="@string/player_4_custom_binds"
android:dependency="input_autodetect_enable" >
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_up_btn"
android:title="@string/up_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_down_btn"
android:title="@string/down_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_left_btn"
android:title="@string/left_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_right_btn"
android:title="@string/right_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_a_btn"
android:title="@string/a_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_b_btn"
android:title="@string/b_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_x_btn"
android:title="@string/x_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_y_btn"
android:title="@string/y_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_start_btn"
android:title="@string/start_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_select_btn"
android:title="@string/select_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_l_btn"
android:title="@string/l1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_r_btn"
android:title="@string/r1_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_l2_btn"
android:title="@string/l2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_r2_btn"
android:title="@string/r2_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_l3_btn"
android:title="@string/l3_button" />
<org.retroarch.browser.KeyBindPreference
<org.retroarch.browser.preferences.KeyBindPreference
android:key="input_player4_r3_btn"
android:title="@string/r3_button" />
</PreferenceScreen>
@ -439,7 +439,7 @@
<Preference android:title="@string/rom_directory"
android:summary="@string/rom_directory_desc">
<intent
android:targetClass="org.retroarch.browser.ROMDirActivity"
android:targetClass="org.retroarch.browser.diractivities.ROMDirActivity"
android:targetPackage="org.retroarch" />
</Preference>
</PreferenceCategory>
@ -453,9 +453,9 @@
android:summary="@string/savefile_directory_desc"
android:dependency="savefile_directory_enable">
<intent
android:targetClass="org.retroarch.browser.SRMDirActivity"
android:targetClass="org.retroarch.browser.diractivities.SRMDirActivity"
android:targetPackage="org.retroarch" />
</Preference>
</Preference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/save_states">
<CheckBoxPreference android:title="@string/enable_custom_dir"
@ -466,7 +466,7 @@
android:summary="@string/save_state_directory_desc"
android:dependency="savestate_directory_enable">
<intent
android:targetClass="org.retroarch.browser.StateDirActivity"
android:targetClass="org.retroarch.browser.diractivities.StateDirActivity"
android:targetPackage="org.retroarch" />
</Preference>
</PreferenceCategory>
@ -479,7 +479,7 @@
android:summary="@string/system_directory_desc"
android:dependency="system_directory_enable">
<intent
android:targetClass="org.retroarch.browser.SystemDirActivity"
android:targetClass="org.retroarch.browser.diractivities.SystemDirActivity"
android:targetPackage="org.retroarch" />
</Preference>
</PreferenceCategory>

View File

@ -1,6 +1,8 @@
package org.retroarch.browser;
import org.retroarch.R;
import org.retroarch.browser.preferences.ConfigFile;
import org.retroarch.browser.preferences.UserPreferences;
import java.io.*;
@ -13,25 +15,23 @@ import android.view.*;
// JELLY_BEAN_MR1 = 17
public final class CoreSelection extends Activity implements
AdapterView.OnItemClickListener {
public final class CoreSelection extends Activity implements AdapterView.OnItemClickListener {
private IconAdapter<ModuleWrapper> adapter;
static private final String TAG = "CoreSelection";
private static final String TAG = "CoreSelection";
@Override
public void onCreate(Bundle savedInstanceState) {
ConfigFile core_config;
super.onCreate(savedInstanceState);
core_config = new ConfigFile();
ConfigFile core_config = new ConfigFile();
try {
core_config.append(getAssets().open("libretro_cores.cfg"));
} catch (IOException e) {
Log.e(TAG, "Failed to load libretro_cores.cfg from assets.");
}
String cpuInfo = MainMenuActivity.readCPUInfo();
boolean cpuIsNeon = cpuInfo.contains("neon");
final String cpuInfo = UserPreferences.readCPUInfo();
final boolean cpuIsNeon = cpuInfo.contains("neon");
setContentView(R.layout.line_list);
@ -44,8 +44,7 @@ public final class CoreSelection extends Activity implements
setTitle(R.string.select_libretro_core);
// Populate the list
final String modulePath = MainMenuActivity.getInstance()
.getApplicationInfo().nativeLibraryDir;
final String modulePath = getApplicationInfo().nativeLibraryDir;
final File[] libs = new File(modulePath).listFiles();
for (final File lib : libs) {
String libName = lib.getName();
@ -87,11 +86,10 @@ public final class CoreSelection extends Activity implements
}
@Override
public void onItemClick(AdapterView<?> aListView, View aView,
int aPosition, long aID) {
final ModuleWrapper item = adapter.getItem(aPosition);
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
final ModuleWrapper item = adapter.getItem(position);
MainMenuActivity.getInstance().setModule(item.file.getAbsolutePath(), item.getText());
MainMenuActivity.getInstance().updateConfigFile();
UserPreferences.updateConfigFile(this);
finish();
}
}

View File

@ -4,6 +4,7 @@ import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import org.retroarch.R;
import org.retroarch.browser.preferences.UserPreferences;
import android.app.Activity;
import android.content.SharedPreferences;
@ -37,9 +38,9 @@ public final class DisplayRefreshRateTest extends Activity {
}
private void setFPSSetting(double fps) {
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(DisplayRefreshRateTest.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.valueOf(fps).toString());
edit.putString("video_refresh_rate", Double.toString(fps));
edit.commit();
}
@ -118,7 +119,7 @@ public final class DisplayRefreshRateTest extends Activity {
@Override
protected void onDestroy() {
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(this);
String fps = prefs.getString("video_refresh_rate", "ERROR");
Toast.makeText(this, String.format(getString(R.string.refresh_rate_measured_to), fps), Toast.LENGTH_LONG).show();
super.onDestroy();

View File

@ -6,7 +6,7 @@ import org.retroarch.R;
import android.graphics.drawable.Drawable;
final class FileWrapper implements IconAdapterItem {
public final class FileWrapper implements IconAdapterItem {
public final File file;
public final boolean parentItem;
public final boolean dirSelectItem;
@ -19,14 +19,14 @@ final class FileWrapper implements IconAdapterItem {
protected final int typeIndex;
public FileWrapper(File aFile, int type, boolean aIsEnabled) {
file = aFile;
parentItem = type == PARENT;
dirSelectItem = type == DIRSELECT;
typeIndex = type == FILE ? (FILE + (file.isDirectory() ? 0 : 1)) : type;
enabled = parentItem || dirSelectItem || aIsEnabled;
public FileWrapper(File file, int type, boolean isEnabled) {
this.file = file;
this.parentItem = type == PARENT;
this.dirSelectItem = type == DIRSELECT;
this.typeIndex = type == FILE ? (FILE + (file.isDirectory() ? 0 : 1)) : type;
this.enabled = parentItem || dirSelectItem || isEnabled;
}
@Override
@ -63,13 +63,13 @@ final class FileWrapper implements IconAdapterItem {
return null;
}
public int compareTo(FileWrapper aOther) {
if (aOther != null) {
public int compareTo(FileWrapper other) {
if (other != null) {
// Who says ternary is hard to follow
if (isEnabled() == aOther.isEnabled()) {
return (typeIndex == aOther.typeIndex) ? file
.compareTo(aOther.file)
: ((typeIndex < aOther.typeIndex) ? -1 : 1);
if (isEnabled() == other.isEnabled()) {
return (typeIndex == other.typeIndex) ? file
.compareTo(other.file)
: ((typeIndex < other.typeIndex) ? -1 : 1);
} else {
return isEnabled() ? -1 : 1;
}

View File

@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import org.retroarch.R;
import org.retroarch.browser.preferences.UserPreferences;
import android.app.Activity;
import android.content.Intent;
@ -17,8 +18,7 @@ import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
public final class HistorySelection extends Activity implements
AdapterView.OnItemClickListener {
public final class HistorySelection extends Activity implements AdapterView.OnItemClickListener {
private IconAdapter<HistoryWrapper> adapter;
@ -57,25 +57,23 @@ public final class HistorySelection extends Activity implements
}
@Override
public void onItemClick(AdapterView<?> aListView, View aView,
int aPosition, long aID) {
final HistoryWrapper item = adapter.getItem(aPosition);
public void onItemClick(AdapterView<?> listView, View view, int position, long id) {
final HistoryWrapper item = adapter.getItem(position);
final String gamePath = item.getGamePath();
final String corePath = item.getCorePath();
MainMenuActivity.getInstance().setModule(corePath, item.getCoreName());
Intent myIntent;
String current_ime = Settings.Secure.getString(getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD);
MainMenuActivity.getInstance().updateConfigFile();
UserPreferences.updateConfigFile(this);
Toast.makeText(this, String.format(getString(R.string.loading_gamepath), gamePath), Toast.LENGTH_SHORT).show();
myIntent = new Intent(this, RetroActivity.class);
Intent myIntent = new Intent(this, RetroActivity.class);
myIntent.putExtra("ROM", gamePath);
myIntent.putExtra("LIBRETRO", corePath);
myIntent.putExtra("CONFIGFILE", MainMenuActivity.getDefaultConfigPath());
myIntent.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(this));
myIntent.putExtra("IME", current_ime);
startActivity(myIntent);
finish();

View File

@ -2,48 +2,48 @@ package org.retroarch.browser;
import org.retroarch.R;
import android.app.*;
import android.content.*;
import android.graphics.drawable.*;
import android.view.*;
import android.widget.*;
interface IconAdapterItem {
public abstract boolean isEnabled();
public abstract String getText();
public abstract String getSubText();
public abstract int getIconResourceId();
public abstract Drawable getIconDrawable();
public boolean isEnabled();
public String getText();
public String getSubText();
public int getIconResourceId();
public Drawable getIconDrawable();
}
final class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
private final int layout;
public final class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
private final int resourceId;
private final Context context;
public IconAdapter(Activity aContext, int aLayout) {
super(aContext, aLayout);
layout = aLayout;
public IconAdapter(Context context, int resourceId) {
super(context, resourceId);
this.context = context;
this.resourceId = resourceId;
}
@Override
public View getView(int aPosition, View aConvertView, ViewGroup aParent) {
public View getView(int position, View convertView, ViewGroup parent) {
// Build the view
if (aConvertView == null) {
LayoutInflater inflater = (LayoutInflater) aParent.getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
aConvertView = inflater.inflate(layout, aParent, false);
if (convertView == null) {
LayoutInflater inflater = LayoutInflater.from(context);
convertView = inflater.inflate(resourceId, parent, false);
}
// Fill the view
IconAdapterItem item = getItem(aPosition);
IconAdapterItem item = getItem(position);
final boolean enabled = item.isEnabled();
TextView textView = (TextView) aConvertView.findViewById(R.id.name);
TextView textView = (TextView) convertView.findViewById(R.id.name);
if (null != textView) {
textView.setText(item.getText());
textView.setEnabled(enabled);
}
textView = (TextView) aConvertView.findViewById(R.id.sub_name);
textView = (TextView) convertView.findViewById(R.id.sub_name);
if (null != textView) {
String subText = item.getSubText();
if (null != subText) {
@ -53,7 +53,7 @@ final class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
}
}
ImageView imageView = (ImageView) aConvertView.findViewById(R.id.icon);
ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
if (null != imageView) {
if (enabled) {
final int id = item.getIconResourceId();
@ -67,12 +67,11 @@ final class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
}
}
return aConvertView;
return convertView;
}
@Override
public boolean isEnabled(int aPosition) {
return getItem(aPosition).isEnabled();
}
}

View File

@ -3,19 +3,17 @@ package org.retroarch.browser;
import java.io.*;
import org.retroarch.R;
import org.retroarch.browser.preferences.UserPreferences;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.CheckBoxPreference;
@ -24,73 +22,62 @@ import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
public final class MainMenuActivity extends PreferenceActivity {
private static MainMenuActivity instance = null;
static private final int ACTIVITY_LOAD_ROM = 0;
static private final String TAG = "MainMenu";
static private String libretro_path;
static private String libretro_name;
private boolean globalConfigEnable = true;
private static final int ACTIVITY_LOAD_ROM = 0;
private static final String TAG = "MainMenu";
private static String libretro_path;
private static String libretro_name;
@SuppressWarnings("deprecation")
private void refreshPreferenceScreen() {
readbackConfigFile();
UserPreferences.readbackConfigFile(this);
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.prefs);
setCoreTitle(libretro_name);
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
final CheckBoxPreference param = (CheckBoxPreference) findPreference("global_config_enable");
globalConfigEnable = param.isChecked();
param.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
updateConfigFile();
globalConfigEnable = param.isChecked();
SharedPreferences prefs = MainMenuActivity.getPreferences();
UserPreferences.updateConfigFile(MainMenuActivity.this);
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("global_config_enable", param.isChecked());
edit.commit();
refreshPreferenceScreen();
return true;
}
});
}
private boolean usePerCoreConfig() {
boolean config_same_as_native_lib_dir = libretro_path
.equals(getApplicationInfo().nativeLibraryDir);
return !globalConfigEnable && !config_same_as_native_lib_dir;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = this;
SharedPreferences prefs = getPreferences();
// Get libretro path and name.
SharedPreferences prefs = UserPreferences.getPreferences(this);
libretro_path = prefs.getString("libretro_path", getApplicationInfo().nativeLibraryDir);
libretro_name = prefs.getString("libretro_name", getString(R.string.no_core));
// Refresh the prefscreen and reload preferences.
refreshPreferenceScreen();
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
// Bind audio stream to hardware controls.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
// Extract assets.
extractAssets();
if (!prefs.getBoolean("first_time_refreshrate_calculate", false)) {
prefs.edit().putBoolean("first_time_refreshrate_calculate", true)
.commit();
prefs.edit().putBoolean("first_time_refreshrate_calculate", true).commit();
if (!detectDevice(false)) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
@ -102,10 +89,8 @@ public final class MainMenuActivity extends PreferenceActivity {
}
Intent startedByIntent = getIntent();
if (null != startedByIntent.getStringExtra("ROM")
&& null != startedByIntent.getStringExtra("LIBRETRO")) {
if (null == savedInstanceState
|| !savedInstanceState.getBoolean("romexec"))
if (startedByIntent.getStringExtra("ROM") != null && startedByIntent.getStringExtra("LIBRETRO") != null) {
if (savedInstanceState == null || !savedInstanceState.getBoolean("romexec"))
loadRomExternal(startedByIntent.getStringExtra("ROM"),
startedByIntent.getStringExtra("LIBRETRO"));
else
@ -117,380 +102,6 @@ public final class MainMenuActivity extends PreferenceActivity {
return instance;
}
private final double getDisplayRefreshRate() {
// Android is *very* likely to screw this up.
// It is rarely a good value to use, so make sure it's not
// completely wrong. Some phones return refresh rates that are
// completely bogus
// (like 0.3 Hz, etc), so try to be very conservative here.
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
double rate = display.getRefreshRate();
if (rate > 61.0 || rate < 58.0)
rate = 59.95;
return rate;
}
public static final double getRefreshRate() {
double rate = 0;
SharedPreferences prefs = getPreferences();
String refresh_rate = prefs.getString("video_refresh_rate", "");
if (!refresh_rate.isEmpty()) {
try {
rate = Double.parseDouble(refresh_rate);
} catch (NumberFormatException e) {
Log.e(TAG, "Cannot parse: " + refresh_rate + " as a double!");
rate = getInstance().getDisplayRefreshRate();
}
} else {
rate = getInstance().getDisplayRefreshRate();
}
Log.i(TAG, "Using refresh rate: " + rate + " Hz.");
return rate;
}
public static String readCPUInfo() {
String result = "";
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/cpuinfo")));
String line;
while ((line = br.readLine()) != null)
result += line + "\n";
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
@TargetApi(17)
public static int getLowLatencyOptimalSamplingRate() {
AudioManager manager = (AudioManager) getInstance()
.getApplicationContext()
.getSystemService(Context.AUDIO_SERVICE);
return Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
}
@TargetApi(17)
public static int getLowLatencyBufferSize() {
AudioManager manager = (AudioManager) getInstance()
.getApplicationContext()
.getSystemService(Context.AUDIO_SERVICE);
int buffersize = Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
Log.i(TAG, "Queried ideal buffer size (frames): " + buffersize);
return buffersize;
}
@TargetApi(17)
public static boolean hasLowLatencyAudio() {
PackageManager pm = getInstance().getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
}
public static int getOptimalSamplingRate() {
int ret;
if (android.os.Build.VERSION.SDK_INT >= 17)
ret = getLowLatencyOptimalSamplingRate();
else
ret = AudioTrack
.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
Log.i(TAG, "Using sampling rate: " + ret + " Hz");
return ret;
}
private static String sanitizeLibretroPath(String path) {
String sanitized_name = path.substring(
path.lastIndexOf("/") + 1,
path.lastIndexOf("."));
sanitized_name = sanitized_name.replace("neon", "");
sanitized_name = sanitized_name.replace("libretro_", "");
return sanitized_name;
}
public static String getDefaultConfigPath() {
String internal = System.getenv("INTERNAL_STORAGE");
String external = System.getenv("EXTERNAL_STORAGE");
String append_path;
if (getInstance().usePerCoreConfig()) {
String sanitized_name = sanitizeLibretroPath(libretro_path);
append_path = File.separator + sanitized_name + ".cfg";
} else {
append_path = File.separator + "retroarch.cfg";
}
if (external != null) {
String confPath = external + append_path;
if (new File(confPath).exists())
return confPath;
} else if (internal != null) {
String confPath = internal + append_path;
if (new File(confPath).exists())
return confPath;
} else {
String confPath = "/mnt/extsd" + append_path;
if (new File(confPath).exists())
return confPath;
}
if (internal != null && new File(internal + append_path).canWrite())
return internal + append_path;
else if (external != null
&& new File(internal + append_path).canWrite())
return external + append_path;
else if ((getInstance().getApplicationInfo().dataDir) != null)
return (getInstance().getApplicationInfo().dataDir)
+ append_path;
else
// emergency fallback, all else failed
return "/mnt/sd" + append_path;
}
private void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putString(key, cfg.getString(key));
else
edit.remove(key);
}
private void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putBoolean(key, cfg.getBoolean(key));
else
edit.remove(key);
}
private void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putFloat(key, (float)cfg.getDouble(key));
else
edit.remove(key);
}
private void readbackFloat(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putFloat(key, cfg.getFloat(key));
else
edit.remove(key);
}
private void readbackInt(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putInt(key, cfg.getInt(key));
else
edit.remove(key);
}
public void readbackConfigFile() {
String path = getDefaultConfigPath();
ConfigFile config;
try {
config = new ConfigFile(new File(path));
} catch (IOException e) {
return;
}
Log.i(TAG, "Config readback from: " + path);
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs.edit();
readbackString(config, edit, "rgui_browser_directory");
readbackString(config, edit, "savefile_directory");
readbackString(config, edit, "savestate_directory");
readbackBool(config, edit, "savefile_directory_enable"); // Ignored by RetroArch
readbackBool(config, edit, "savestate_directory_enable"); // Ignored by RetroArch
readbackString(config, edit, "input_overlay");
readbackBool(config, edit, "input_overlay_enable");
readbackBool(config, edit, "video_scale_integer");
readbackBool(config, edit, "video_smooth");
readbackBool(config, edit, "video_threaded");
readbackBool(config, edit, "rewind_enable");
readbackBool(config, edit, "savestate_auto_load");
readbackBool(config, edit, "savestate_auto_save");
//readbackDouble(config, edit, "video_refresh_rate");
readbackBool(config, edit, "audio_rate_control");
readbackBool(config, edit, "audio_enable");
// TODO: other audio settings
readbackDouble(config, edit, "input_overlay_opacity");
readbackBool(config, edit, "input_autodetect_enable");
//readbackInt(config, edit, "input_back_behavior");
readbackBool(config, edit, "video_allow_rotate");
readbackBool(config, edit, "video_font_enable");
readbackBool(config, edit, "video_vsync");
edit.commit();
}
public void updateConfigFile() {
String path = getDefaultConfigPath();
ConfigFile config;
try {
config = new ConfigFile(new File(path));
} catch (IOException e) {
config = new ConfigFile();
}
Log.i(TAG, "Writing config to: " + path);
SharedPreferences prefs = getPreferences();
config.setString("libretro_path", libretro_path);
config.setString("rgui_browser_directory",
prefs.getString("rgui_browser_directory", ""));
config.setBoolean("audio_rate_control",
prefs.getBoolean("audio_rate_control", true));
int optimalRate = getOptimalSamplingRate();
config.setInt("audio_out_rate", optimalRate);
// Refactor this entire mess and make this usable for per-core config
if (android.os.Build.VERSION.SDK_INT >= 17 &&
prefs.getBoolean("audio_latency_auto", true)) {
int buffersize = getLowLatencyBufferSize();
boolean lowLatency = hasLowLatencyAudio();
Log.i(TAG, "Audio is low latency: " + (lowLatency ? "yes" : "no"));
config.setInt("audio_latency", 64);
if (lowLatency) {
config.setInt("audio_block_frames", buffersize);
} else {
config.setInt("audio_block_frames", 0);
}
} else {
String latency_audio = prefs.getString("audio_latency", "64");
config.setInt("audio_latency", Integer.parseInt(latency_audio));
}
config.setBoolean("audio_enable",
prefs.getBoolean("audio_enable", true));
config.setBoolean("video_smooth",
prefs.getBoolean("video_smooth", true));
config.setBoolean("video_allow_rotate",
prefs.getBoolean("video_allow_rotate", true));
config.setBoolean("savestate_auto_load",
prefs.getBoolean("savestate_auto_load", true));
config.setBoolean("savestate_auto_save",
prefs.getBoolean("savestate_auto_save", false));
config.setBoolean("rewind_enable",
prefs.getBoolean("rewind_enable", false));
config.setBoolean("video_vsync", prefs.getBoolean("video_vsync", true));
config.setBoolean("input_autodetect_enable",
prefs.getBoolean("input_autodetect_enable", true));
config.setBoolean("input_debug_enable",
prefs.getBoolean("input_debug_enable", false));
config.setInt("input_back_behavior",
Integer.valueOf(prefs.getString("input_back_behavior", "0")));
config.setInt("input_autodetect_icade_profile_pad1", Integer
.valueOf(prefs.getString("input_autodetect_icade_profile_pad1",
"0")));
config.setInt("input_autodetect_icade_profile_pad2", Integer
.valueOf(prefs.getString("input_autodetect_icade_profile_pad2",
"0")));
config.setInt("input_autodetect_icade_profile_pad3", Integer
.valueOf(prefs.getString("input_autodetect_icade_profile_pad3",
"0")));
config.setInt("input_autodetect_icade_profile_pad4", Integer
.valueOf(prefs.getString("input_autodetect_icade_profile_pad4",
"0")));
config.setDouble("video_refresh_rate",
getRefreshRate());
config.setBoolean("video_threaded",
prefs.getBoolean("video_threaded", true));
// Refactor these weird values - 'full', 'auto', 'square', whatever -
// go by what we have in RGUI - makes maintaining state easier too
String aspect = prefs.getString("video_aspect_ratio", "auto");
if (aspect.equals("full")) {
config.setBoolean("video_force_aspect", false);
} else if (aspect.equals("auto")) {
config.setBoolean("video_force_aspect", true);
config.setBoolean("video_force_aspect_auto", true);
config.setDouble("video_aspect_ratio", -1.0);
} else if (aspect.equals("square")) {
config.setBoolean("video_force_aspect", true);
config.setBoolean("video_force_aspect_auto", false);
config.setDouble("video_aspect_ratio", -1.0);
} else {
double aspect_ratio = Double.parseDouble(aspect);
config.setBoolean("video_force_aspect", true);
config.setDouble("video_aspect_ratio", aspect_ratio);
}
config.setBoolean("video_scale_integer",
prefs.getBoolean("video_scale_integer", false));
String shaderPath = prefs.getString("video_shader", "");
config.setString("video_shader", shaderPath);
config.setBoolean("video_shader_enable",
prefs.getBoolean("video_shader_enable", false)
&& new File(shaderPath).exists());
boolean useOverlay = prefs.getBoolean("input_overlay_enable", true);
config.setBoolean("input_overlay_enable", useOverlay); // Not used by RetroArch directly.
if (useOverlay) {
String overlayPath = prefs
.getString("input_overlay", (getInstance()
.getApplicationInfo().dataDir)
+ "/overlays/snes-landscape.cfg");
config.setString("input_overlay", overlayPath);
config.setDouble("input_overlay_opacity",
prefs.getFloat("input_overlay_opacity", 1.0f));
} else {
config.setString("input_overlay", "");
}
config.setString(
"savefile_directory",
prefs.getBoolean("savefile_directory_enable", false) ? prefs
.getString("savefile_directory", "") : "");
config.setString(
"savestate_directory",
prefs.getBoolean("savestate_directory_enable", false) ? prefs
.getString("savestate_directory", "") : "");
config.setString(
"system_directory",
prefs.getBoolean("system_directory_enable", false) ? prefs
.getString("system_directory", "") : "");
config.setBoolean("video_font_enable",
prefs.getBoolean("video_font_enable", true));
config.setString("game_history_path", getInstance()
.getApplicationInfo().dataDir + "/retroarch-history.txt");
for (int i = 1; i <= 4; i++) {
final String[] btns = { "up", "down", "left", "right", "a", "b",
"x", "y", "start", "select", "l", "r", "l2", "r2", "l3",
"r3" };
for (String b : btns) {
String p = "input_player" + i + "_" + b
+ "_btn";
config.setInt(p, prefs.getInt(p, 0));
}
}
try {
config.write(new File(path));
} catch (IOException e) {
Log.e(TAG, "Failed to save config file to: " + path);
}
}
private byte[] loadAsset(String asset) throws IOException {
InputStream stream = getAssets().open(asset);
int len = stream.available();
@ -499,8 +110,7 @@ public final class MainMenuActivity extends PreferenceActivity {
return buf;
}
private void extractAssets(AssetManager manager, String dataDir,
String relativePath, int level) throws IOException {
private void extractAssets(AssetManager manager, String dataDir, String relativePath, int level) throws IOException {
final String[] paths = manager.list(relativePath);
if (paths != null && paths.length > 0) { // Directory
// Log.d(TAG, "Extracting assets directory: " + relativePath);
@ -621,24 +231,24 @@ public final class MainMenuActivity extends PreferenceActivity {
dialog.show();
}
public static SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(getInstance().getBaseContext());
}
public void setModule(String core_path, String core_name) {
updateConfigFile();
UserPreferences.updateConfigFile(this);
libretro_path = core_path;
libretro_name = core_name;
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(this);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("libretro_path", libretro_path);
edit.putString("libretro_name", libretro_name);
edit.commit();
if (usePerCoreConfig())
final boolean globalConfigEnabled = prefs.getBoolean("global_config_enable", true);
final String nativeLibraryDir = getApplicationInfo().nativeLibraryDir;
// Check if per-core settings are being used.
if (!globalConfigEnabled && !libretro_path.equals(nativeLibraryDir))
refreshPreferenceScreen();
else {
setCoreTitle(libretro_name); // this still needs to be applied
@ -649,14 +259,14 @@ public final class MainMenuActivity extends PreferenceActivity {
setTitle("RetroArch : " + core_name);
}
boolean detectDevice(boolean show_dialog) {
private boolean detectDevice(boolean show_dialog) {
boolean retval = false;
final boolean mentionPlayStore = !android.os.Build.MODEL.equals("OUYA Console");
final boolean mentionPlayStore = !Build.MODEL.equals("OUYA Console");
final String message = (mentionPlayStore ? getString(R.string.detect_device_msg_general) : getString(R.string.detect_device_msg_ouya));
Log.i("Device MODEL", android.os.Build.MODEL);
if (android.os.Build.MODEL.equals("SHIELD")) {
Log.i("Device MODEL", Build.MODEL);
if (Build.MODEL.equals("SHIELD")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.nvidia_shield_detected)
.setMessage(message)
@ -664,7 +274,7 @@ public final class MainMenuActivity extends PreferenceActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.toString(60.00d));
edit.putBoolean("input_overlay_enable", false);
@ -676,7 +286,7 @@ public final class MainMenuActivity extends PreferenceActivity {
});
alert.show();
retval = true;
} else if (android.os.Build.MODEL.equals("GAMEMID_BT")) {
} else if (Build.MODEL.equals("GAMEMID_BT")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.game_mid_detected)
.setMessage(message)
@ -684,7 +294,7 @@ public final class MainMenuActivity extends PreferenceActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("input_overlay_enable", false);
edit.putBoolean("input_autodetect_enable", true);
@ -695,7 +305,7 @@ public final class MainMenuActivity extends PreferenceActivity {
});
alert.show();
retval = true;
} else if (android.os.Build.MODEL.equals("OUYA Console")) {
} else if (Build.MODEL.equals("OUYA Console")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.ouya_detected)
.setMessage(message)
@ -703,7 +313,7 @@ public final class MainMenuActivity extends PreferenceActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("input_overlay_enable", false);
edit.putBoolean("input_autodetect_enable", true);
@ -714,7 +324,7 @@ public final class MainMenuActivity extends PreferenceActivity {
});
alert.show();
retval = true;
} else if (android.os.Build.MODEL.equals("R800x")) {
} else if (Build.MODEL.equals("R800x")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.xperia_play_detected)
.setMessage(message)
@ -722,7 +332,7 @@ public final class MainMenuActivity extends PreferenceActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("video_threaded", false);
edit.putBoolean("input_overlay_enable", false);
@ -735,7 +345,7 @@ public final class MainMenuActivity extends PreferenceActivity {
});
alert.show();
retval = true;
} else if (android.os.Build.ID.equals("JSS15J")) {
} else if (Build.ID.equals("JSS15J")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.nexus_7_2013_detected)
.setMessage(message)
@ -743,7 +353,7 @@ public final class MainMenuActivity extends PreferenceActivity {
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(MainMenuActivity.this);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.toString(59.65));
edit.putString("audio_latency", "64");
@ -764,15 +374,10 @@ public final class MainMenuActivity extends PreferenceActivity {
return retval;
}
@Override
protected void onStart() {
super.onStart();
}
@Override
public void startActivity(Intent intent) {
if (intent.getComponent().getClassName()
.equals("org.retroarch.browser.ROMActivity")) {
.equals("org.retroarch.browser.diractivities.ROMActivity")) {
if (!new File(libretro_path).isDirectory()) {
super.startActivityForResult(intent, ACTIVITY_LOAD_ROM);
} else {
@ -788,13 +393,13 @@ public final class MainMenuActivity extends PreferenceActivity {
switch (reqCode) {
case ACTIVITY_LOAD_ROM: {
if (data.getStringExtra("PATH") != null) {
updateConfigFile();
UserPreferences.updateConfigFile(this);
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
Toast.makeText(this,String.format(getString(R.string.loading_data), data.getStringExtra("PATH")), Toast.LENGTH_SHORT).show();
Intent myIntent = new Intent(this, RetroActivity.class);
myIntent.putExtra("ROM", data.getStringExtra("PATH"));
myIntent.putExtra("LIBRETRO", libretro_path);
myIntent.putExtra("CONFIGFILE", getDefaultConfigPath());
myIntent.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(this));
myIntent.putExtra("IME", current_ime);
startActivity(myIntent);
}
@ -810,13 +415,13 @@ public final class MainMenuActivity extends PreferenceActivity {
}
private void loadRomExternal(String rom, String core) {
updateConfigFile();
UserPreferences.updateConfigFile(this);
Intent myIntent = new Intent(this, RetroActivity.class);
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
Toast.makeText(this, String.format(getString(R.string.loading_data), rom), Toast.LENGTH_SHORT).show();
myIntent.putExtra("ROM", rom);
myIntent.putExtra("LIBRETRO", core);
myIntent.putExtra("CONFIGFILE", getDefaultConfigPath());
myIntent.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(this));
myIntent.putExtra("IME", current_ime);
startActivity(myIntent);
}

View File

@ -3,6 +3,8 @@ package org.retroarch.browser;
import java.io.File;
import java.io.IOException;
import org.retroarch.browser.preferences.ConfigFile;
import android.content.Context;
import android.graphics.drawable.Drawable;

View File

@ -1,9 +1,9 @@
package org.retroarch.browser;
import org.retroarch.R;
import org.retroarch.browser.preferences.UserPreferences;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Display;
@ -16,12 +16,12 @@ public final class RefreshRateSetOS extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
final WindowManager wm = getWindowManager();
final Display display = wm.getDefaultDisplay();
double rate = display.getRefreshRate();
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(this);
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.valueOf(rate).toString());
edit.putString("video_refresh_rate", Double.toString(rate));
edit.commit();
Toast.makeText(this, String.format(getString(R.string.using_os_reported_refresh_rate), rate), Toast.LENGTH_LONG).show();

View File

@ -15,21 +15,19 @@ public final class ReportIME extends Activity {
String current_ime = Settings.Secure.getString(getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD);
final Activity ctx = this;
AlertDialog.Builder dialog = new AlertDialog.Builder(this)
.setMessage(current_ime)
.setNeutralButton(R.string.close,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
ctx.finish();
public void onClick(DialogInterface dialog, int which) {
finish();
}
}).setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
ctx.finish();
finish();
}
});

View File

@ -18,20 +18,20 @@ public final class RetroActivity extends NativeActivity {
@Override
public void onTrimMemory(int level) {
}
// We call this function from native to display a toast string
public void showToastAlert(String text)
{
// We call this function from native to display a toast string
public void showToastAlert(String text)
{
// We need to use a runnable here to ensure that when the spawned
// native_app_glue thread calls, we actually post the work to the UI
// thread. Otherwise, we'll likely get exceptions because there's no
// prepared Looper on the native_app_glue main thread.
final String finalText = text;
runOnUiThread(new Runnable() {
public void run()
final String finalText = text;
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(getApplicationContext(), finalText, Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), finalText, Toast.LENGTH_SHORT).show();
}
});
}
});
}
}

View File

@ -1,21 +1,23 @@
package org.retroarch.browser;
import org.retroarch.browser.preferences.UserPreferences;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
public final class RetroTVMode extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainMenuActivity.getInstance().updateConfigFile();
UserPreferences.updateConfigFile(this);
Intent myIntent = new Intent(this, RetroActivity.class);
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
myIntent.putExtra("CONFIGFILE", MainMenuActivity.getDefaultConfigPath());
myIntent.putExtra("CONFIGFILE", UserPreferences.getDefaultConfigPath(this));
myIntent.putExtra("IME", current_ime);
startActivity(myIntent);
finish();

View File

@ -1,6 +1,9 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import org.retroarch.R;
import org.retroarch.browser.FileWrapper;
import org.retroarch.browser.IconAdapter;
import org.retroarch.browser.preferences.UserPreferences;
import java.util.*;
import java.io.*;
@ -13,8 +16,7 @@ import android.widget.*;
import android.view.*;
public class DirectoryActivity extends Activity implements
AdapterView.OnItemClickListener {
public class DirectoryActivity extends Activity implements AdapterView.OnItemClickListener {
private IconAdapter<FileWrapper> adapter;
private File listedDirectory;
@ -106,7 +108,7 @@ public class DirectoryActivity extends Activity implements
private void finishWithPath(String path) {
if (pathSettingKey != null && !pathSettingKey.isEmpty()) {
SharedPreferences settings = MainMenuActivity.getPreferences();
SharedPreferences settings = UserPreferences.getPreferences(this);
SharedPreferences.Editor editor = settings.edit();
editor.putString(pathSettingKey, path);
editor.commit();

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import java.io.File;
@ -7,7 +7,7 @@ import android.os.Bundle;
public final class OverlayActivity extends DirectoryActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
File overlayDir = new File(getBaseContext().getApplicationInfo().dataDir, "overlays");
File overlayDir = new File(getApplicationInfo().dataDir, "overlays");
if (overlayDir.exists())
super.setStartDirectory(overlayDir.getAbsolutePath());

View File

@ -1,7 +1,9 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import java.io.File;
import org.retroarch.browser.preferences.UserPreferences;
import android.content.SharedPreferences;
import android.os.Bundle;
@ -9,7 +11,7 @@ public final class ROMActivity extends DirectoryActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences prefs = UserPreferences.getPreferences(this);
String startPath = prefs.getString("rgui_browser_directory", "");
if (!startPath.isEmpty() && new File(startPath).exists())
super.setStartDirectory(startPath);

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import android.os.Bundle;

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import android.os.Bundle;

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import java.io.File;

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import android.os.Bundle;

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.diractivities;
import android.os.Bundle;

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.preferences;
import java.io.BufferedReader;
import java.io.InputStream;
@ -90,9 +90,9 @@ public final class ConfigFile {
}
public String getString(String key) {
Object ret = map.get(key);
String ret = map.get(key);
if (ret != null)
return (String) ret;
return ret;
else
return null;
}

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.preferences;
import android.content.Context;
import android.preference.DialogPreference;
@ -42,15 +42,16 @@ final class KeyBindEditText extends EditText
final class KeyBindPreference extends DialogPreference implements View.OnKeyListener, AdapterView.OnItemClickListener, LayoutInflater.Factory {
private int key_bind_code;
private boolean grabKeyCode = false;
KeyBindEditText keyText;
private KeyBindEditText keyText;
private String[] key_labels;
private final int DEFAULT_KEYCODE = 0;
private final Context context;
public KeyBindPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
key_labels = getContext().getResources().getStringArray(R.array.key_bind_values);
this.key_labels = getContext().getResources().getStringArray(R.array.key_bind_values);
}
private void setKey(int keyCode, boolean force)
@ -62,16 +63,11 @@ final class KeyBindPreference extends DialogPreference implements View.OnKeyList
keyText.setText(String.format(context.getString(R.string.current_binding), key_labels[key_bind_code]));
}
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
}
@Override
protected View onCreateDialogView()
{
LayoutInflater inflater = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).cloneInContext(getContext());
LayoutInflater inflater = LayoutInflater.from(context).cloneInContext(getContext());
inflater.setFactory(this);
View view = inflater.inflate(R.layout.key_bind_dialog, null);
keyText = (KeyBindEditText) view.findViewById(R.id.key_bind_value);
@ -79,17 +75,17 @@ final class KeyBindPreference extends DialogPreference implements View.OnKeyList
view.setOnKeyListener(this);
((ListView) view.findViewById(R.id.key_bind_list)).setOnItemClickListener(this);
((Button) view.findViewById(R.id.key_bind_clear)).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
setKey(0, true);
}
});
public void onClick(View v) {
setKey(0, true);
}
});
((Button) view.findViewById(R.id.key_bind_detect)).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
grabKeyCode = true;
keyText.setText(R.string.press_key_to_use);
keyText.requestFocus();
}
});
public void onClick(View v) {
grabKeyCode = true;
keyText.setText(R.string.press_key_to_use);
keyText.requestFocus();
}
});
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(keyText.getWindowToken(), 0);
setKey(getPersistedInt(DEFAULT_KEYCODE), true);
@ -98,12 +94,12 @@ final class KeyBindPreference extends DialogPreference implements View.OnKeyList
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
super.onDialogClosed(positiveResult);
if (positiveResult) {
persistInt(key_bind_code);
notifyChanged();
}
if (positiveResult) {
persistInt(key_bind_code);
notifyChanged();
}
}
@Override
@ -121,21 +117,21 @@ final class KeyBindPreference extends DialogPreference implements View.OnKeyList
setKey((int)id, true);
}
@Override
public CharSequence getSummary() {
int code = getPersistedInt(DEFAULT_KEYCODE);
@Override
public CharSequence getSummary() {
int code = getPersistedInt(DEFAULT_KEYCODE);
if (code >= key_labels.length)
return "";
else
return key_labels[code];
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
Log.i("RetroArch", "view name: " + name);
if (name.equals("EditText"))
return new KeyBindEditText(context, attrs);
else
return null;
}
}
@Override
public View onCreateView(String name, Context context, AttributeSet attrs) {
Log.i("RetroArch", "view name: " + name);
if (name.equals("EditText"))
return new KeyBindEditText(context, attrs);
else
return null;
}
}

View File

@ -1,4 +1,4 @@
package org.retroarch.browser;
package org.retroarch.browser.preferences;
import org.retroarch.R;
@ -11,36 +11,44 @@ import android.widget.SeekBar;
import android.widget.TextView;
public final class SeekbarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
float seek_value;
SeekBar bar;
TextView text;
private float seek_value;
private SeekBar bar;
private TextView text;
private final Context context;
public SeekbarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
protected View onCreateDialogView()
{
LayoutInflater inflater = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE));
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.seek_dialog, null);
bar = (SeekBar) view.findViewById(R.id.seekbar_bar);
text = (TextView) view.findViewById(R.id.seekbar_text);
seek_value = getPersistedFloat(1.0f);
this.bar = (SeekBar) view.findViewById(R.id.seekbar_bar);
this.text = (TextView) view.findViewById(R.id.seekbar_text);
this.seek_value = getPersistedFloat(1.0f);
// Set initial progress for seek bar and set the listener.
int prog = (int) (seek_value * 100);
bar.setProgress(prog);
text.setText(prog + "%");
bar.setOnSeekBarChangeListener(this);
this.bar.setProgress(prog);
this.text.setText(prog + "%");
this.bar.setOnSeekBarChangeListener(this);
return view;
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
persistFloat(seek_value);
}
super.onDialogClosed(positiveResult);
if (positiveResult) {
persistFloat(seek_value);
}
}
@Override

View File

@ -0,0 +1,543 @@
package org.retroarch.browser.preferences;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import org.retroarch.R;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Build;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
/**
* Utility class for retrieving, saving, or loading preferences.
*/
public final class UserPreferences
{
// Logging tag.
private static final String TAG = "UserPreferences";
/**
* Retrieves the path to the default location of the libretro config.
*
* @param ctx the current {@link Context}
*
* @return the path to the default location of the libretro config.
*/
public static String getDefaultConfigPath(Context ctx)
{
// Internal/External storage dirs.
final String internal = System.getenv("INTERNAL_STORAGE");
final String external = System.getenv("EXTERNAL_STORAGE");
// Native library directory and data directory for this front-end.
final String nativeLibraryDir = ctx.getApplicationInfo().nativeLibraryDir;
final String dataDir = ctx.getApplicationInfo().dataDir;
// Get libretro name and path
final SharedPreferences prefs = getPreferences(ctx);
final String libretro_path = prefs.getString("libretro_path", nativeLibraryDir);
final String libretro_name = prefs.getString("libretro_name", ctx.getString(R.string.no_core));
// Check if global config is being used. Return true upon failure.
final boolean globalConfigEnabled = prefs.getBoolean("global_config_enable", true);
String append_path;
// If we aren't using the global config.
if (!globalConfigEnabled && !libretro_path.equals(nativeLibraryDir))
{
String sanitized_name = sanitizeLibretroPath(libretro_path);
append_path = File.separator + sanitized_name + ".cfg";
}
else // Using global config.
{
append_path = File.separator + "retroarch.cfg";
}
if (external != null)
{
String confPath = external + append_path;
if (new File(confPath).exists())
return confPath;
}
else if (internal != null)
{
String confPath = internal + append_path;
if (new File(confPath).exists())
return confPath;
}
else
{
String confPath = "/mnt/extsd" + append_path;
if (new File(confPath).exists())
return confPath;
}
if (internal != null && new File(internal + append_path).canWrite())
return internal + append_path;
else if (external != null && new File(internal + append_path).canWrite())
return external + append_path;
else if (dataDir != null)
return dataDir + append_path;
else
// emergency fallback, all else failed
return "/mnt/sd" + append_path;
}
/**
* Re-reads the configuration file into the {@link SharedPreferences}
* instance that contains all of the settings for the front-end.
*
* @param ctx the current {@link Context}.
*/
public static void readbackConfigFile(Context ctx)
{
String path = getDefaultConfigPath(ctx);
ConfigFile config;
try
{
config = new ConfigFile(new File(path));
}
catch (IOException e)
{
return;
}
Log.i(TAG, "Config readback from: " + path);
SharedPreferences prefs = getPreferences(ctx);
SharedPreferences.Editor edit = prefs.edit();
readbackString(config, edit, "rgui_browser_directory");
readbackString(config, edit, "savefile_directory");
readbackString(config, edit, "savestate_directory");
readbackBool(config, edit, "savefile_directory_enable"); // Ignored by RetroArch
readbackBool(config, edit, "savestate_directory_enable"); // Ignored by RetroArch
readbackString(config, edit, "input_overlay");
readbackBool(config, edit, "input_overlay_enable");
readbackBool(config, edit, "video_scale_integer");
readbackBool(config, edit, "video_smooth");
readbackBool(config, edit, "video_threaded");
readbackBool(config, edit, "rewind_enable");
readbackBool(config, edit, "savestate_auto_load");
readbackBool(config, edit, "savestate_auto_save");
//readbackDouble(config, edit, "video_refresh_rate");
readbackBool(config, edit, "audio_rate_control");
readbackBool(config, edit, "audio_enable");
// TODO: other audio settings
readbackDouble(config, edit, "input_overlay_opacity");
readbackBool(config, edit, "input_autodetect_enable");
//readbackInt(config, edit, "input_back_behavior");
readbackBool(config, edit, "video_allow_rotate");
readbackBool(config, edit, "video_font_enable");
readbackBool(config, edit, "video_vsync");
edit.commit();
}
/**
* Updates the libretro configuration file
* with new values if settings have changed.
*
* @param ctx the current {@link Context}.
*/
public static void updateConfigFile(Context ctx)
{
String path = getDefaultConfigPath(ctx);
ConfigFile config;
try
{
config = new ConfigFile(new File(path));
}
catch (IOException e)
{
config = new ConfigFile();
}
Log.i(TAG, "Writing config to: " + path);
// Native library and data directories.
final String dataDir = ctx.getApplicationInfo().dataDir;
final String nativeLibraryDir = ctx.getApplicationInfo().nativeLibraryDir;
final SharedPreferences prefs = getPreferences(ctx);
final String libretro_path = prefs.getString("libretro_path", nativeLibraryDir);
config.setString("libretro_path", libretro_path);
config.setString("rgui_browser_directory", prefs.getString("rgui_browser_directory", ""));
config.setBoolean("audio_rate_control", prefs.getBoolean("audio_rate_control", true));
int optimalRate = getOptimalSamplingRate(ctx);
config.setInt("audio_out_rate", optimalRate);
// Refactor this entire mess and make this usable for per-core config
if (Build.VERSION.SDK_INT >= 17 && prefs.getBoolean("audio_latency_auto", true))
{
int buffersize = getLowLatencyBufferSize(ctx);
boolean lowLatency = hasLowLatencyAudio(ctx);
Log.i(TAG, "Audio is low latency: " + (lowLatency ? "yes" : "no"));
config.setInt("audio_latency", 64);
if (lowLatency)
{
config.setInt("audio_block_frames", buffersize);
}
else
{
config.setInt("audio_block_frames", 0);
}
}
else
{
String latency_audio = prefs.getString("audio_latency", "64");
config.setInt("audio_latency", Integer.parseInt(latency_audio));
}
config.setBoolean("audio_enable", prefs.getBoolean("audio_enable", true));
config.setBoolean("video_smooth", prefs.getBoolean("video_smooth", true));
config.setBoolean("video_allow_rotate", prefs.getBoolean("video_allow_rotate", true));
config.setBoolean("savestate_auto_load", prefs.getBoolean("savestate_auto_load", true));
config.setBoolean("savestate_auto_save", prefs.getBoolean("savestate_auto_save", false));
config.setBoolean("rewind_enable", prefs.getBoolean("rewind_enable", false));
config.setBoolean("video_vsync", prefs.getBoolean("video_vsync", true));
config.setBoolean("input_autodetect_enable", prefs.getBoolean("input_autodetect_enable", true));
config.setBoolean("input_debug_enable", prefs.getBoolean("input_debug_enable", false));
config.setInt("input_back_behavior", Integer.parseInt(prefs.getString("input_back_behavior", "0")));
// Set the iCade profiles
config.setInt("input_autodetect_icade_profile_pad1", Integer.parseInt(prefs.getString("input_autodetect_icade_profile_pad1", "0")));
config.setInt("input_autodetect_icade_profile_pad2", Integer.parseInt(prefs.getString("input_autodetect_icade_profile_pad2", "0")));
config.setInt("input_autodetect_icade_profile_pad3", Integer.parseInt(prefs.getString("input_autodetect_icade_profile_pad3", "0")));
config.setInt("input_autodetect_icade_profile_pad4", Integer.parseInt(prefs.getString("input_autodetect_icade_profile_pad4", "0")));
// Set the video refresh rate.
config.setDouble("video_refresh_rate", getRefreshRate(ctx));
// Set whether or not we're using threaded video.
config.setBoolean("video_threaded", prefs.getBoolean("video_threaded", true));
// Refactor these weird values - 'full', 'auto', 'square', whatever -
// go by what we have in RGUI - makes maintaining state easier too
String aspect = prefs.getString("video_aspect_ratio", "auto");
if (aspect.equals("full"))
{
config.setBoolean("video_force_aspect", false);
}
else if (aspect.equals("auto"))
{
config.setBoolean("video_force_aspect", true);
config.setBoolean("video_force_aspect_auto", true);
config.setDouble("video_aspect_ratio", -1.0);
}
else if (aspect.equals("square"))
{
config.setBoolean("video_force_aspect", true);
config.setBoolean("video_force_aspect_auto", false);
config.setDouble("video_aspect_ratio", -1.0);
}
else
{
double aspect_ratio = Double.parseDouble(aspect);
config.setBoolean("video_force_aspect", true);
config.setDouble("video_aspect_ratio", aspect_ratio);
}
// Set whether or not integer scaling is enabled.
config.setBoolean("video_scale_integer", prefs.getBoolean("video_scale_integer", false));
// Set whether or not shaders are being used.
String shaderPath = prefs.getString("video_shader", "");
config.setString("video_shader", shaderPath);
config.setBoolean("video_shader_enable", prefs.getBoolean("video_shader_enable", false) && new File(shaderPath).exists());
// Set whether or not custom overlays are being used.
final boolean useOverlay = prefs.getBoolean("input_overlay_enable", true);
config.setBoolean("input_overlay_enable", useOverlay); // Not used by RetroArch directly.
if (useOverlay)
{
String overlayPath = prefs.getString("input_overlay", dataDir + "/overlays/snes-landscape.cfg");
config.setString("input_overlay", overlayPath);
config.setDouble("input_overlay_opacity", prefs.getFloat("input_overlay_opacity", 1.0f));
}
else
{
config.setString("input_overlay", "");
}
// Set whether or not custom directories are being used.
final boolean usingCustomSaveFileDir = prefs.getBoolean("savefile_directory_enable", false);
final boolean usingCustomSaveStateDir = prefs.getBoolean("savestate_directory_enable", false);
final boolean usingCustomSystemDir = prefs.getBoolean("system_directory_enable", false);
config.setString("savefile_directory", usingCustomSaveFileDir ? prefs.getString("savefile_directory", "") : "");
config.setString("savestate_directory", usingCustomSaveStateDir ? prefs.getString("savestate_directory", "") : "");
config.setString("system_directory", usingCustomSystemDir ? prefs.getString("system_directory", "") : "");
config.setBoolean("video_font_enable", prefs.getBoolean("video_font_enable", true));
config.setString("game_history_path", dataDir + "/retroarch-history.txt");
for (int i = 1; i <= 4; i++)
{
final String[] btns =
{
"up", "down", "left", "right",
"a", "b", "x", "y", "start", "select",
"l", "r", "l2", "r2", "l3", "r3"
};
for (String b : btns)
{
String p = "input_player" + i + "_" + b + "_btn";
config.setInt(p, prefs.getInt(p, 0));
}
}
try
{
config.write(new File(path));
}
catch (IOException e)
{
Log.e(TAG, "Failed to save config file to: " + path);
}
}
private static void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key)
{
if (cfg.keyExists(key))
edit.putString(key, cfg.getString(key));
else
edit.remove(key);
}
private static void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key)
{
if (cfg.keyExists(key))
edit.putBoolean(key, cfg.getBoolean(key));
else
edit.remove(key);
}
private static void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key)
{
if (cfg.keyExists(key))
edit.putFloat(key, (float)cfg.getDouble(key));
else
edit.remove(key);
}
private static void readbackFloat(ConfigFile cfg, SharedPreferences.Editor edit, String key)
{
if (cfg.keyExists(key))
edit.putFloat(key, cfg.getFloat(key));
else
edit.remove(key);
}
private static void readbackInt(ConfigFile cfg, SharedPreferences.Editor edit, String key)
{
if (cfg.keyExists(key))
edit.putInt(key, cfg.getInt(key));
else
edit.remove(key);
}
/**
* Sanitizes a libretro core path.
*
* @param path The path to the libretro core.
*
* @return the sanitized libretro path.
*/
private static String sanitizeLibretroPath(String path)
{
String sanitized_name = path.substring(
path.lastIndexOf("/") + 1,
path.lastIndexOf("."));
sanitized_name = sanitized_name.replace("neon", "");
sanitized_name = sanitized_name.replace("libretro_", "");
return sanitized_name;
}
/**
* Gets a {@link SharedPreferences} instance containing current settings.
*
* @param ctx the current {@link Context}.
*
* @return A SharedPreference instance containing current settings.
*/
public static SharedPreferences getPreferences(Context ctx)
{
return PreferenceManager.getDefaultSharedPreferences(ctx);
}
/**
* Retrieves an approximate display refresh rate for a device.
* <p>
* Note that some devices will return completely wrong values
* with the {@link Display#getRefreshRate()} method, and so
* this method attempts to ballpark an appropriate value.
*
* @param ctx the current {@link Context}.
*
* @return an approximately correct display refresh rate for a device.
*/
private static double getRefreshRate(Context ctx)
{
double rate = 0;
SharedPreferences prefs = getPreferences(ctx);
String refresh_rate = prefs.getString("video_refresh_rate", "");
if (!refresh_rate.isEmpty())
{
try
{
rate = Double.parseDouble(refresh_rate);
}
catch (NumberFormatException e)
{
Log.e(TAG, "Cannot parse: " + refresh_rate + " as a double!");
rate = getDisplayRefreshRate(ctx);
}
}
else
{
rate = getDisplayRefreshRate(ctx);
}
Log.i(TAG, "Using refresh rate: " + rate + " Hz.");
return rate;
}
// Utility function used with getRefreshRate.
private static double getDisplayRefreshRate(Context ctx)
{
// Android is *very* likely to screw this up.
// It is rarely a good value to use, so make sure it's not
// completely wrong. Some phones return refresh rates that are
// completely bogus
// (like 0.3 Hz, etc), so try to be very conservative here.
final WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
double rate = display.getRefreshRate();
if (rate > 61.0 || rate < 58.0)
rate = 59.95;
return rate;
}
/**
* Gets the optimal sampling rate for low-latency audio playback.
*
* @param ctx the current {@link Context}.
*
* @return the optimal sampling rate for low-latency audio playback in Hz.
*/
@TargetApi(17)
private static int getLowLatencyOptimalSamplingRate(Context ctx)
{
AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
return Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
}
/**
* Gets the optimal buffer size for low-latency audio playback.
*
* @param ctx the current {@link Context}.
*
* @return the optimal output buffer size in decimal PCM frames.
*/
@TargetApi(17)
private static int getLowLatencyBufferSize(Context ctx)
{
AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
int buffersize = Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
Log.i(TAG, "Queried ideal buffer size (frames): " + buffersize);
return buffersize;
}
/**
* Checks whether or not a device supports low-latency audio.
*
* @param ctx the current {@link Context}.
*
* @return true if the device supports low-latency audio; false otherwise.
*/
@TargetApi(17)
private static boolean hasLowLatencyAudio(Context ctx)
{
PackageManager pm = ctx.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
}
/**
* Gets the optimal audio sampling rate.
* <p>
* On Android 4.2+ devices this will retrieve the optimal low-latency sampling rate,
* since Android 4.2 adds support for low latency audio in general.
* <p>
* On other devices, it simply returns the regular optimal sampling rate
* as returned by the hardware.
*
* @param ctx The current {@link Context}.
*
* @return the optimal audio sampling rate in Hz.
*/
private static int getOptimalSamplingRate(Context ctx)
{
int ret;
if (Build.VERSION.SDK_INT >= 17)
ret = getLowLatencyOptimalSamplingRate(ctx);
else
ret = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
Log.i(TAG, "Using sampling rate: " + ret + " Hz");
return ret;
}
/**
* Retrieves the CPU info, as provided by /proc/cpuinfo.
*
* @return the CPU info.
*/
public static String readCPUInfo()
{
String result = "";
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("/proc/cpuinfo")));
String line;
while ((line = br.readLine()) != null)
result += line + "\n";
br.close();
}
catch (IOException ex)
{
ex.printStackTrace();
}
return result;
}
}