Reformat Android code
This commit is contained in:
parent
ab76631a7f
commit
248ee12aed
|
@ -67,7 +67,8 @@ android {
|
|||
defaultConfig {
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=RelWithDebInfo" // , "-DENABLE_GENERIC=ON"
|
||||
arguments "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
|
||||
// , "-DENABLE_GENERIC=ON"
|
||||
abiFilters "arm64-v8a", "x86_64" //, "armeabi-v7a", "x86"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
android:name="android.software.leanback"
|
||||
android:required="false"/>
|
||||
|
||||
<uses-feature android:glEsVersion="0x00030000" />
|
||||
<uses-feature android:glEsVersion="0x00030000"/>
|
||||
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
|
||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
|
||||
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
|
||||
|
||||
<application
|
||||
android:name=".DolphinApplication"
|
||||
|
@ -27,7 +27,9 @@
|
|||
android:supportsRtl="true"
|
||||
android:isGame="true"
|
||||
android:banner="@drawable/banner_tv">
|
||||
<meta-data android:name="android.max_aspect" android:value="2.1" />
|
||||
<meta-data
|
||||
android:name="android.max_aspect"
|
||||
android:value="2.1"/>
|
||||
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
|
@ -67,18 +69,18 @@
|
|||
android:label="@string/app_name"
|
||||
android:theme="@style/FilePickerTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.GET_CONTENT" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.GET_CONTENT"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".activities.AppLinkActivity" >
|
||||
<activity android:name=".activities.AppLinkActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<data
|
||||
android:host="@string/host"
|
||||
android:scheme="@string/scheme" />
|
||||
android:scheme="@string/scheme"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
@ -87,11 +89,11 @@
|
|||
<service
|
||||
android:name=".services.SyncChannelJobService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||
<service
|
||||
android:name=".services.SyncProgramsJobService"
|
||||
android:exported="false"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
|
@ -100,7 +102,7 @@
|
|||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/nnf_provider_paths" />
|
||||
android:resource="@xml/nnf_provider_paths"/>
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
|
|
@ -8,15 +8,15 @@ import org.dolphinemu.dolphinemu.utils.VolleyUtil;
|
|||
|
||||
public class DolphinApplication extends Application
|
||||
{
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
@Override
|
||||
public void onCreate()
|
||||
{
|
||||
super.onCreate();
|
||||
|
||||
VolleyUtil.init(getApplicationContext());
|
||||
System.loadLibrary("main");
|
||||
VolleyUtil.init(getApplicationContext());
|
||||
System.loadLibrary("main");
|
||||
|
||||
if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
|
||||
DirectoryInitializationService.startService(getApplicationContext());
|
||||
}
|
||||
if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
|
||||
DirectoryInitializationService.startService(getApplicationContext());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,7 @@
|
|||
package org.dolphinemu.dolphinemu;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.content.res.AssetManager;
|
||||
import android.view.Surface;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
@ -26,433 +20,448 @@ import java.lang.ref.WeakReference;
|
|||
*/
|
||||
public final class NativeLibrary
|
||||
{
|
||||
public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
|
||||
public static WeakReference<EmulationActivity> sEmulationActivity = new WeakReference<>(null);
|
||||
|
||||
/**
|
||||
* Button type for use in onTouchEvent
|
||||
*/
|
||||
public static final class ButtonType
|
||||
{
|
||||
public static final int BUTTON_A = 0;
|
||||
public static final int BUTTON_B = 1;
|
||||
public static final int BUTTON_START = 2;
|
||||
public static final int BUTTON_X = 3;
|
||||
public static final int BUTTON_Y = 4;
|
||||
public static final int BUTTON_Z = 5;
|
||||
public static final int BUTTON_UP = 6;
|
||||
public static final int BUTTON_DOWN = 7;
|
||||
public static final int BUTTON_LEFT = 8;
|
||||
public static final int BUTTON_RIGHT = 9;
|
||||
public static final int STICK_MAIN = 10;
|
||||
public static final int STICK_MAIN_UP = 11;
|
||||
public static final int STICK_MAIN_DOWN = 12;
|
||||
public static final int STICK_MAIN_LEFT = 13;
|
||||
public static final int STICK_MAIN_RIGHT = 14;
|
||||
public static final int STICK_C = 15;
|
||||
public static final int STICK_C_UP = 16;
|
||||
public static final int STICK_C_DOWN = 17;
|
||||
public static final int STICK_C_LEFT = 18;
|
||||
public static final int STICK_C_RIGHT = 19;
|
||||
public static final int TRIGGER_L = 20;
|
||||
public static final int TRIGGER_R = 21;
|
||||
public static final int WIIMOTE_BUTTON_A = 100;
|
||||
public static final int WIIMOTE_BUTTON_B = 101;
|
||||
public static final int WIIMOTE_BUTTON_MINUS = 102;
|
||||
public static final int WIIMOTE_BUTTON_PLUS = 103;
|
||||
public static final int WIIMOTE_BUTTON_HOME = 104;
|
||||
public static final int WIIMOTE_BUTTON_1 = 105;
|
||||
public static final int WIIMOTE_BUTTON_2 = 106;
|
||||
public static final int WIIMOTE_UP = 107;
|
||||
public static final int WIIMOTE_DOWN = 108;
|
||||
public static final int WIIMOTE_LEFT = 109;
|
||||
public static final int WIIMOTE_RIGHT = 110;
|
||||
public static final int WIIMOTE_IR = 111;
|
||||
public static final int WIIMOTE_IR_UP = 112;
|
||||
public static final int WIIMOTE_IR_DOWN = 113;
|
||||
public static final int WIIMOTE_IR_LEFT = 114;
|
||||
public static final int WIIMOTE_IR_RIGHT = 115;
|
||||
public static final int WIIMOTE_IR_FORWARD = 116;
|
||||
public static final int WIIMOTE_IR_BACKWARD = 117;
|
||||
public static final int WIIMOTE_IR_HIDE = 118;
|
||||
public static final int WIIMOTE_SWING = 119;
|
||||
public static final int WIIMOTE_SWING_UP = 120;
|
||||
public static final int WIIMOTE_SWING_DOWN = 121;
|
||||
public static final int WIIMOTE_SWING_LEFT = 122;
|
||||
public static final int WIIMOTE_SWING_RIGHT = 123;
|
||||
public static final int WIIMOTE_SWING_FORWARD = 124;
|
||||
public static final int WIIMOTE_SWING_BACKWARD = 125;
|
||||
public static final int WIIMOTE_TILT = 126;
|
||||
public static final int WIIMOTE_TILT_FORWARD = 127;
|
||||
public static final int WIIMOTE_TILT_BACKWARD = 128;
|
||||
public static final int WIIMOTE_TILT_LEFT = 129;
|
||||
public static final int WIIMOTE_TILT_RIGHT = 130;
|
||||
public static final int WIIMOTE_TILT_MODIFIER = 131;
|
||||
public static final int WIIMOTE_SHAKE_X = 132;
|
||||
public static final int WIIMOTE_SHAKE_Y = 133;
|
||||
public static final int WIIMOTE_SHAKE_Z = 134;
|
||||
public static final int NUNCHUK_BUTTON_C = 200;
|
||||
public static final int NUNCHUK_BUTTON_Z = 201;
|
||||
public static final int NUNCHUK_STICK = 202;
|
||||
public static final int NUNCHUK_STICK_UP = 203;
|
||||
public static final int NUNCHUK_STICK_DOWN = 204;
|
||||
public static final int NUNCHUK_STICK_LEFT = 205;
|
||||
public static final int NUNCHUK_STICK_RIGHT = 206;
|
||||
public static final int NUNCHUK_SWING = 207;
|
||||
public static final int NUNCHUK_SWING_UP = 208;
|
||||
public static final int NUNCHUK_SWING_DOWN = 209;
|
||||
public static final int NUNCHUK_SWING_LEFT = 210;
|
||||
public static final int NUNCHUK_SWING_RIGHT = 221;
|
||||
public static final int NUNCHUK_SWING_FORWARD = 212;
|
||||
public static final int NUNCHUK_SWING_BACKWARD = 213;
|
||||
public static final int NUNCHUK_TILT = 214;
|
||||
public static final int NUNCHUK_TILT_FORWARD = 215;
|
||||
public static final int NUNCHUK_TILT_BACKWARD = 216;
|
||||
public static final int NUNCHUK_TILT_LEFT = 217;
|
||||
public static final int NUNCHUK_TILT_RIGHT = 218;
|
||||
public static final int NUNCHUK_TILT_MODIFIER = 219;
|
||||
public static final int NUNCHUK_SHAKE_X = 220;
|
||||
public static final int NUNCHUK_SHAKE_Y = 221;
|
||||
public static final int NUNCHUK_SHAKE_Z = 222;
|
||||
public static final int CLASSIC_BUTTON_A = 300;
|
||||
public static final int CLASSIC_BUTTON_B = 301;
|
||||
public static final int CLASSIC_BUTTON_X = 302;
|
||||
public static final int CLASSIC_BUTTON_Y = 303;
|
||||
public static final int CLASSIC_BUTTON_MINUS = 304;
|
||||
public static final int CLASSIC_BUTTON_PLUS = 305;
|
||||
public static final int CLASSIC_BUTTON_HOME = 306;
|
||||
public static final int CLASSIC_BUTTON_ZL = 307;
|
||||
public static final int CLASSIC_BUTTON_ZR = 308;
|
||||
public static final int CLASSIC_DPAD_UP = 309;
|
||||
public static final int CLASSIC_DPAD_DOWN = 310;
|
||||
public static final int CLASSIC_DPAD_LEFT = 311;
|
||||
public static final int CLASSIC_DPAD_RIGHT = 312;
|
||||
public static final int CLASSIC_STICK_LEFT = 313;
|
||||
public static final int CLASSIC_STICK_LEFT_UP = 314;
|
||||
public static final int CLASSIC_STICK_LEFT_DOWN = 315;
|
||||
public static final int CLASSIC_STICK_LEFT_LEFT = 316;
|
||||
public static final int CLASSIC_STICK_LEFT_RIGHT = 317;
|
||||
public static final int CLASSIC_STICK_RIGHT = 318;
|
||||
public static final int CLASSIC_STICK_RIGHT_UP = 319;
|
||||
public static final int CLASSIC_STICK_RIGHT_DOWN = 100;
|
||||
public static final int CLASSIC_STICK_RIGHT_LEFT = 321;
|
||||
public static final int CLASSIC_STICK_RIGHT_RIGHT = 322;
|
||||
public static final int CLASSIC_TRIGGER_L = 323;
|
||||
public static final int CLASSIC_TRIGGER_R = 324;
|
||||
public static final int GUITAR_BUTTON_MINUS = 400;
|
||||
public static final int GUITAR_BUTTON_PLUS = 401;
|
||||
public static final int GUITAR_FRET_GREEN = 402;
|
||||
public static final int GUITAR_FRET_RED = 403;
|
||||
public static final int GUITAR_FRET_YELLOW = 404;
|
||||
public static final int GUITAR_FRET_BLUE = 405;
|
||||
public static final int GUITAR_FRET_ORANGE = 406;
|
||||
public static final int GUITAR_STRUM_UP = 407;
|
||||
public static final int GUITAR_STRUM_DOWN = 408;
|
||||
public static final int GUITAR_STICK = 409;
|
||||
public static final int GUITAR_STICK_UP = 410;
|
||||
public static final int GUITAR_STICK_DOWN = 411;
|
||||
public static final int GUITAR_STICK_LEFT = 412;
|
||||
public static final int GUITAR_STICK_RIGHT = 413;
|
||||
public static final int GUITAR_WHAMMY_BAR = 414;
|
||||
public static final int DRUMS_BUTTON_MINUS = 500;
|
||||
public static final int DRUMS_BUTTON_PLUS = 501;
|
||||
public static final int DRUMS_PAD_RED = 502;
|
||||
public static final int DRUMS_PAD_YELLOW = 503;
|
||||
public static final int DRUMS_PAD_BLUE = 504;
|
||||
public static final int DRUMS_PAD_GREEN = 505;
|
||||
public static final int DRUMS_PAD_ORANGE = 506;
|
||||
public static final int DRUMS_PAD_BASS = 507;
|
||||
public static final int DRUMS_STICK = 508;
|
||||
public static final int DRUMS_STICK_UP = 509;
|
||||
public static final int DRUMS_STICK_DOWN = 510;
|
||||
public static final int DRUMS_STICK_LEFT = 511;
|
||||
public static final int DRUMS_STICK_RIGHT = 512;
|
||||
public static final int TURNTABLE_BUTTON_GREEN_LEFT = 600;
|
||||
public static final int TURNTABLE_BUTTON_RED_LEFT = 601;
|
||||
public static final int TURNTABLE_BUTTON_BLUE_LEFT = 602;
|
||||
public static final int TURNTABLE_BUTTON_GREEN_RIGHT = 603;
|
||||
public static final int TURNTABLE_BUTTON_RED_RIGHT = 604;
|
||||
public static final int TURNTABLE_BUTTON_BLUE_RIGHT = 605;
|
||||
public static final int TURNTABLE_BUTTON_MINUS = 606;
|
||||
public static final int TURNTABLE_BUTTON_PLUS = 607;
|
||||
public static final int TURNTABLE_BUTTON_HOME = 608;
|
||||
public static final int TURNTABLE_BUTTON_EUPHORIA = 609;
|
||||
public static final int TURNTABLE_TABLE_LEFT = 610;
|
||||
public static final int TURNTABLE_TABLE_LEFT_LEFT = 611;
|
||||
public static final int TURNTABLE_TABLE_LEFT_RIGHT = 612;
|
||||
public static final int TURNTABLE_TABLE_RIGHT = 613;
|
||||
public static final int TURNTABLE_TABLE_RIGHT_LEFT = 614;
|
||||
public static final int TURNTABLE_TABLE_RIGHT_RIGHT = 615;
|
||||
public static final int TURNTABLE_STICK = 616;
|
||||
public static final int TURNTABLE_STICK_UP = 617;
|
||||
public static final int TURNTABLE_STICK_DOWN = 618;
|
||||
public static final int TURNTABLE_STICK_LEFT = 619;
|
||||
public static final int TURNTABLE_STICK_RIGHT = 620;
|
||||
public static final int TURNTABLE_EFFECT_DIAL = 621;
|
||||
public static final int TURNTABLE_CROSSFADE = 622;
|
||||
public static final int TURNTABLE_CROSSFADE_LEFT = 623;
|
||||
public static final int TURNTABLE_CROSSFADE_RIGHT = 624;
|
||||
}
|
||||
/**
|
||||
* Button type for use in onTouchEvent
|
||||
*/
|
||||
public static final class ButtonType
|
||||
{
|
||||
public static final int BUTTON_A = 0;
|
||||
public static final int BUTTON_B = 1;
|
||||
public static final int BUTTON_START = 2;
|
||||
public static final int BUTTON_X = 3;
|
||||
public static final int BUTTON_Y = 4;
|
||||
public static final int BUTTON_Z = 5;
|
||||
public static final int BUTTON_UP = 6;
|
||||
public static final int BUTTON_DOWN = 7;
|
||||
public static final int BUTTON_LEFT = 8;
|
||||
public static final int BUTTON_RIGHT = 9;
|
||||
public static final int STICK_MAIN = 10;
|
||||
public static final int STICK_MAIN_UP = 11;
|
||||
public static final int STICK_MAIN_DOWN = 12;
|
||||
public static final int STICK_MAIN_LEFT = 13;
|
||||
public static final int STICK_MAIN_RIGHT = 14;
|
||||
public static final int STICK_C = 15;
|
||||
public static final int STICK_C_UP = 16;
|
||||
public static final int STICK_C_DOWN = 17;
|
||||
public static final int STICK_C_LEFT = 18;
|
||||
public static final int STICK_C_RIGHT = 19;
|
||||
public static final int TRIGGER_L = 20;
|
||||
public static final int TRIGGER_R = 21;
|
||||
public static final int WIIMOTE_BUTTON_A = 100;
|
||||
public static final int WIIMOTE_BUTTON_B = 101;
|
||||
public static final int WIIMOTE_BUTTON_MINUS = 102;
|
||||
public static final int WIIMOTE_BUTTON_PLUS = 103;
|
||||
public static final int WIIMOTE_BUTTON_HOME = 104;
|
||||
public static final int WIIMOTE_BUTTON_1 = 105;
|
||||
public static final int WIIMOTE_BUTTON_2 = 106;
|
||||
public static final int WIIMOTE_UP = 107;
|
||||
public static final int WIIMOTE_DOWN = 108;
|
||||
public static final int WIIMOTE_LEFT = 109;
|
||||
public static final int WIIMOTE_RIGHT = 110;
|
||||
public static final int WIIMOTE_IR = 111;
|
||||
public static final int WIIMOTE_IR_UP = 112;
|
||||
public static final int WIIMOTE_IR_DOWN = 113;
|
||||
public static final int WIIMOTE_IR_LEFT = 114;
|
||||
public static final int WIIMOTE_IR_RIGHT = 115;
|
||||
public static final int WIIMOTE_IR_FORWARD = 116;
|
||||
public static final int WIIMOTE_IR_BACKWARD = 117;
|
||||
public static final int WIIMOTE_IR_HIDE = 118;
|
||||
public static final int WIIMOTE_SWING = 119;
|
||||
public static final int WIIMOTE_SWING_UP = 120;
|
||||
public static final int WIIMOTE_SWING_DOWN = 121;
|
||||
public static final int WIIMOTE_SWING_LEFT = 122;
|
||||
public static final int WIIMOTE_SWING_RIGHT = 123;
|
||||
public static final int WIIMOTE_SWING_FORWARD = 124;
|
||||
public static final int WIIMOTE_SWING_BACKWARD = 125;
|
||||
public static final int WIIMOTE_TILT = 126;
|
||||
public static final int WIIMOTE_TILT_FORWARD = 127;
|
||||
public static final int WIIMOTE_TILT_BACKWARD = 128;
|
||||
public static final int WIIMOTE_TILT_LEFT = 129;
|
||||
public static final int WIIMOTE_TILT_RIGHT = 130;
|
||||
public static final int WIIMOTE_TILT_MODIFIER = 131;
|
||||
public static final int WIIMOTE_SHAKE_X = 132;
|
||||
public static final int WIIMOTE_SHAKE_Y = 133;
|
||||
public static final int WIIMOTE_SHAKE_Z = 134;
|
||||
public static final int NUNCHUK_BUTTON_C = 200;
|
||||
public static final int NUNCHUK_BUTTON_Z = 201;
|
||||
public static final int NUNCHUK_STICK = 202;
|
||||
public static final int NUNCHUK_STICK_UP = 203;
|
||||
public static final int NUNCHUK_STICK_DOWN = 204;
|
||||
public static final int NUNCHUK_STICK_LEFT = 205;
|
||||
public static final int NUNCHUK_STICK_RIGHT = 206;
|
||||
public static final int NUNCHUK_SWING = 207;
|
||||
public static final int NUNCHUK_SWING_UP = 208;
|
||||
public static final int NUNCHUK_SWING_DOWN = 209;
|
||||
public static final int NUNCHUK_SWING_LEFT = 210;
|
||||
public static final int NUNCHUK_SWING_RIGHT = 221;
|
||||
public static final int NUNCHUK_SWING_FORWARD = 212;
|
||||
public static final int NUNCHUK_SWING_BACKWARD = 213;
|
||||
public static final int NUNCHUK_TILT = 214;
|
||||
public static final int NUNCHUK_TILT_FORWARD = 215;
|
||||
public static final int NUNCHUK_TILT_BACKWARD = 216;
|
||||
public static final int NUNCHUK_TILT_LEFT = 217;
|
||||
public static final int NUNCHUK_TILT_RIGHT = 218;
|
||||
public static final int NUNCHUK_TILT_MODIFIER = 219;
|
||||
public static final int NUNCHUK_SHAKE_X = 220;
|
||||
public static final int NUNCHUK_SHAKE_Y = 221;
|
||||
public static final int NUNCHUK_SHAKE_Z = 222;
|
||||
public static final int CLASSIC_BUTTON_A = 300;
|
||||
public static final int CLASSIC_BUTTON_B = 301;
|
||||
public static final int CLASSIC_BUTTON_X = 302;
|
||||
public static final int CLASSIC_BUTTON_Y = 303;
|
||||
public static final int CLASSIC_BUTTON_MINUS = 304;
|
||||
public static final int CLASSIC_BUTTON_PLUS = 305;
|
||||
public static final int CLASSIC_BUTTON_HOME = 306;
|
||||
public static final int CLASSIC_BUTTON_ZL = 307;
|
||||
public static final int CLASSIC_BUTTON_ZR = 308;
|
||||
public static final int CLASSIC_DPAD_UP = 309;
|
||||
public static final int CLASSIC_DPAD_DOWN = 310;
|
||||
public static final int CLASSIC_DPAD_LEFT = 311;
|
||||
public static final int CLASSIC_DPAD_RIGHT = 312;
|
||||
public static final int CLASSIC_STICK_LEFT = 313;
|
||||
public static final int CLASSIC_STICK_LEFT_UP = 314;
|
||||
public static final int CLASSIC_STICK_LEFT_DOWN = 315;
|
||||
public static final int CLASSIC_STICK_LEFT_LEFT = 316;
|
||||
public static final int CLASSIC_STICK_LEFT_RIGHT = 317;
|
||||
public static final int CLASSIC_STICK_RIGHT = 318;
|
||||
public static final int CLASSIC_STICK_RIGHT_UP = 319;
|
||||
public static final int CLASSIC_STICK_RIGHT_DOWN = 100;
|
||||
public static final int CLASSIC_STICK_RIGHT_LEFT = 321;
|
||||
public static final int CLASSIC_STICK_RIGHT_RIGHT = 322;
|
||||
public static final int CLASSIC_TRIGGER_L = 323;
|
||||
public static final int CLASSIC_TRIGGER_R = 324;
|
||||
public static final int GUITAR_BUTTON_MINUS = 400;
|
||||
public static final int GUITAR_BUTTON_PLUS = 401;
|
||||
public static final int GUITAR_FRET_GREEN = 402;
|
||||
public static final int GUITAR_FRET_RED = 403;
|
||||
public static final int GUITAR_FRET_YELLOW = 404;
|
||||
public static final int GUITAR_FRET_BLUE = 405;
|
||||
public static final int GUITAR_FRET_ORANGE = 406;
|
||||
public static final int GUITAR_STRUM_UP = 407;
|
||||
public static final int GUITAR_STRUM_DOWN = 408;
|
||||
public static final int GUITAR_STICK = 409;
|
||||
public static final int GUITAR_STICK_UP = 410;
|
||||
public static final int GUITAR_STICK_DOWN = 411;
|
||||
public static final int GUITAR_STICK_LEFT = 412;
|
||||
public static final int GUITAR_STICK_RIGHT = 413;
|
||||
public static final int GUITAR_WHAMMY_BAR = 414;
|
||||
public static final int DRUMS_BUTTON_MINUS = 500;
|
||||
public static final int DRUMS_BUTTON_PLUS = 501;
|
||||
public static final int DRUMS_PAD_RED = 502;
|
||||
public static final int DRUMS_PAD_YELLOW = 503;
|
||||
public static final int DRUMS_PAD_BLUE = 504;
|
||||
public static final int DRUMS_PAD_GREEN = 505;
|
||||
public static final int DRUMS_PAD_ORANGE = 506;
|
||||
public static final int DRUMS_PAD_BASS = 507;
|
||||
public static final int DRUMS_STICK = 508;
|
||||
public static final int DRUMS_STICK_UP = 509;
|
||||
public static final int DRUMS_STICK_DOWN = 510;
|
||||
public static final int DRUMS_STICK_LEFT = 511;
|
||||
public static final int DRUMS_STICK_RIGHT = 512;
|
||||
public static final int TURNTABLE_BUTTON_GREEN_LEFT = 600;
|
||||
public static final int TURNTABLE_BUTTON_RED_LEFT = 601;
|
||||
public static final int TURNTABLE_BUTTON_BLUE_LEFT = 602;
|
||||
public static final int TURNTABLE_BUTTON_GREEN_RIGHT = 603;
|
||||
public static final int TURNTABLE_BUTTON_RED_RIGHT = 604;
|
||||
public static final int TURNTABLE_BUTTON_BLUE_RIGHT = 605;
|
||||
public static final int TURNTABLE_BUTTON_MINUS = 606;
|
||||
public static final int TURNTABLE_BUTTON_PLUS = 607;
|
||||
public static final int TURNTABLE_BUTTON_HOME = 608;
|
||||
public static final int TURNTABLE_BUTTON_EUPHORIA = 609;
|
||||
public static final int TURNTABLE_TABLE_LEFT = 610;
|
||||
public static final int TURNTABLE_TABLE_LEFT_LEFT = 611;
|
||||
public static final int TURNTABLE_TABLE_LEFT_RIGHT = 612;
|
||||
public static final int TURNTABLE_TABLE_RIGHT = 613;
|
||||
public static final int TURNTABLE_TABLE_RIGHT_LEFT = 614;
|
||||
public static final int TURNTABLE_TABLE_RIGHT_RIGHT = 615;
|
||||
public static final int TURNTABLE_STICK = 616;
|
||||
public static final int TURNTABLE_STICK_UP = 617;
|
||||
public static final int TURNTABLE_STICK_DOWN = 618;
|
||||
public static final int TURNTABLE_STICK_LEFT = 619;
|
||||
public static final int TURNTABLE_STICK_RIGHT = 620;
|
||||
public static final int TURNTABLE_EFFECT_DIAL = 621;
|
||||
public static final int TURNTABLE_CROSSFADE = 622;
|
||||
public static final int TURNTABLE_CROSSFADE_LEFT = 623;
|
||||
public static final int TURNTABLE_CROSSFADE_RIGHT = 624;
|
||||
}
|
||||
|
||||
/**
|
||||
* Button states
|
||||
*/
|
||||
public static final class ButtonState
|
||||
{
|
||||
public static final int RELEASED = 0;
|
||||
public static final int PRESSED = 1;
|
||||
}
|
||||
/**
|
||||
* Button states
|
||||
*/
|
||||
public static final class ButtonState
|
||||
{
|
||||
public static final int RELEASED = 0;
|
||||
public static final int PRESSED = 1;
|
||||
}
|
||||
|
||||
private NativeLibrary()
|
||||
{
|
||||
// Disallows instantiation.
|
||||
}
|
||||
private NativeLibrary()
|
||||
{
|
||||
// Disallows instantiation.
|
||||
}
|
||||
|
||||
/**
|
||||
* Default touchscreen device
|
||||
*/
|
||||
public static final String TouchScreenDevice = "Touchscreen";
|
||||
/**
|
||||
* Default touchscreen device
|
||||
*/
|
||||
public static final String TouchScreenDevice = "Touchscreen";
|
||||
|
||||
/**
|
||||
* Handles button press events for a gamepad.
|
||||
*
|
||||
* @param Device The input descriptor of the gamepad.
|
||||
* @param Button Key code identifying which button was pressed.
|
||||
* @param Action Mask identifying which action is happening (button pressed down, or button released).
|
||||
*
|
||||
* @return If we handled the button press.
|
||||
*/
|
||||
public static native boolean onGamePadEvent(String Device, int Button, int Action);
|
||||
/**
|
||||
* Handles button press events for a gamepad.
|
||||
*
|
||||
* @param Device The input descriptor of the gamepad.
|
||||
* @param Button Key code identifying which button was pressed.
|
||||
* @param Action Mask identifying which action is happening (button pressed down, or button released).
|
||||
* @return If we handled the button press.
|
||||
*/
|
||||
public static native boolean onGamePadEvent(String Device, int Button, int Action);
|
||||
|
||||
/**
|
||||
* Handles gamepad movement events.
|
||||
*
|
||||
* @param Device The device ID of the gamepad.
|
||||
* @param Axis The axis ID
|
||||
* @param Value The value of the axis represented by the given ID.
|
||||
*/
|
||||
public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
|
||||
/**
|
||||
* Handles gamepad movement events.
|
||||
*
|
||||
* @param Device The device ID of the gamepad.
|
||||
* @param Axis The axis ID
|
||||
* @param Value The value of the axis represented by the given ID.
|
||||
*/
|
||||
public static native void onGamePadMoveEvent(String Device, int Axis, float Value);
|
||||
|
||||
public static native String GetUserSetting(String gameID, String Section, String Key);
|
||||
public static native String GetUserSetting(String gameID, String Section, String Key);
|
||||
|
||||
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
|
||||
public static native void SetUserSetting(String gameID, String Section, String Key, String Value);
|
||||
|
||||
public static native void InitGameIni(String gameID);
|
||||
public static native void InitGameIni(String gameID);
|
||||
|
||||
/**
|
||||
* Gets a value from a key in the given ini-based config file.
|
||||
*
|
||||
* @param configFile The ini-based config file to get the value from.
|
||||
* @param Section The section key that the actual key is in.
|
||||
* @param Key The key to get the value from.
|
||||
* @param Default The value to return in the event the given key doesn't exist.
|
||||
*
|
||||
* @return the value stored at the key, or a default value if it doesn't exist.
|
||||
*/
|
||||
public static native String GetConfig(String configFile, String Section, String Key, String Default);
|
||||
/**
|
||||
* Gets a value from a key in the given ini-based config file.
|
||||
*
|
||||
* @param configFile The ini-based config file to get the value from.
|
||||
* @param Section The section key that the actual key is in.
|
||||
* @param Key The key to get the value from.
|
||||
* @param Default The value to return in the event the given key doesn't exist.
|
||||
* @return the value stored at the key, or a default value if it doesn't exist.
|
||||
*/
|
||||
public static native String GetConfig(String configFile, String Section, String Key,
|
||||
String Default);
|
||||
|
||||
/**
|
||||
* Sets a value to a key in the given ini config file.
|
||||
*
|
||||
* @param configFile The ini-based config file to add the value to.
|
||||
* @param Section The section key for the ini key
|
||||
* @param Key The actual ini key to set.
|
||||
* @param Value The string to set the ini key to.
|
||||
*/
|
||||
public static native void SetConfig(String configFile, String Section, String Key, String Value);
|
||||
/**
|
||||
* Sets a value to a key in the given ini config file.
|
||||
*
|
||||
* @param configFile The ini-based config file to add the value to.
|
||||
* @param Section The section key for the ini key
|
||||
* @param Key The actual ini key to set.
|
||||
* @param Value The string to set the ini key to.
|
||||
*/
|
||||
public static native void SetConfig(String configFile, String Section, String Key, String Value);
|
||||
|
||||
/**
|
||||
* Gets the Dolphin version string.
|
||||
*
|
||||
* @return the Dolphin version string.
|
||||
*/
|
||||
public static native String GetVersionString();
|
||||
/**
|
||||
* Gets the Dolphin version string.
|
||||
*
|
||||
* @return the Dolphin version string.
|
||||
*/
|
||||
public static native String GetVersionString();
|
||||
|
||||
public static native String GetGitRevision();
|
||||
public static native String GetGitRevision();
|
||||
|
||||
/**
|
||||
* Saves a screen capture of the game
|
||||
*/
|
||||
public static native void SaveScreenShot();
|
||||
/**
|
||||
* Saves a screen capture of the game
|
||||
*/
|
||||
public static native void SaveScreenShot();
|
||||
|
||||
/**
|
||||
* Saves a game state to the slot number.
|
||||
*
|
||||
* @param slot The slot location to save state to.
|
||||
* @param wait If false, returns as early as possible.
|
||||
* If true, returns once the savestate has been written to disk.
|
||||
*/
|
||||
public static native void SaveState(int slot, boolean wait);
|
||||
/**
|
||||
* Saves a game state to the slot number.
|
||||
*
|
||||
* @param slot The slot location to save state to.
|
||||
* @param wait If false, returns as early as possible.
|
||||
* If true, returns once the savestate has been written to disk.
|
||||
*/
|
||||
public static native void SaveState(int slot, boolean wait);
|
||||
|
||||
/**
|
||||
* Saves a game state to the specified path.
|
||||
*
|
||||
* @param path The path to save state to.
|
||||
* @param wait If false, returns as early as possible.
|
||||
* If true, returns once the savestate has been written to disk.
|
||||
*/
|
||||
public static native void SaveStateAs(String path, boolean wait);
|
||||
/**
|
||||
* Saves a game state to the specified path.
|
||||
*
|
||||
* @param path The path to save state to.
|
||||
* @param wait If false, returns as early as possible.
|
||||
* If true, returns once the savestate has been written to disk.
|
||||
*/
|
||||
public static native void SaveStateAs(String path, boolean wait);
|
||||
|
||||
/**
|
||||
* Loads a game state from the slot number.
|
||||
*
|
||||
* @param slot The slot location to load state from.
|
||||
*/
|
||||
public static native void LoadState(int slot);
|
||||
/**
|
||||
* Loads a game state from the slot number.
|
||||
*
|
||||
* @param slot The slot location to load state from.
|
||||
*/
|
||||
public static native void LoadState(int slot);
|
||||
|
||||
/**
|
||||
* Loads a game state from the specified path.
|
||||
*
|
||||
* @param path The path to load state from.
|
||||
*/
|
||||
public static native void LoadStateAs(String path);
|
||||
/**
|
||||
* Loads a game state from the specified path.
|
||||
*
|
||||
* @param path The path to load state from.
|
||||
*/
|
||||
public static native void LoadStateAs(String path);
|
||||
|
||||
/**
|
||||
* Sets the current working user directory
|
||||
* If not set, it auto-detects a location
|
||||
*/
|
||||
public static native void SetUserDirectory(String directory);
|
||||
/**
|
||||
* Sets the current working user directory
|
||||
* If not set, it auto-detects a location
|
||||
*/
|
||||
public static native void SetUserDirectory(String directory);
|
||||
|
||||
/**
|
||||
* Returns the current working user directory
|
||||
*/
|
||||
public static native String GetUserDirectory();
|
||||
/**
|
||||
* Returns the current working user directory
|
||||
*/
|
||||
public static native String GetUserDirectory();
|
||||
|
||||
public static native int DefaultCPUCore();
|
||||
public static native int DefaultCPUCore();
|
||||
|
||||
/**
|
||||
* Begins emulation.
|
||||
*/
|
||||
public static native void Run(String path, boolean firstOpen);
|
||||
/**
|
||||
* Begins emulation.
|
||||
*/
|
||||
public static native void Run(String path, boolean firstOpen);
|
||||
|
||||
/**
|
||||
* Begins emulation from the specified savestate.
|
||||
*/
|
||||
public static native void Run(String path, String savestatePath, boolean deleteSavestate);
|
||||
/**
|
||||
* Begins emulation from the specified savestate.
|
||||
*/
|
||||
public static native void Run(String path, String savestatePath, boolean deleteSavestate);
|
||||
|
||||
public static native void ChangeDisc(String path);
|
||||
public static native void ChangeDisc(String path);
|
||||
|
||||
// Surface Handling
|
||||
public static native void SurfaceChanged(Surface surf);
|
||||
public static native void SurfaceDestroyed();
|
||||
// Surface Handling
|
||||
public static native void SurfaceChanged(Surface surf);
|
||||
|
||||
/** Unpauses emulation from a paused state. */
|
||||
public static native void UnPauseEmulation();
|
||||
public static native void SurfaceDestroyed();
|
||||
|
||||
/** Pauses emulation. */
|
||||
public static native void PauseEmulation();
|
||||
/**
|
||||
* Unpauses emulation from a paused state.
|
||||
*/
|
||||
public static native void UnPauseEmulation();
|
||||
|
||||
/** Stops emulation. */
|
||||
public static native void StopEmulation();
|
||||
/**
|
||||
* Pauses emulation.
|
||||
*/
|
||||
public static native void PauseEmulation();
|
||||
|
||||
/** Returns true if emulation is running (or is paused). */
|
||||
public static native boolean IsRunning();
|
||||
/**
|
||||
* Stops emulation.
|
||||
*/
|
||||
public static native void StopEmulation();
|
||||
|
||||
/**
|
||||
* Enables or disables CPU block profiling
|
||||
* @param enable
|
||||
*/
|
||||
public static native void SetProfiling(boolean enable);
|
||||
/**
|
||||
* Returns true if emulation is running (or is paused).
|
||||
*/
|
||||
public static native boolean IsRunning();
|
||||
|
||||
/**
|
||||
* Writes out the block profile results
|
||||
*/
|
||||
public static native void WriteProfileResults();
|
||||
/**
|
||||
* Enables or disables CPU block profiling
|
||||
*
|
||||
* @param enable
|
||||
*/
|
||||
public static native void SetProfiling(boolean enable);
|
||||
|
||||
/** Native EGL functions not exposed by Java bindings **/
|
||||
public static native void eglBindAPI(int api);
|
||||
/**
|
||||
* Writes out the block profile results
|
||||
*/
|
||||
public static native void WriteProfileResults();
|
||||
|
||||
/**
|
||||
* Provides a way to refresh the connections on Wiimotes
|
||||
*/
|
||||
public static native void RefreshWiimotes();
|
||||
/**
|
||||
* Native EGL functions not exposed by Java bindings
|
||||
**/
|
||||
public static native void eglBindAPI(int api);
|
||||
|
||||
private static boolean alertResult = false;
|
||||
public static boolean displayAlertMsg(final String caption, final String text, final boolean yesNo)
|
||||
{
|
||||
Log.error("[NativeLibrary] Alert: " + text);
|
||||
final EmulationActivity emulationActivity = sEmulationActivity.get();
|
||||
boolean result = false;
|
||||
if (emulationActivity == null)
|
||||
{
|
||||
Log.warning("[NativeLibrary] EmulationActivity is null, can't do panic alert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create object used for waiting.
|
||||
final Object lock = new Object();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(emulationActivity)
|
||||
.setTitle(caption)
|
||||
.setMessage(text);
|
||||
/**
|
||||
* Provides a way to refresh the connections on Wiimotes
|
||||
*/
|
||||
public static native void RefreshWiimotes();
|
||||
|
||||
// If not yes/no dialog just have one button that dismisses modal,
|
||||
// otherwise have a yes and no button that sets alertResult accordingly.
|
||||
if (!yesNo)
|
||||
{
|
||||
builder
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("OK", (dialog, whichButton) ->
|
||||
{
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
alertResult = false;
|
||||
private static boolean alertResult = false;
|
||||
|
||||
builder
|
||||
.setPositiveButton("Yes", (dialog, whichButton) ->
|
||||
{
|
||||
alertResult = true;
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("No", (dialog, whichButton) ->
|
||||
{
|
||||
alertResult = false;
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
});
|
||||
}
|
||||
public static boolean displayAlertMsg(final String caption, final String text,
|
||||
final boolean yesNo)
|
||||
{
|
||||
Log.error("[NativeLibrary] Alert: " + text);
|
||||
final EmulationActivity emulationActivity = sEmulationActivity.get();
|
||||
boolean result = false;
|
||||
if (emulationActivity == null)
|
||||
{
|
||||
Log.warning("[NativeLibrary] EmulationActivity is null, can't do panic alert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create object used for waiting.
|
||||
final Object lock = new Object();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(emulationActivity)
|
||||
.setTitle(caption)
|
||||
.setMessage(text);
|
||||
|
||||
// Show the AlertDialog on the main thread.
|
||||
emulationActivity.runOnUiThread(() -> builder.show());
|
||||
// If not yes/no dialog just have one button that dismisses modal,
|
||||
// otherwise have a yes and no button that sets alertResult accordingly.
|
||||
if (!yesNo)
|
||||
{
|
||||
builder
|
||||
.setCancelable(false)
|
||||
.setPositiveButton("OK", (dialog, whichButton) ->
|
||||
{
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
alertResult = false;
|
||||
|
||||
// Wait for the lock to notify that it is complete.
|
||||
synchronized (lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock.wait();
|
||||
}
|
||||
catch (Exception e) { }
|
||||
}
|
||||
builder
|
||||
.setPositiveButton("Yes", (dialog, whichButton) ->
|
||||
{
|
||||
alertResult = true;
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
})
|
||||
.setNegativeButton("No", (dialog, whichButton) ->
|
||||
{
|
||||
alertResult = false;
|
||||
dialog.dismiss();
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notify();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (yesNo)
|
||||
result = alertResult;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// Show the AlertDialog on the main thread.
|
||||
emulationActivity.runOnUiThread(() -> builder.show());
|
||||
|
||||
public static void setEmulationActivity(EmulationActivity emulationActivity)
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
||||
sEmulationActivity = new WeakReference<>(emulationActivity);
|
||||
}
|
||||
// Wait for the lock to notify that it is complete.
|
||||
synchronized (lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
lock.wait();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearEmulationActivity()
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Unregistering EmulationActivity.");
|
||||
if (yesNo)
|
||||
result = alertResult;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sEmulationActivity.clear();
|
||||
}
|
||||
public static void setEmulationActivity(EmulationActivity emulationActivity)
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Registering EmulationActivity.");
|
||||
sEmulationActivity = new WeakReference<>(emulationActivity);
|
||||
}
|
||||
|
||||
public static void clearEmulationActivity()
|
||||
{
|
||||
Log.verbose("[NativeLibrary] Unregistering EmulationActivity.");
|
||||
|
||||
sEmulationActivity.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,113 +22,116 @@ import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
|||
*/
|
||||
public class AppLinkActivity extends FragmentActivity
|
||||
{
|
||||
private static final String TAG = "AppLinkActivity";
|
||||
private static final String TAG = "AppLinkActivity";
|
||||
|
||||
private AppLinkHelper.PlayAction playAction;
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
private AppLinkHelper.PlayAction playAction;
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
Intent intent = getIntent();
|
||||
Uri uri = intent.getData();
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
Intent intent = getIntent();
|
||||
Uri uri = intent.getData();
|
||||
|
||||
Log.v(TAG, uri.toString());
|
||||
Log.v(TAG, uri.toString());
|
||||
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
{
|
||||
Log.e(TAG, "Invalid uri " + uri);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
{
|
||||
Log.e(TAG, "Invalid uri " + uri);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
AppLinkHelper.AppLinkAction action = AppLinkHelper.extractAction(uri);
|
||||
switch (action.getAction())
|
||||
{
|
||||
case AppLinkHelper.PLAY:
|
||||
playAction = (AppLinkHelper.PlayAction) action;
|
||||
initResources();
|
||||
break;
|
||||
case AppLinkHelper.BROWSE:
|
||||
browse();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid Action " + action);
|
||||
}
|
||||
}
|
||||
AppLinkHelper.AppLinkAction action = AppLinkHelper.extractAction(uri);
|
||||
switch (action.getAction())
|
||||
{
|
||||
case AppLinkHelper.PLAY:
|
||||
playAction = (AppLinkHelper.PlayAction) action;
|
||||
initResources();
|
||||
break;
|
||||
case AppLinkHelper.BROWSE:
|
||||
browse();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid Action " + action);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Need to init these since they usually occur in the main activity.
|
||||
*/
|
||||
private void initResources()
|
||||
{
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
/**
|
||||
* Need to init these since they usually occur in the main activity.
|
||||
*/
|
||||
private void initResources()
|
||||
{
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
play(playAction);
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState ==
|
||||
DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
play(playAction);
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationService.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
DirectoryInitializationService.startService(this);
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
DirectoryInitializationService.startService(this);
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Action if channel icon is selected
|
||||
*/
|
||||
private void browse()
|
||||
{
|
||||
Intent openApp = new Intent(this, TvMainActivity.class);
|
||||
startActivity(openApp);
|
||||
/**
|
||||
* Action if channel icon is selected
|
||||
*/
|
||||
private void browse()
|
||||
{
|
||||
Intent openApp = new Intent(this, TvMainActivity.class);
|
||||
startActivity(openApp);
|
||||
|
||||
finish();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action if program(game) is selected
|
||||
*/
|
||||
private void play(AppLinkHelper.PlayAction action)
|
||||
{
|
||||
Log.d(TAG, "Playing game "
|
||||
+ action.getGameId()
|
||||
+ " from channel "
|
||||
+ action.getChannelId());
|
||||
/**
|
||||
* Action if program(game) is selected
|
||||
*/
|
||||
private void play(AppLinkHelper.PlayAction action)
|
||||
{
|
||||
Log.d(TAG, "Playing game "
|
||||
+ action.getGameId()
|
||||
+ " from channel "
|
||||
+ action.getChannelId());
|
||||
|
||||
GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
|
||||
if (game == null)
|
||||
Log.e(TAG, "Invalid Game: " + action.getGameId());
|
||||
else
|
||||
startGame(game);
|
||||
finish();
|
||||
}
|
||||
GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
|
||||
if (game == null)
|
||||
Log.e(TAG, "Invalid Game: " + action.getGameId());
|
||||
else
|
||||
startGame(game);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void startGame(GameFile game)
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
EmulationActivity.launch(this, game, -1, null);
|
||||
}
|
||||
private void startGame(GameFile game)
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
EmulationActivity.launch(this, game, -1, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,16 +13,17 @@ import java.io.File;
|
|||
public class CustomFilePickerActivity extends FilePickerActivity
|
||||
|
||||
{
|
||||
@Override
|
||||
protected AbstractFilePickerFragment<File> getFragment(
|
||||
@Nullable final String startPath, final int mode, final boolean allowMultiple,
|
||||
final boolean allowCreateDir, final boolean allowExistingFile,
|
||||
final boolean singleClick)
|
||||
{
|
||||
AbstractFilePickerFragment<File> fragment = new CustomFilePickerFragment();
|
||||
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
|
||||
fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
|
||||
mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
|
||||
return fragment;
|
||||
}
|
||||
@Override
|
||||
protected AbstractFilePickerFragment<File> getFragment(
|
||||
@Nullable final String startPath, final int mode, final boolean allowMultiple,
|
||||
final boolean allowCreateDir, final boolean allowExistingFile,
|
||||
final boolean singleClick)
|
||||
{
|
||||
AbstractFilePickerFragment<File> fragment = new CustomFilePickerFragment();
|
||||
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
|
||||
fragment.setArgs(
|
||||
startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
|
||||
mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
|
||||
return fragment;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,10 +12,10 @@ import android.widget.Toast;
|
|||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.utils.PicassoUtils;
|
||||
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
|
||||
|
||||
|
@ -24,186 +24,195 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
||||
View.OnClickListener,
|
||||
View.OnLongClickListener
|
||||
View.OnClickListener,
|
||||
View.OnLongClickListener
|
||||
{
|
||||
private List<GameFile> mGameFiles;
|
||||
private List<GameFile> mGameFiles;
|
||||
|
||||
/**
|
||||
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
|
||||
* display no data until swapDataSet is called.
|
||||
*/
|
||||
public GameAdapter()
|
||||
{
|
||||
mGameFiles = new ArrayList<>();
|
||||
}
|
||||
/**
|
||||
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
|
||||
* display no data until swapDataSet is called.
|
||||
*/
|
||||
public GameAdapter()
|
||||
{
|
||||
mGameFiles = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager when it is necessary to create a new view.
|
||||
*
|
||||
* @param parent The RecyclerView (I think?) the created view will be thrown into.
|
||||
* @param viewType Not used here, but useful when more than one type of child will be used in the RecyclerView.
|
||||
* @return The created ViewHolder with references to all the child view's members.
|
||||
*/
|
||||
@Override
|
||||
public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
// Create a new view.
|
||||
View gameCard = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.card_game, parent, false);
|
||||
/**
|
||||
* Called by the LayoutManager when it is necessary to create a new view.
|
||||
*
|
||||
* @param parent The RecyclerView (I think?) the created view will be thrown into.
|
||||
* @param viewType Not used here, but useful when more than one type of child will be used in the RecyclerView.
|
||||
* @return The created ViewHolder with references to all the child view's members.
|
||||
*/
|
||||
@Override
|
||||
public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
// Create a new view.
|
||||
View gameCard = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.card_game, parent, false);
|
||||
|
||||
gameCard.setOnClickListener(this);
|
||||
gameCard.setOnLongClickListener(this);
|
||||
gameCard.setOnClickListener(this);
|
||||
gameCard.setOnLongClickListener(this);
|
||||
|
||||
// Use that view to create a ViewHolder.
|
||||
return new GameViewHolder(gameCard);
|
||||
}
|
||||
// Use that view to create a ViewHolder.
|
||||
return new GameViewHolder(gameCard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager when a new view is not necessary because we can recycle
|
||||
* an existing one (for example, if a view just scrolled onto the screen from the bottom, we
|
||||
* can use the view that just scrolled off the top instead of inflating a new one.)
|
||||
*
|
||||
* @param holder A ViewHolder representing the view we're recycling.
|
||||
* @param position The position of the 'new' view in the dataset.
|
||||
*/
|
||||
@Override
|
||||
public void onBindViewHolder(GameViewHolder holder, int position)
|
||||
{
|
||||
GameFile gameFile = mGameFiles.get(position);
|
||||
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
|
||||
/**
|
||||
* Called by the LayoutManager when a new view is not necessary because we can recycle
|
||||
* an existing one (for example, if a view just scrolled onto the screen from the bottom, we
|
||||
* can use the view that just scrolled off the top instead of inflating a new one.)
|
||||
*
|
||||
* @param holder A ViewHolder representing the view we're recycling.
|
||||
* @param position The position of the 'new' view in the dataset.
|
||||
*/
|
||||
@Override
|
||||
public void onBindViewHolder(GameViewHolder holder, int position)
|
||||
{
|
||||
GameFile gameFile = mGameFiles.get(position);
|
||||
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
|
||||
|
||||
holder.textGameTitle.setText(gameFile.getTitle());
|
||||
holder.textCompany.setText(gameFile.getCompany());
|
||||
holder.textGameTitle.setText(gameFile.getTitle());
|
||||
holder.textCompany.setText(gameFile.getCompany());
|
||||
|
||||
holder.gameFile = gameFile;
|
||||
}
|
||||
holder.gameFile = gameFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager to find out how much data we have.
|
||||
*
|
||||
* @return Size of the dataset.
|
||||
*/
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return mGameFiles.size();
|
||||
}
|
||||
/**
|
||||
* Called by the LayoutManager to find out how much data we have.
|
||||
*
|
||||
* @return Size of the dataset.
|
||||
*/
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return mGameFiles.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell Android whether or not each item in the dataset has a stable identifier.
|
||||
*
|
||||
* @param hasStableIds ignored.
|
||||
*/
|
||||
@Override
|
||||
public void setHasStableIds(boolean hasStableIds)
|
||||
{
|
||||
super.setHasStableIds(false);
|
||||
}
|
||||
/**
|
||||
* Tell Android whether or not each item in the dataset has a stable identifier.
|
||||
*
|
||||
* @param hasStableIds ignored.
|
||||
*/
|
||||
@Override
|
||||
public void setHasStableIds(boolean hasStableIds)
|
||||
{
|
||||
super.setHasStableIds(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a load is finished, call this to replace the existing data
|
||||
* with the newly-loaded data.
|
||||
*/
|
||||
public void swapDataSet(List<GameFile> gameFiles)
|
||||
{
|
||||
mGameFiles = gameFiles;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
/**
|
||||
* When a load is finished, call this to replace the existing data
|
||||
* with the newly-loaded data.
|
||||
*/
|
||||
public void swapDataSet(List<GameFile> gameFiles)
|
||||
{
|
||||
mGameFiles = gameFiles;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the game that was clicked on.
|
||||
*
|
||||
* @param view The card representing the game the user wants to play.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
/**
|
||||
* Launches the game that was clicked on.
|
||||
*
|
||||
* @param view The card representing the game the user wants to play.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
|
||||
EmulationActivity.launch((FragmentActivity) view.getContext(),
|
||||
holder.gameFile,
|
||||
holder.getAdapterPosition(),
|
||||
holder.imageScreenshot);
|
||||
}
|
||||
EmulationActivity.launch((FragmentActivity) view.getContext(),
|
||||
holder.gameFile,
|
||||
holder.getAdapterPosition(),
|
||||
holder.imageScreenshot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the details activity for this Game, using an ID stored in the
|
||||
* details button's Tag.
|
||||
*
|
||||
* @param view The Card button that was long-clicked.
|
||||
*/
|
||||
@Override
|
||||
public boolean onLongClick(View view)
|
||||
{
|
||||
FragmentActivity activity = (FragmentActivity) view.getContext();
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
String gameId = holder.gameFile.getGameId();
|
||||
/**
|
||||
* Launches the details activity for this Game, using an ID stored in the
|
||||
* details button's Tag.
|
||||
*
|
||||
* @param view The Card button that was long-clicked.
|
||||
*/
|
||||
@Override
|
||||
public boolean onLongClick(View view)
|
||||
{
|
||||
FragmentActivity activity = (FragmentActivity) view.getContext();
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
String gameId = holder.gameFile.getGameId();
|
||||
|
||||
if (gameId.isEmpty())
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings");
|
||||
builder.setMessage("Files without game IDs don't support game-specific settings.");
|
||||
if (gameId.isEmpty())
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings");
|
||||
builder.setMessage("Files without game IDs don't support game-specific settings.");
|
||||
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings")
|
||||
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case 0:
|
||||
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
|
||||
break;
|
||||
case 1:
|
||||
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
|
||||
break;
|
||||
case 2:
|
||||
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini";
|
||||
File gameSettingsFile = new File(path);
|
||||
if (gameSettingsFile.exists())
|
||||
{
|
||||
if (gameSettingsFile.delete())
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Cleared settings for " + gameId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings")
|
||||
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
|
||||
break;
|
||||
case 1:
|
||||
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
|
||||
break;
|
||||
case 2:
|
||||
String path =
|
||||
DirectoryInitializationService.getUserDirectory() + "/GameSettings/" +
|
||||
gameId + ".ini";
|
||||
File gameSettingsFile = new File(path);
|
||||
if (gameSettingsFile.exists())
|
||||
{
|
||||
if (gameSettingsFile.delete())
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Cleared settings for " + gameId,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "No game settings to delete",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
|
||||
{
|
||||
private int space;
|
||||
public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
|
||||
{
|
||||
private int space;
|
||||
|
||||
public SpacesItemDecoration(int space)
|
||||
{
|
||||
this.space = space;
|
||||
}
|
||||
public SpacesItemDecoration(int space)
|
||||
{
|
||||
this.space = space;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
|
||||
{
|
||||
outRect.left = space;
|
||||
outRect.right = space;
|
||||
outRect.bottom = space;
|
||||
outRect.top = space;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
||||
RecyclerView.State state)
|
||||
{
|
||||
outRect.left = space;
|
||||
outRect.right = space;
|
||||
outRect.bottom = space;
|
||||
outRect.top = space;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,11 +14,11 @@ import android.widget.ImageView;
|
|||
import android.widget.Toast;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.utils.PicassoUtils;
|
||||
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
|
||||
|
||||
|
@ -30,117 +30,126 @@ import java.io.File;
|
|||
*/
|
||||
public final class GameRowPresenter extends Presenter
|
||||
{
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent)
|
||||
{
|
||||
// Create a new view.
|
||||
ImageCardView gameCard = new ImageCardView(parent.getContext());
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent)
|
||||
{
|
||||
// Create a new view.
|
||||
ImageCardView gameCard = new ImageCardView(parent.getContext());
|
||||
|
||||
gameCard.setMainImageAdjustViewBounds(true);
|
||||
gameCard.setMainImageDimensions(240, 336);
|
||||
gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
gameCard.setMainImageAdjustViewBounds(true);
|
||||
gameCard.setMainImageDimensions(240, 336);
|
||||
gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
|
||||
gameCard.setFocusable(true);
|
||||
gameCard.setFocusableInTouchMode(true);
|
||||
gameCard.setFocusable(true);
|
||||
gameCard.setFocusableInTouchMode(true);
|
||||
|
||||
// Use that view to create a ViewHolder.
|
||||
return new TvGameViewHolder(gameCard);
|
||||
}
|
||||
// Use that view to create a ViewHolder.
|
||||
return new TvGameViewHolder(gameCard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder viewHolder, Object item)
|
||||
{
|
||||
TvGameViewHolder holder = (TvGameViewHolder) viewHolder;
|
||||
GameFile gameFile = (GameFile) item;
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder viewHolder, Object item)
|
||||
{
|
||||
TvGameViewHolder holder = (TvGameViewHolder) viewHolder;
|
||||
GameFile gameFile = (GameFile) item;
|
||||
|
||||
holder.imageScreenshot.setImageDrawable(null);
|
||||
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
|
||||
holder.imageScreenshot.setImageDrawable(null);
|
||||
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
|
||||
|
||||
holder.cardParent.setTitleText(gameFile.getTitle());
|
||||
holder.cardParent.setContentText(gameFile.getCompany());
|
||||
holder.cardParent.setTitleText(gameFile.getTitle());
|
||||
holder.cardParent.setContentText(gameFile.getCompany());
|
||||
|
||||
holder.gameFile = gameFile;
|
||||
holder.gameFile = gameFile;
|
||||
|
||||
// Set the platform-dependent background color of the card
|
||||
int backgroundId;
|
||||
switch (Platform.fromNativeInt(gameFile.getPlatform()))
|
||||
{
|
||||
case GAMECUBE:
|
||||
backgroundId = R.drawable.tv_card_background_gamecube;
|
||||
break;
|
||||
case WII:
|
||||
backgroundId = R.drawable.tv_card_background_wii;
|
||||
break;
|
||||
case WIIWARE:
|
||||
backgroundId = R.drawable.tv_card_background_wiiware;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Not reachable.");
|
||||
}
|
||||
Context context = holder.cardParent.getContext();
|
||||
Drawable background = ContextCompat.getDrawable(context, backgroundId);
|
||||
holder.cardParent.setInfoAreaBackground(background);
|
||||
holder.cardParent.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View view)
|
||||
{
|
||||
FragmentActivity activity = (FragmentActivity) view.getContext();
|
||||
String gameId = gameFile.getGameId();
|
||||
// Set the platform-dependent background color of the card
|
||||
int backgroundId;
|
||||
switch (Platform.fromNativeInt(gameFile.getPlatform()))
|
||||
{
|
||||
case GAMECUBE:
|
||||
backgroundId = R.drawable.tv_card_background_gamecube;
|
||||
break;
|
||||
case WII:
|
||||
backgroundId = R.drawable.tv_card_background_wii;
|
||||
break;
|
||||
case WIIWARE:
|
||||
backgroundId = R.drawable.tv_card_background_wiiware;
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Not reachable.");
|
||||
}
|
||||
Context context = holder.cardParent.getContext();
|
||||
Drawable background = ContextCompat.getDrawable(context, backgroundId);
|
||||
holder.cardParent.setInfoAreaBackground(background);
|
||||
holder.cardParent.setOnLongClickListener(new View.OnLongClickListener()
|
||||
{
|
||||
@Override
|
||||
public boolean onLongClick(View view)
|
||||
{
|
||||
FragmentActivity activity = (FragmentActivity) view.getContext();
|
||||
String gameId = gameFile.getGameId();
|
||||
|
||||
if (gameId.isEmpty())
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings");
|
||||
builder.setMessage("Files without game IDs don't support game-specific settings.");
|
||||
if (gameId.isEmpty())
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings");
|
||||
builder.setMessage("Files without game IDs don't support game-specific settings.");
|
||||
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings")
|
||||
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case 0:
|
||||
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
|
||||
break;
|
||||
case 1:
|
||||
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
|
||||
break;
|
||||
case 2:
|
||||
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini";
|
||||
File gameSettingsFile = new File(path);
|
||||
if (gameSettingsFile.exists())
|
||||
{
|
||||
if (gameSettingsFile.delete())
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Cleared settings for " + gameId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Game Settings")
|
||||
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
|
||||
break;
|
||||
case 1:
|
||||
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
|
||||
break;
|
||||
case 2:
|
||||
String path = DirectoryInitializationService.getUserDirectory() +
|
||||
"/GameSettings/" + gameId + ".ini";
|
||||
File gameSettingsFile = new File(path);
|
||||
if (gameSettingsFile.exists())
|
||||
{
|
||||
if (gameSettingsFile.delete())
|
||||
{
|
||||
Toast.makeText(view.getContext(), "Cleared settings for " + gameId,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(),
|
||||
"Unable to clear settings for " + gameId, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(view.getContext(), "No game settings to delete",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
builder.show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUnbindViewHolder(ViewHolder viewHolder)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
@Override
|
||||
public void onUnbindViewHolder(ViewHolder viewHolder)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ package org.dolphinemu.dolphinemu.adapters;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ImageSpan;
|
||||
|
@ -15,48 +15,48 @@ import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesFragment;
|
|||
|
||||
public class PlatformPagerAdapter extends FragmentPagerAdapter
|
||||
{
|
||||
private Context mContext;
|
||||
private Context mContext;
|
||||
|
||||
private final static int[] TAB_ICONS =
|
||||
{
|
||||
R.drawable.ic_gamecube,
|
||||
R.drawable.ic_wii,
|
||||
R.drawable.ic_folder // WiiWare TODO Have an icon here.
|
||||
};
|
||||
private final static int[] TAB_ICONS =
|
||||
{
|
||||
R.drawable.ic_gamecube,
|
||||
R.drawable.ic_wii,
|
||||
R.drawable.ic_folder // WiiWare TODO Have an icon here.
|
||||
};
|
||||
|
||||
public PlatformPagerAdapter(FragmentManager fm, Context context)
|
||||
{
|
||||
super(fm);
|
||||
mContext = context;
|
||||
}
|
||||
public PlatformPagerAdapter(FragmentManager fm, Context context)
|
||||
{
|
||||
super(fm);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position)
|
||||
{
|
||||
return PlatformGamesFragment.newInstance(Platform.fromPosition(position));
|
||||
}
|
||||
@Override
|
||||
public Fragment getItem(int position)
|
||||
{
|
||||
return PlatformGamesFragment.newInstance(Platform.fromPosition(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
return TAB_ICONS.length;
|
||||
}
|
||||
@Override
|
||||
public int getCount()
|
||||
{
|
||||
return TAB_ICONS.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position)
|
||||
{
|
||||
// Hax from https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout#design-support-library
|
||||
// Apparently a workaround for TabLayout not supporting icons.
|
||||
// TODO This workaround will eventually not be necessary; switch to more legit methods when that is the case
|
||||
// TODO Also remove additional hax from styles.xml
|
||||
Drawable drawable = mContext.getResources().getDrawable(TAB_ICONS[position]);
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position)
|
||||
{
|
||||
// Hax from https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout#design-support-library
|
||||
// Apparently a workaround for TabLayout not supporting icons.
|
||||
// TODO This workaround will eventually not be necessary; switch to more legit methods when that is the case
|
||||
// TODO Also remove additional hax from styles.xml
|
||||
Drawable drawable = mContext.getResources().getDrawable(TAB_ICONS[position]);
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
|
||||
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
|
||||
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
|
||||
|
||||
SpannableString sb = new SpannableString(" ");
|
||||
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
SpannableString sb = new SpannableString(" ");
|
||||
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
return sb;
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,37 +10,37 @@ import org.dolphinemu.dolphinemu.viewholders.TvSettingsViewHolder;
|
|||
|
||||
public final class SettingsRowPresenter extends Presenter
|
||||
{
|
||||
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent)
|
||||
{
|
||||
// Create a new view.
|
||||
ImageCardView settingsCard = new ImageCardView(parent.getContext());
|
||||
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent)
|
||||
{
|
||||
// Create a new view.
|
||||
ImageCardView settingsCard = new ImageCardView(parent.getContext());
|
||||
|
||||
settingsCard.setMainImageAdjustViewBounds(true);
|
||||
settingsCard.setMainImageDimensions(192, 160);
|
||||
settingsCard.setMainImageAdjustViewBounds(true);
|
||||
settingsCard.setMainImageDimensions(192, 160);
|
||||
|
||||
|
||||
settingsCard.setFocusable(true);
|
||||
settingsCard.setFocusableInTouchMode(true);
|
||||
settingsCard.setFocusable(true);
|
||||
settingsCard.setFocusableInTouchMode(true);
|
||||
|
||||
// Use that view to create a ViewHolder.
|
||||
return new TvSettingsViewHolder(settingsCard);
|
||||
}
|
||||
// Use that view to create a ViewHolder.
|
||||
return new TvSettingsViewHolder(settingsCard);
|
||||
}
|
||||
|
||||
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)
|
||||
{
|
||||
TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder;
|
||||
TvSettingsItem settingsItem = (TvSettingsItem) item;
|
||||
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)
|
||||
{
|
||||
TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder;
|
||||
TvSettingsItem settingsItem = (TvSettingsItem) item;
|
||||
|
||||
Resources resources = holder.cardParent.getResources();
|
||||
Resources resources = holder.cardParent.getResources();
|
||||
|
||||
holder.itemId = settingsItem.getItemId();
|
||||
holder.itemId = settingsItem.getItemId();
|
||||
|
||||
holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId()));
|
||||
holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null));
|
||||
}
|
||||
holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId()));
|
||||
holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null));
|
||||
}
|
||||
|
||||
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder)
|
||||
{
|
||||
// no op
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,12 @@ import android.app.Dialog;
|
|||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.dolphinemu.dolphinemu.DolphinApplication;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
|
@ -22,63 +20,64 @@ import de.hdodenhof.circleimageview.CircleImageView;
|
|||
|
||||
public final class GameDetailsDialog extends DialogFragment
|
||||
{
|
||||
private static final String ARG_GAME_PATH = "game_path";
|
||||
private static final String ARG_GAME_PATH = "game_path";
|
||||
|
||||
public static GameDetailsDialog newInstance(String gamePath)
|
||||
{
|
||||
GameDetailsDialog fragment = new GameDetailsDialog();
|
||||
public static GameDetailsDialog newInstance(String gamePath)
|
||||
{
|
||||
GameDetailsDialog fragment = new GameDetailsDialog();
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(ARG_GAME_PATH, gamePath);
|
||||
fragment.setArguments(arguments);
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(ARG_GAME_PATH, gamePath);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
return fragment;
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
GameFile gameFile = GameFileCacheService.addOrGet(getArguments().getString(ARG_GAME_PATH));
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState)
|
||||
{
|
||||
GameFile gameFile = GameFileCacheService.addOrGet(getArguments().getString(ARG_GAME_PATH));
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
ViewGroup contents = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.dialog_game_details, null);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
ViewGroup contents = (ViewGroup) getActivity().getLayoutInflater()
|
||||
.inflate(R.layout.dialog_game_details, null);
|
||||
|
||||
final ImageView imageGameScreen = contents.findViewById(R.id.image_game_screen);
|
||||
CircleImageView circleBanner = contents.findViewById(R.id.circle_banner);
|
||||
final ImageView imageGameScreen = contents.findViewById(R.id.image_game_screen);
|
||||
CircleImageView circleBanner = contents.findViewById(R.id.circle_banner);
|
||||
|
||||
TextView textTitle = contents.findViewById(R.id.text_game_title);
|
||||
TextView textDescription = contents.findViewById(R.id.text_description);
|
||||
TextView textTitle = contents.findViewById(R.id.text_game_title);
|
||||
TextView textDescription = contents.findViewById(R.id.text_description);
|
||||
|
||||
TextView textCountry = contents.findViewById(R.id.text_country);
|
||||
TextView textCompany = contents.findViewById(R.id.text_company);
|
||||
TextView textCountry = contents.findViewById(R.id.text_country);
|
||||
TextView textCompany = contents.findViewById(R.id.text_company);
|
||||
|
||||
FloatingActionButton buttonLaunch = contents.findViewById(R.id.button_launch);
|
||||
FloatingActionButton buttonLaunch = contents.findViewById(R.id.button_launch);
|
||||
|
||||
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
|
||||
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
|
||||
|
||||
textTitle.setText(gameFile.getTitle());
|
||||
textDescription.setText(gameFile.getDescription());
|
||||
textCountry.setText(country);
|
||||
textCompany.setText(gameFile.getCompany());
|
||||
textTitle.setText(gameFile.getTitle());
|
||||
textDescription.setText(gameFile.getDescription());
|
||||
textCountry.setText(country);
|
||||
textCompany.setText(gameFile.getCompany());
|
||||
|
||||
buttonLaunch.setOnClickListener(view ->
|
||||
{
|
||||
// Start the emulation activity and send the path of the clicked ROM to it.
|
||||
EmulationActivity.launch(getActivity(), gameFile, -1, imageGameScreen);
|
||||
});
|
||||
buttonLaunch.setOnClickListener(view ->
|
||||
{
|
||||
// Start the emulation activity and send the path of the clicked ROM to it.
|
||||
EmulationActivity.launch(getActivity(), gameFile, -1, imageGameScreen);
|
||||
});
|
||||
|
||||
// Fill in the view contents.
|
||||
Picasso.with(imageGameScreen.getContext())
|
||||
.load(getArguments().getString(gameFile.getScreenshotPath()))
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.into(imageGameScreen);
|
||||
// Fill in the view contents.
|
||||
Picasso.with(imageGameScreen.getContext())
|
||||
.load(getArguments().getString(gameFile.getScreenshotPath()))
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.into(imageGameScreen);
|
||||
|
||||
circleBanner.setImageResource(R.drawable.no_banner);
|
||||
circleBanner.setImageResource(R.drawable.no_banner);
|
||||
|
||||
builder.setView(contents);
|
||||
return builder.create();
|
||||
}
|
||||
builder.setView(contents);
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,205 +22,209 @@ import java.util.List;
|
|||
*/
|
||||
public final class MotionAlertDialog extends AlertDialog
|
||||
{
|
||||
// The selected input preference
|
||||
private final InputBindingSetting setting;
|
||||
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
|
||||
private int mPrevDeviceId = 0;
|
||||
private boolean mWaitingForEvent = true;
|
||||
// The selected input preference
|
||||
private final InputBindingSetting setting;
|
||||
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
|
||||
private int mPrevDeviceId = 0;
|
||||
private boolean mWaitingForEvent = true;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context The current {@link Context}.
|
||||
* @param setting The Preference to show this dialog for.
|
||||
*/
|
||||
public MotionAlertDialog(Context context, InputBindingSetting setting)
|
||||
{
|
||||
super(context);
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param context The current {@link Context}.
|
||||
* @param setting The Preference to show this dialog for.
|
||||
*/
|
||||
public MotionAlertDialog(Context context, InputBindingSetting setting)
|
||||
{
|
||||
super(context);
|
||||
|
||||
this.setting = setting;
|
||||
}
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
public boolean onKeyEvent(int keyCode, KeyEvent event)
|
||||
{
|
||||
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
|
||||
switch (event.getAction())
|
||||
{
|
||||
case KeyEvent.ACTION_UP:
|
||||
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
|
||||
{
|
||||
saveKeyInput(event);
|
||||
}
|
||||
// Even if we ignore the key, we still consume it. Thus return true regardless.
|
||||
return true;
|
||||
public boolean onKeyEvent(int keyCode, KeyEvent event)
|
||||
{
|
||||
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
|
||||
switch (event.getAction())
|
||||
{
|
||||
case KeyEvent.ACTION_UP:
|
||||
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
|
||||
{
|
||||
saveKeyInput(event);
|
||||
}
|
||||
// Even if we ignore the key, we still consume it. Thus return true regardless.
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event)
|
||||
{
|
||||
// Option to clear by long back is only needed on the TV interface
|
||||
if (TvUtil.isLeanback(getContext()))
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
clearBinding();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event)
|
||||
{
|
||||
// Option to clear by long back is only needed on the TV interface
|
||||
if (TvUtil.isLeanback(getContext()))
|
||||
{
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK)
|
||||
{
|
||||
clearBinding();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyLongPress(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
// Handle this key if we care about it, otherwise pass it down the framework
|
||||
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
|
||||
}
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event)
|
||||
{
|
||||
// Handle this key if we care about it, otherwise pass it down the framework
|
||||
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
// Handle this event if we care about it, otherwise pass it down the framework
|
||||
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
@Override
|
||||
public boolean dispatchGenericMotionEvent(MotionEvent event)
|
||||
{
|
||||
// Handle this event if we care about it, otherwise pass it down the framework
|
||||
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
private boolean onMotionEvent(MotionEvent event)
|
||||
{
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
|
||||
return false;
|
||||
if (event.getAction() != MotionEvent.ACTION_MOVE)
|
||||
return false;
|
||||
private boolean onMotionEvent(MotionEvent event)
|
||||
{
|
||||
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
|
||||
return false;
|
||||
if (event.getAction() != MotionEvent.ACTION_MOVE)
|
||||
return false;
|
||||
|
||||
InputDevice input = event.getDevice();
|
||||
InputDevice input = event.getDevice();
|
||||
|
||||
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
|
||||
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
|
||||
|
||||
if (input.getId() != mPrevDeviceId)
|
||||
{
|
||||
mPreviousValues.clear();
|
||||
}
|
||||
mPrevDeviceId = input.getId();
|
||||
boolean firstEvent = mPreviousValues.isEmpty();
|
||||
if (input.getId() != mPrevDeviceId)
|
||||
{
|
||||
mPreviousValues.clear();
|
||||
}
|
||||
mPrevDeviceId = input.getId();
|
||||
boolean firstEvent = mPreviousValues.isEmpty();
|
||||
|
||||
int numMovedAxis = 0;
|
||||
float axisMoveValue = 0.0f;
|
||||
InputDevice.MotionRange lastMovedRange = null;
|
||||
char lastMovedDir = '?';
|
||||
if (mWaitingForEvent)
|
||||
{
|
||||
for (int i = 0; i < motionRanges.size(); i++)
|
||||
{
|
||||
InputDevice.MotionRange range = motionRanges.get(i);
|
||||
int axis = range.getAxis();
|
||||
float origValue = event.getAxisValue(axis);
|
||||
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
|
||||
if (firstEvent)
|
||||
{
|
||||
mPreviousValues.add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
float previousValue = mPreviousValues.get(i);
|
||||
int numMovedAxis = 0;
|
||||
float axisMoveValue = 0.0f;
|
||||
InputDevice.MotionRange lastMovedRange = null;
|
||||
char lastMovedDir = '?';
|
||||
if (mWaitingForEvent)
|
||||
{
|
||||
for (int i = 0; i < motionRanges.size(); i++)
|
||||
{
|
||||
InputDevice.MotionRange range = motionRanges.get(i);
|
||||
int axis = range.getAxis();
|
||||
float origValue = event.getAxisValue(axis);
|
||||
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
|
||||
if (firstEvent)
|
||||
{
|
||||
mPreviousValues.add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
float previousValue = mPreviousValues.get(i);
|
||||
|
||||
// Only handle the axes that are not neutral (more than 0.5)
|
||||
// but ignore any axis that has a constant value (e.g. always 1)
|
||||
if (Math.abs(value) > 0.5f && value != previousValue)
|
||||
{
|
||||
// It is common to have multiple axes with the same physical input. For example,
|
||||
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
||||
// To handle this, we ignore an axis motion that's the exact same as a motion
|
||||
// we already saw. This way, we ignore axes with two names, but catch the case
|
||||
// where a joystick is moved in two directions.
|
||||
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
||||
if (value != axisMoveValue)
|
||||
{
|
||||
axisMoveValue = value;
|
||||
numMovedAxis++;
|
||||
lastMovedRange = range;
|
||||
lastMovedDir = value < 0.0f ? '-' : '+';
|
||||
}
|
||||
}
|
||||
// Special case for d-pads (axis value jumps between 0 and 1 without any values
|
||||
// in between). Without this, the user would need to press the d-pad twice
|
||||
// due to the first press being caught by the "if (firstEvent)" case further up.
|
||||
else if (Math.abs(value) < 0.25f && Math.abs(previousValue) > 0.75f)
|
||||
{
|
||||
numMovedAxis++;
|
||||
lastMovedRange = range;
|
||||
lastMovedDir = previousValue < 0.0f ? '-' : '+';
|
||||
}
|
||||
}
|
||||
// Only handle the axes that are not neutral (more than 0.5)
|
||||
// but ignore any axis that has a constant value (e.g. always 1)
|
||||
if (Math.abs(value) > 0.5f && value != previousValue)
|
||||
{
|
||||
// It is common to have multiple axes with the same physical input. For example,
|
||||
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
|
||||
// To handle this, we ignore an axis motion that's the exact same as a motion
|
||||
// we already saw. This way, we ignore axes with two names, but catch the case
|
||||
// where a joystick is moved in two directions.
|
||||
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
|
||||
if (value != axisMoveValue)
|
||||
{
|
||||
axisMoveValue = value;
|
||||
numMovedAxis++;
|
||||
lastMovedRange = range;
|
||||
lastMovedDir = value < 0.0f ? '-' : '+';
|
||||
}
|
||||
}
|
||||
// Special case for d-pads (axis value jumps between 0 and 1 without any values
|
||||
// in between). Without this, the user would need to press the d-pad twice
|
||||
// due to the first press being caught by the "if (firstEvent)" case further up.
|
||||
else if (Math.abs(value) < 0.25f && Math.abs(previousValue) > 0.75f)
|
||||
{
|
||||
numMovedAxis++;
|
||||
lastMovedRange = range;
|
||||
lastMovedDir = previousValue < 0.0f ? '-' : '+';
|
||||
}
|
||||
}
|
||||
|
||||
mPreviousValues.set(i, value);
|
||||
}
|
||||
mPreviousValues.set(i, value);
|
||||
}
|
||||
|
||||
// If only one axis moved, that's the winner.
|
||||
if (numMovedAxis == 1)
|
||||
{
|
||||
mWaitingForEvent = false;
|
||||
saveMotionInput(input, lastMovedRange, lastMovedDir);
|
||||
}
|
||||
}
|
||||
// If only one axis moved, that's the winner.
|
||||
if (numMovedAxis == 1)
|
||||
{
|
||||
mWaitingForEvent = false;
|
||||
saveMotionInput(input, lastMovedRange, lastMovedDir);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the provided key input setting both to the INI file (so native code can use it) and as
|
||||
* an Android preference (so it persists correctly and is human-readable.)
|
||||
*
|
||||
* @param keyEvent KeyEvent of this key press.
|
||||
*/
|
||||
private void saveKeyInput(KeyEvent keyEvent)
|
||||
{
|
||||
InputDevice device = keyEvent.getDevice();
|
||||
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
|
||||
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
|
||||
/**
|
||||
* Saves the provided key input setting both to the INI file (so native code can use it) and as
|
||||
* an Android preference (so it persists correctly and is human-readable.)
|
||||
*
|
||||
* @param keyEvent KeyEvent of this key press.
|
||||
*/
|
||||
private void saveKeyInput(KeyEvent keyEvent)
|
||||
{
|
||||
InputDevice device = keyEvent.getDevice();
|
||||
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
|
||||
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
|
||||
|
||||
saveInput(bindStr, uiString);
|
||||
}
|
||||
saveInput(bindStr, uiString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the provided motion input setting both to the INI file (so native code can use it) and as
|
||||
* an Android preference (so it persists correctly and is human-readable.)
|
||||
*
|
||||
* @param device InputDevice from which the input event originated.
|
||||
* @param motionRange MotionRange of the movement
|
||||
* @param axisDir Either '-' or '+'
|
||||
*/
|
||||
private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange, char axisDir)
|
||||
{
|
||||
String bindStr = "Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
|
||||
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
|
||||
/**
|
||||
* Saves the provided motion input setting both to the INI file (so native code can use it) and as
|
||||
* an Android preference (so it persists correctly and is human-readable.)
|
||||
*
|
||||
* @param device InputDevice from which the input event originated.
|
||||
* @param motionRange MotionRange of the movement
|
||||
* @param axisDir Either '-' or '+'
|
||||
*/
|
||||
private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
|
||||
char axisDir)
|
||||
{
|
||||
String bindStr =
|
||||
"Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
|
||||
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
|
||||
|
||||
saveInput(bindStr, uiString);
|
||||
}
|
||||
saveInput(bindStr, uiString);
|
||||
}
|
||||
|
||||
/** Save the input string to settings and SharedPreferences, then dismiss this Dialog. */
|
||||
private void saveInput(String bind, String ui)
|
||||
{
|
||||
setting.setValue(bind);
|
||||
/**
|
||||
* Save the input string to settings and SharedPreferences, then dismiss this Dialog.
|
||||
*/
|
||||
private void saveInput(String bind, String ui)
|
||||
{
|
||||
setting.setValue(bind);
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
editor.putString(setting.getKey(), ui);
|
||||
editor.apply();
|
||||
editor.putString(setting.getKey(), ui);
|
||||
editor.apply();
|
||||
|
||||
dismiss();
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private void clearBinding()
|
||||
{
|
||||
setting.setValue("");
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.remove(setting.getKey());
|
||||
editor.apply();
|
||||
dismiss();
|
||||
}
|
||||
private void clearBinding()
|
||||
{
|
||||
setting.setValue("");
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.remove(setting.getKey());
|
||||
editor.apply();
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
|
|||
|
||||
public final class BooleanSetting extends Setting
|
||||
{
|
||||
private boolean mValue;
|
||||
private boolean mValue;
|
||||
|
||||
public BooleanSetting(String key, String section, boolean value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
public BooleanSetting(String key, String section, boolean value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public boolean getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
public boolean getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(boolean value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
public void setValue(boolean value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return mValue ? "True" : "False";
|
||||
}
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return mValue ? "True" : "False";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
|
|||
|
||||
public final class FloatSetting extends Setting
|
||||
{
|
||||
private float mValue;
|
||||
private float mValue;
|
||||
|
||||
public FloatSetting(String key, String section, float value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
public FloatSetting(String key, String section, float value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public float getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
public float getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(float value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
public void setValue(float value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return Float.toString(mValue);
|
||||
}
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return Float.toString(mValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,41 +4,41 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|||
|
||||
public final class IntSetting extends Setting
|
||||
{
|
||||
private int mValue;
|
||||
private MenuTag menuTag;
|
||||
private int mValue;
|
||||
private MenuTag menuTag;
|
||||
|
||||
public IntSetting(String key, String section, int value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
public IntSetting(String key, String section, int value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public IntSetting(String key, String section, int value, MenuTag menuTag)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
this.menuTag = menuTag;
|
||||
}
|
||||
public IntSetting(String key, String section, int value, MenuTag menuTag)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
this.menuTag = menuTag;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(int value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
public void setValue(int value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return Integer.toString(mValue);
|
||||
}
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return Integer.toString(mValue);
|
||||
}
|
||||
|
||||
public MenuTag getMenuTag()
|
||||
{
|
||||
return menuTag;
|
||||
}
|
||||
public MenuTag getMenuTag()
|
||||
{
|
||||
return menuTag;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,42 +8,40 @@ package org.dolphinemu.dolphinemu.features.settings.model;
|
|||
*/
|
||||
public abstract class Setting
|
||||
{
|
||||
private String mKey;
|
||||
private String mSection;
|
||||
private String mKey;
|
||||
private String mSection;
|
||||
|
||||
/**
|
||||
* Base constructor.
|
||||
*
|
||||
* @param key Everything to the left of the = in a line from the ini file.
|
||||
* @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets.
|
||||
*/
|
||||
public Setting(String key, String section)
|
||||
{
|
||||
mKey = key;
|
||||
mSection = section;
|
||||
}
|
||||
/**
|
||||
* Base constructor.
|
||||
*
|
||||
* @param key Everything to the left of the = in a line from the ini file.
|
||||
* @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets.
|
||||
*/
|
||||
public Setting(String key, String section)
|
||||
{
|
||||
mKey = key;
|
||||
mSection = section;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The identifier used to write this setting to the ini file.
|
||||
*/
|
||||
public String getKey()
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
/**
|
||||
* @return The identifier used to write this setting to the ini file.
|
||||
*/
|
||||
public String getKey()
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The name of the header under which this Setting should be written in the ini file.
|
||||
*/
|
||||
public String getSection()
|
||||
{
|
||||
return mSection;
|
||||
}
|
||||
/**
|
||||
* @return The name of the header under which this Setting should be written in the ini file.
|
||||
*/
|
||||
public String getSection()
|
||||
{
|
||||
return mSection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return A representation of this Setting's backing value converted to a String (e.g. for serialization).
|
||||
*/
|
||||
public abstract String getValueAsString();
|
||||
/**
|
||||
* @return A representation of this Setting's backing value converted to a String (e.g. for serialization).
|
||||
*/
|
||||
public abstract String getValueAsString();
|
||||
}
|
||||
|
|
|
@ -8,56 +8,56 @@ import java.util.HashMap;
|
|||
*/
|
||||
public final class SettingSection
|
||||
{
|
||||
private String mName;
|
||||
private String mName;
|
||||
|
||||
private HashMap<String, Setting> mSettings = new HashMap<>();
|
||||
private HashMap<String, Setting> mSettings = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new SettingSection with no Settings in it.
|
||||
*
|
||||
* @param name The header of this section; e.g. [Core] or [Enhancements] without the brackets.
|
||||
*/
|
||||
public SettingSection(String name)
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
/**
|
||||
* Create a new SettingSection with no Settings in it.
|
||||
*
|
||||
* @param name The header of this section; e.g. [Core] or [Enhancements] without the brackets.
|
||||
*/
|
||||
public SettingSection(String name)
|
||||
{
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method; inserts a value directly into the backing HashMap.
|
||||
*
|
||||
* @param setting The Setting to be inserted.
|
||||
*/
|
||||
public void putSetting(Setting setting)
|
||||
{
|
||||
mSettings.put(setting.getKey(), setting);
|
||||
}
|
||||
/**
|
||||
* Convenience method; inserts a value directly into the backing HashMap.
|
||||
*
|
||||
* @param setting The Setting to be inserted.
|
||||
*/
|
||||
public void putSetting(Setting setting)
|
||||
{
|
||||
mSettings.put(setting.getKey(), setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method; gets a value directly from the backing HashMap.
|
||||
*
|
||||
* @param key Used to retrieve the Setting.
|
||||
* @return A Setting object (you should probably cast this before using)
|
||||
*/
|
||||
public Setting getSetting(String key)
|
||||
{
|
||||
return mSettings.get(key);
|
||||
}
|
||||
/**
|
||||
* Convenience method; gets a value directly from the backing HashMap.
|
||||
*
|
||||
* @param key Used to retrieve the Setting.
|
||||
* @return A Setting object (you should probably cast this before using)
|
||||
*/
|
||||
public Setting getSetting(String key)
|
||||
{
|
||||
return mSettings.get(key);
|
||||
}
|
||||
|
||||
public HashMap<String, Setting> getSettings()
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
public HashMap<String, Setting> getSettings()
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
public void mergeSection(SettingSection settingSection)
|
||||
{
|
||||
for (Setting setting : settingSection.mSettings.values())
|
||||
{
|
||||
putSetting(setting);
|
||||
}
|
||||
}
|
||||
public void mergeSection(SettingSection settingSection)
|
||||
{
|
||||
for (Setting setting : settingSection.mSettings.values())
|
||||
{
|
||||
putSetting(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,168 +14,174 @@ import java.util.TreeMap;
|
|||
|
||||
public class Settings
|
||||
{
|
||||
public static final String SECTION_INI_CORE = "Core";
|
||||
public static final String SECTION_INI_INTERFACE = "Interface";
|
||||
public static final String SECTION_INI_CORE = "Core";
|
||||
public static final String SECTION_INI_INTERFACE = "Interface";
|
||||
|
||||
public static final String SECTION_GFX_SETTINGS = "Settings";
|
||||
public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
|
||||
public static final String SECTION_GFX_HACKS = "Hacks";
|
||||
public static final String SECTION_GFX_SETTINGS = "Settings";
|
||||
public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
|
||||
public static final String SECTION_GFX_HACKS = "Hacks";
|
||||
|
||||
public static final String SECTION_STEREOSCOPY = "Stereoscopy";
|
||||
public static final String SECTION_STEREOSCOPY = "Stereoscopy";
|
||||
|
||||
public static final String SECTION_WIIMOTE = "Wiimote";
|
||||
public static final String SECTION_WIIMOTE = "Wiimote";
|
||||
|
||||
public static final String SECTION_BINDINGS = "Android";
|
||||
public static final String SECTION_BINDINGS = "Android";
|
||||
|
||||
public static final String SECTION_ANALYTICS = "Analytics";
|
||||
public static final String SECTION_ANALYTICS = "Analytics";
|
||||
|
||||
private String gameId;
|
||||
private String gameId;
|
||||
|
||||
private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
|
||||
private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
|
||||
|
||||
static
|
||||
static
|
||||
{
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN,
|
||||
Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS,
|
||||
SECTION_ANALYTICS));
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX,
|
||||
Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS,
|
||||
SECTION_STEREOSCOPY));
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE,
|
||||
Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3,
|
||||
SECTION_WIIMOTE + 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
{
|
||||
@Override
|
||||
public SettingSection get(Object key)
|
||||
{
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN, Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS, SECTION_ANALYTICS));
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX, Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS, SECTION_STEREOSCOPY));
|
||||
configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE, Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3, SECTION_WIIMOTE + 4));
|
||||
if (!(key instanceof String))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String stringKey = (String) key;
|
||||
|
||||
if (!super.containsKey(stringKey))
|
||||
{
|
||||
SettingSection section = new SettingSection(stringKey);
|
||||
super.put(stringKey, section);
|
||||
return section;
|
||||
}
|
||||
return super.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, SettingSection> sections = new Settings.SettingsSectionMap();
|
||||
|
||||
public SettingSection getSection(String sectionName)
|
||||
{
|
||||
return sections.get(sectionName);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return sections.isEmpty();
|
||||
}
|
||||
|
||||
public HashMap<String, SettingSection> getSections()
|
||||
{
|
||||
return sections;
|
||||
}
|
||||
|
||||
public void loadSettings(SettingsActivityView view)
|
||||
{
|
||||
sections = new Settings.SettingsSectionMap();
|
||||
|
||||
HashSet<String> filesToExclude = new HashSet<>();
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
// for per-game settings, don't load the WiiMoteNew.ini settings
|
||||
filesToExclude.add(SettingsFile.FILE_NAME_WIIMOTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
loadDolphinSettings(view, filesToExclude);
|
||||
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
@Override
|
||||
public SettingSection get(Object key)
|
||||
loadGenericGameSettings(gameId, view);
|
||||
loadCustomGameSettings(gameId, view);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDolphinSettings(SettingsActivityView view, HashSet<String> filesToExclude)
|
||||
{
|
||||
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
|
||||
{
|
||||
String fileName = entry.getKey();
|
||||
if (filesToExclude == null || !filesToExclude.contains(fileName))
|
||||
{
|
||||
sections.putAll(SettingsFile.readFile(fileName, view));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSettings(String gameId, SettingsActivityView view)
|
||||
{
|
||||
this.gameId = gameId;
|
||||
loadSettings(view);
|
||||
}
|
||||
|
||||
public void saveSettings(SettingsActivityView view)
|
||||
{
|
||||
if (TextUtils.isEmpty(gameId))
|
||||
{
|
||||
view.showToastMessage("Saved settings to INI files");
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
|
||||
{
|
||||
String fileName = entry.getKey();
|
||||
List<String> sectionNames = entry.getValue();
|
||||
TreeMap<String, SettingSection> iniSections = new TreeMap<>();
|
||||
for (String section : sectionNames)
|
||||
{
|
||||
if (!(key instanceof String))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String stringKey = (String) key;
|
||||
|
||||
if (!super.containsKey(stringKey))
|
||||
{
|
||||
SettingSection section = new SettingSection(stringKey);
|
||||
super.put(stringKey, section);
|
||||
return section;
|
||||
}
|
||||
return super.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, SettingSection> sections = new Settings.SettingsSectionMap();
|
||||
|
||||
public SettingSection getSection(String sectionName)
|
||||
{
|
||||
return sections.get(sectionName);
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return sections.isEmpty();
|
||||
}
|
||||
|
||||
public HashMap<String, SettingSection> getSections()
|
||||
{
|
||||
return sections;
|
||||
}
|
||||
|
||||
public void loadSettings(SettingsActivityView view)
|
||||
{
|
||||
sections = new Settings.SettingsSectionMap();
|
||||
|
||||
HashSet<String> filesToExclude = new HashSet<>();
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
// for per-game settings, don't load the WiiMoteNew.ini settings
|
||||
filesToExclude.add(SettingsFile.FILE_NAME_WIIMOTE);
|
||||
iniSections.put(section, sections.get(section));
|
||||
}
|
||||
|
||||
loadDolphinSettings(view, filesToExclude);
|
||||
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
loadGenericGameSettings(gameId, view);
|
||||
loadCustomGameSettings(gameId, view);
|
||||
}
|
||||
SettingsFile.saveFile(fileName, iniSections, view);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDolphinSettings(SettingsActivityView view, HashSet<String> filesToExclude)
|
||||
else
|
||||
{
|
||||
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
|
||||
{
|
||||
String fileName = entry.getKey();
|
||||
if(filesToExclude == null || !filesToExclude.contains(fileName))
|
||||
{
|
||||
sections.putAll(SettingsFile.readFile(fileName, view));
|
||||
}
|
||||
}
|
||||
// custom game settings
|
||||
view.showToastMessage("Saved settings for " + gameId);
|
||||
SettingsFile.saveCustomGameSettings(gameId, sections);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadSettings(String gameId, SettingsActivityView view)
|
||||
{
|
||||
this.gameId = gameId;
|
||||
loadSettings(view);
|
||||
}
|
||||
|
||||
public void saveSettings(SettingsActivityView view)
|
||||
{
|
||||
if (TextUtils.isEmpty(gameId))
|
||||
{
|
||||
view.showToastMessage("Saved settings to INI files");
|
||||
|
||||
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.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);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// custom game settings
|
||||
view.showToastMessage("Saved settings for " + gameId);
|
||||
SettingsFile.saveCustomGameSettings(gameId, sections);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
|
|||
|
||||
public final class StringSetting extends Setting
|
||||
{
|
||||
private String mValue;
|
||||
private String mValue;
|
||||
|
||||
public StringSetting(String key, String section, String value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
public StringSetting(String key, String section, String value)
|
||||
{
|
||||
super(key, section);
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
public String getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public void setValue(String value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
public void setValue(String value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
@Override
|
||||
public String getValueAsString()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,51 +5,52 @@ import org.dolphinemu.dolphinemu.features.settings.model.Setting;
|
|||
|
||||
public final class CheckBoxSetting extends SettingsItem
|
||||
{
|
||||
private boolean mDefaultValue;
|
||||
private boolean mDefaultValue;
|
||||
|
||||
public CheckBoxSetting(String key, String section, int titleId, int descriptionId, boolean defaultValue, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
public CheckBoxSetting(String key, String section, int titleId, int descriptionId,
|
||||
boolean defaultValue, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public boolean isChecked()
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
public boolean isChecked()
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
|
||||
BooleanSetting setting = (BooleanSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
BooleanSetting setting = (BooleanSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
BooleanSetting setting = new BooleanSetting(getKey(), getSection(), checked);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
BooleanSetting setting = (BooleanSetting) getSetting();
|
||||
setting.setValue(checked);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
BooleanSetting setting = new BooleanSetting(getKey(), getSection(), checked);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
BooleanSetting setting = (BooleanSetting) getSetting();
|
||||
setting.setValue(checked);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_CHECKBOX;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_CHECKBOX;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@ import org.dolphinemu.dolphinemu.features.settings.model.Setting;
|
|||
|
||||
public final class HeaderSetting extends SettingsItem
|
||||
{
|
||||
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId)
|
||||
{
|
||||
super(key, null, setting, titleId, descriptionId);
|
||||
}
|
||||
public HeaderSetting(String key, Setting setting, int titleId, int descriptionId)
|
||||
{
|
||||
super(key, null, setting, titleId, descriptionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return SettingsItem.TYPE_HEADER;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return SettingsItem.TYPE_HEADER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,48 +5,48 @@ import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
|
|||
|
||||
public final class InputBindingSetting extends SettingsItem
|
||||
{
|
||||
public InputBindingSetting(String key, String section, int titleId, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, 0);
|
||||
}
|
||||
public InputBindingSetting(String key, String section, int titleId, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, 0);
|
||||
}
|
||||
|
||||
public String getValue()
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
public String getValue()
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), bind);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
setting.setValue(bind);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), bind);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
setting.setValue(bind);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_INPUT_BINDING;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_INPUT_BINDING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.dolphinemu.dolphinemu.features.settings.model.view;
|
||||
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.Setting;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
||||
|
||||
/**
|
||||
* ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments.
|
||||
|
@ -12,99 +12,95 @@ import org.dolphinemu.dolphinemu.features.settings.model.Setting;
|
|||
*/
|
||||
public abstract class SettingsItem
|
||||
{
|
||||
public static final int TYPE_HEADER = 0;
|
||||
public static final int TYPE_CHECKBOX = 1;
|
||||
public static final int TYPE_SINGLE_CHOICE = 2;
|
||||
public static final int TYPE_SLIDER = 3;
|
||||
public static final int TYPE_SUBMENU = 4;
|
||||
public static final int TYPE_INPUT_BINDING = 5;
|
||||
public static final int TYPE_STRING_SINGLE_CHOICE = 6;
|
||||
public static final int TYPE_HEADER = 0;
|
||||
public static final int TYPE_CHECKBOX = 1;
|
||||
public static final int TYPE_SINGLE_CHOICE = 2;
|
||||
public static final int TYPE_SLIDER = 3;
|
||||
public static final int TYPE_SUBMENU = 4;
|
||||
public static final int TYPE_INPUT_BINDING = 5;
|
||||
public static final int TYPE_STRING_SINGLE_CHOICE = 6;
|
||||
|
||||
private String mKey;
|
||||
private String mSection;
|
||||
private String mKey;
|
||||
private String mSection;
|
||||
|
||||
private Setting mSetting;
|
||||
private Setting mSetting;
|
||||
|
||||
private int mNameId;
|
||||
private int mDescriptionId;
|
||||
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.
|
||||
*
|
||||
* @param key Identifier for the Setting represented by this Item.
|
||||
* @param section Section to which the Setting belongs.
|
||||
* @param setting A possibly-null backing Setting, to be modified on UI events.
|
||||
* @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)
|
||||
{
|
||||
mKey = key;
|
||||
mSection = section;
|
||||
mSetting = setting;
|
||||
mNameId = nameId;
|
||||
mDescriptionId = descriptionId;
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param key Identifier for the Setting represented by this Item.
|
||||
* @param section Section to which the Setting belongs.
|
||||
* @param setting A possibly-null backing Setting, to be modified on UI events.
|
||||
* @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)
|
||||
{
|
||||
mKey = key;
|
||||
mSection = section;
|
||||
mSetting = setting;
|
||||
mNameId = nameId;
|
||||
mDescriptionId = descriptionId;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The identifier for the backing Setting.
|
||||
*/
|
||||
public String getKey()
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
/**
|
||||
* @return The identifier for the backing Setting.
|
||||
*/
|
||||
public String getKey()
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The header under which the backing Setting belongs.
|
||||
*/
|
||||
public String getSection()
|
||||
{
|
||||
return mSection;
|
||||
}
|
||||
/**
|
||||
* @return The header under which the backing Setting belongs.
|
||||
*/
|
||||
public String getSection()
|
||||
{
|
||||
return mSection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The backing Setting, possibly null.
|
||||
*/
|
||||
public Setting getSetting()
|
||||
{
|
||||
return mSetting;
|
||||
}
|
||||
/**
|
||||
* @return The backing Setting, possibly null.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
mSetting = setting;
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
mSetting = setting;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return A resource ID for a text string representing this Setting's name.
|
||||
*/
|
||||
public int getNameId()
|
||||
{
|
||||
return mNameId;
|
||||
}
|
||||
/**
|
||||
* @return A resource ID for a text string representing this Setting's name.
|
||||
*/
|
||||
public int getNameId()
|
||||
{
|
||||
return mNameId;
|
||||
}
|
||||
|
||||
public int getDescriptionId()
|
||||
{
|
||||
return mDescriptionId;
|
||||
}
|
||||
public int getDescriptionId()
|
||||
{
|
||||
return mDescriptionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link SettingsAdapter}'s onCreateViewHolder()
|
||||
* method to determine which type of ViewHolder should be created.
|
||||
*
|
||||
* @return An integer (ideally, one of the constants defined in this file)
|
||||
*/
|
||||
public abstract int getType();
|
||||
/**
|
||||
* Used by {@link SettingsAdapter}'s onCreateViewHolder()
|
||||
* method to determine which type of ViewHolder should be created.
|
||||
*
|
||||
* @return An integer (ideally, one of the constants defined in this file)
|
||||
*/
|
||||
public abstract int getType();
|
||||
}
|
||||
|
|
|
@ -6,80 +6,82 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|||
|
||||
public final class SingleChoiceSetting extends SettingsItem
|
||||
{
|
||||
private int mDefaultValue;
|
||||
private int mDefaultValue;
|
||||
|
||||
private int mChoicesId;
|
||||
private int mValuesId;
|
||||
private MenuTag menuTag;
|
||||
private int mChoicesId;
|
||||
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)
|
||||
{
|
||||
super(key, section, setting, 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, MenuTag menuTag)
|
||||
{
|
||||
super(key, section, setting, 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)
|
||||
{
|
||||
this(key, section, titleId, descriptionId, choicesId, valuesId, defaultValue, setting, null);
|
||||
}
|
||||
public SingleChoiceSetting(String key, String section, int titleId, int descriptionId,
|
||||
int choicesId, int valuesId, int defaultValue, Setting setting)
|
||||
{
|
||||
this(key, section, titleId, descriptionId, choicesId, valuesId, defaultValue, setting, null);
|
||||
}
|
||||
|
||||
public int getChoicesId()
|
||||
{
|
||||
return mChoicesId;
|
||||
}
|
||||
public int getChoicesId()
|
||||
{
|
||||
return mChoicesId;
|
||||
}
|
||||
|
||||
public int getValuesId()
|
||||
{
|
||||
return mValuesId;
|
||||
}
|
||||
public int getValuesId()
|
||||
{
|
||||
return mValuesId;
|
||||
}
|
||||
|
||||
public int getSelectedValue()
|
||||
{
|
||||
if (getSetting() != null)
|
||||
{
|
||||
IntSetting setting = (IntSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
}
|
||||
public int getSelectedValue()
|
||||
{
|
||||
if (getSetting() != null)
|
||||
{
|
||||
IntSetting setting = (IntSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public MenuTag getMenuTag()
|
||||
{
|
||||
return menuTag;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
IntSetting setting = new IntSetting(getKey(), getSection(), selection);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
IntSetting setting = (IntSetting) getSetting();
|
||||
setting.setValue(selection);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SINGLE_CHOICE;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SINGLE_CHOICE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,117 +3,118 @@ 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.utils.Log;
|
||||
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
||||
public final class SliderSetting extends SettingsItem
|
||||
{
|
||||
private int mMax;
|
||||
private int mDefaultValue;
|
||||
private int mMax;
|
||||
private int mDefaultValue;
|
||||
|
||||
private String mUnits;
|
||||
private String mUnits;
|
||||
|
||||
public SliderSetting(String key, String section, int titleId, int descriptionId, int max, String units, int defaultValue, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mMax = max;
|
||||
mUnits = units;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
public SliderSetting(String key, String section, int titleId, int descriptionId, int max,
|
||||
String units, int defaultValue, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mMax = max;
|
||||
mUnits = units;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public int getMax()
|
||||
{
|
||||
return mMax;
|
||||
}
|
||||
public int getMax()
|
||||
{
|
||||
return mMax;
|
||||
}
|
||||
|
||||
public int getSelectedValue()
|
||||
{
|
||||
Setting setting = getSetting();
|
||||
public int getSelectedValue()
|
||||
{
|
||||
Setting setting = getSetting();
|
||||
|
||||
if (setting == null)
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
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 (floatSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)
|
||||
|| floatSetting.getKey().equals(SettingsFile.KEY_SPEED_LIMIT))
|
||||
{
|
||||
return Math.round(floatSetting.getValue() * 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.round(floatSetting.getValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[SliderSetting] Error casting setting type.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (setting instanceof IntSetting)
|
||||
{
|
||||
IntSetting intSetting = (IntSetting) setting;
|
||||
return intSetting.getValue();
|
||||
}
|
||||
else if (setting instanceof FloatSetting)
|
||||
{
|
||||
FloatSetting floatSetting = (FloatSetting) setting;
|
||||
if (floatSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)
|
||||
|| floatSetting.getKey().equals(SettingsFile.KEY_SPEED_LIMIT))
|
||||
{
|
||||
return Math.round(floatSetting.getValue() * 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Math.round(floatSetting.getValue());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[SliderSetting] Error casting setting type.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
FloatSetting setting = new FloatSetting(getKey(), getSection(), selection);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatSetting setting = (FloatSetting) 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
public String getUnits()
|
||||
{
|
||||
return mUnits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SLIDER;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SLIDER;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,93 +5,98 @@ import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
|
|||
|
||||
public class StringSingleChoiceSetting extends SettingsItem
|
||||
{
|
||||
private String mDefaultValue;
|
||||
private String mDefaultValue;
|
||||
|
||||
private String[] mChoicesId;
|
||||
private String[] mValuesId;
|
||||
private String[] mChoicesId;
|
||||
private String[] mValuesId;
|
||||
|
||||
public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId, String[] choicesId, String[] valuesId, String defaultValue, Setting setting)
|
||||
public StringSingleChoiceSetting(String key, String section, int titleId, int descriptionId,
|
||||
String[] choicesId, String[] valuesId, String defaultValue, Setting setting)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mValuesId = valuesId;
|
||||
mChoicesId = choicesId;
|
||||
mDefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public String[] getChoicesId()
|
||||
{
|
||||
return mChoicesId;
|
||||
}
|
||||
|
||||
public String[] getValuesId()
|
||||
{
|
||||
return mValuesId;
|
||||
}
|
||||
|
||||
public String getValueAt(int index)
|
||||
{
|
||||
if (mValuesId == null)
|
||||
return null;
|
||||
|
||||
if (index >= 0 && index < mValuesId.length)
|
||||
{
|
||||
super(key, section, setting, titleId, descriptionId);
|
||||
mValuesId = valuesId;
|
||||
mChoicesId = choicesId;
|
||||
mDefaultValue = defaultValue;
|
||||
return mValuesId[index];
|
||||
}
|
||||
|
||||
public String[] getChoicesId()
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getSelectedValue()
|
||||
{
|
||||
if (getSetting() != null)
|
||||
{
|
||||
return mChoicesId;
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
|
||||
public String[] getValuesId()
|
||||
else
|
||||
{
|
||||
return mValuesId;
|
||||
return mDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public String getValueAt(int index)
|
||||
public int getSelectValueIndex()
|
||||
{
|
||||
String selectedValue = getSelectedValue();
|
||||
for (int i = 0; i < mValuesId.length; i++)
|
||||
{
|
||||
if (mValuesId == null)
|
||||
return null;
|
||||
|
||||
if (index >= 0 && index < mValuesId.length)
|
||||
{
|
||||
return mValuesId[index];
|
||||
}
|
||||
|
||||
return "";
|
||||
if (mValuesId[i].equals(selectedValue))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSelectedValue()
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
if (getSetting() != null)
|
||||
{
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
return setting.getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), selection);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
|
||||
public int getSelectValueIndex() {
|
||||
String selectedValue = getSelectedValue();
|
||||
for(int i=0;i<mValuesId.length;i++) {
|
||||
if(mValuesId[i].equals(selectedValue)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* 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)
|
||||
else
|
||||
{
|
||||
if (getSetting() == null)
|
||||
{
|
||||
StringSetting setting = new StringSetting(getKey(), getSection(), selection);
|
||||
setSetting(setting);
|
||||
return setting;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
setting.setValue(selection);
|
||||
return null;
|
||||
}
|
||||
StringSetting setting = (StringSetting) getSetting();
|
||||
setting.setValue(selection);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_STRING_SINGLE_CHOICE;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_STRING_SINGLE_CHOICE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,22 +5,23 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|||
|
||||
public final class SubmenuSetting extends SettingsItem
|
||||
{
|
||||
private MenuTag mMenuKey;
|
||||
private MenuTag mMenuKey;
|
||||
|
||||
public SubmenuSetting(String key, Setting setting, int titleId, int descriptionId, MenuTag menuKey)
|
||||
{
|
||||
super(key, null, setting, titleId, descriptionId);
|
||||
mMenuKey = menuKey;
|
||||
}
|
||||
public SubmenuSetting(String key, Setting setting, int titleId, int descriptionId,
|
||||
MenuTag menuKey)
|
||||
{
|
||||
super(key, null, setting, titleId, descriptionId);
|
||||
mMenuKey = menuKey;
|
||||
}
|
||||
|
||||
public MenuTag getMenuKey()
|
||||
{
|
||||
return mMenuKey;
|
||||
}
|
||||
public MenuTag getMenuKey()
|
||||
{
|
||||
return mMenuKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SUBMENU;
|
||||
}
|
||||
@Override
|
||||
public int getType()
|
||||
{
|
||||
return TYPE_SUBMENU;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,105 +2,105 @@ package org.dolphinemu.dolphinemu.features.settings.ui;
|
|||
|
||||
public enum MenuTag
|
||||
{
|
||||
CONFIG("config"),
|
||||
CONFIG_GENERAL("config_general"),
|
||||
CONFIG_INTERFACE("config_interface"),
|
||||
CONFIG_GAME_CUBE("config_gamecube"),
|
||||
CONFIG_WII("config_wii"),
|
||||
WIIMOTE("wiimote"),
|
||||
WIIMOTE_EXTENSION("wiimote_extension"),
|
||||
GCPAD_TYPE("gc_pad_type"),
|
||||
GRAPHICS("graphics"),
|
||||
HACKS("hacks"),
|
||||
ENHANCEMENTS("enhancements"),
|
||||
STEREOSCOPY("stereoscopy"),
|
||||
GCPAD_1("gcpad", 0),
|
||||
GCPAD_2("gcpad", 1),
|
||||
GCPAD_3("gcpad", 2),
|
||||
GCPAD_4("gcpad", 3),
|
||||
WIIMOTE_1("wiimote", 4),
|
||||
WIIMOTE_2("wiimote", 5),
|
||||
WIIMOTE_3("wiimote", 6),
|
||||
WIIMOTE_4("wiimote", 7),
|
||||
WIIMOTE_EXTENSION_1("wiimote_extension", 4),
|
||||
WIIMOTE_EXTENSION_2("wiimote_extension", 5),
|
||||
WIIMOTE_EXTENSION_3("wiimote_extension", 6),
|
||||
WIIMOTE_EXTENSION_4("wiimote_extension", 7);
|
||||
CONFIG("config"),
|
||||
CONFIG_GENERAL("config_general"),
|
||||
CONFIG_INTERFACE("config_interface"),
|
||||
CONFIG_GAME_CUBE("config_gamecube"),
|
||||
CONFIG_WII("config_wii"),
|
||||
WIIMOTE("wiimote"),
|
||||
WIIMOTE_EXTENSION("wiimote_extension"),
|
||||
GCPAD_TYPE("gc_pad_type"),
|
||||
GRAPHICS("graphics"),
|
||||
HACKS("hacks"),
|
||||
ENHANCEMENTS("enhancements"),
|
||||
STEREOSCOPY("stereoscopy"),
|
||||
GCPAD_1("gcpad", 0),
|
||||
GCPAD_2("gcpad", 1),
|
||||
GCPAD_3("gcpad", 2),
|
||||
GCPAD_4("gcpad", 3),
|
||||
WIIMOTE_1("wiimote", 4),
|
||||
WIIMOTE_2("wiimote", 5),
|
||||
WIIMOTE_3("wiimote", 6),
|
||||
WIIMOTE_4("wiimote", 7),
|
||||
WIIMOTE_EXTENSION_1("wiimote_extension", 4),
|
||||
WIIMOTE_EXTENSION_2("wiimote_extension", 5),
|
||||
WIIMOTE_EXTENSION_3("wiimote_extension", 6),
|
||||
WIIMOTE_EXTENSION_4("wiimote_extension", 7);
|
||||
|
||||
private String tag;
|
||||
private int subType = -1;
|
||||
private String tag;
|
||||
private int subType = -1;
|
||||
|
||||
MenuTag(String tag)
|
||||
MenuTag(String tag)
|
||||
{
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
MenuTag(String tag, int subtype)
|
||||
{
|
||||
this.tag = tag;
|
||||
this.subType = subtype;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (subType != -1)
|
||||
{
|
||||
this.tag = tag;
|
||||
return tag + subType;
|
||||
}
|
||||
|
||||
MenuTag(String tag, int subtype)
|
||||
return tag;
|
||||
}
|
||||
|
||||
public String getTag()
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
public int getSubType()
|
||||
{
|
||||
return subType;
|
||||
}
|
||||
|
||||
public boolean isGCPadMenu()
|
||||
{
|
||||
return this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4;
|
||||
}
|
||||
|
||||
public boolean isWiimoteMenu()
|
||||
{
|
||||
return this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4;
|
||||
}
|
||||
|
||||
public boolean isWiimoteExtensionMenu()
|
||||
{
|
||||
return this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2
|
||||
|| this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4;
|
||||
}
|
||||
|
||||
public static MenuTag getGCPadMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("gcpad", subtype);
|
||||
}
|
||||
|
||||
public static MenuTag getWiimoteMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("wiimote", subtype);
|
||||
}
|
||||
|
||||
public static MenuTag getWiimoteExtensionMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("wiimote_extension", subtype);
|
||||
}
|
||||
|
||||
private static MenuTag getMenuTag(String tag, int subtype)
|
||||
{
|
||||
for (MenuTag menuTag : MenuTag.values())
|
||||
{
|
||||
this.tag = tag;
|
||||
this.subType = subtype;
|
||||
if (menuTag.tag.equals(tag) && menuTag.subType == subtype) return menuTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (subType != -1)
|
||||
{
|
||||
return tag + subType;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
public String getTag()
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
public int getSubType()
|
||||
{
|
||||
return subType;
|
||||
}
|
||||
|
||||
public boolean isGCPadMenu()
|
||||
{
|
||||
return this == GCPAD_1 || this == GCPAD_2 || this == GCPAD_3 || this == GCPAD_4;
|
||||
}
|
||||
|
||||
public boolean isWiimoteMenu()
|
||||
{
|
||||
return this == WIIMOTE_1 || this == WIIMOTE_2 || this == WIIMOTE_3 || this == WIIMOTE_4;
|
||||
}
|
||||
|
||||
public boolean isWiimoteExtensionMenu()
|
||||
{
|
||||
return this == WIIMOTE_EXTENSION_1 || this == WIIMOTE_EXTENSION_2
|
||||
|| this == WIIMOTE_EXTENSION_3 || this == WIIMOTE_EXTENSION_4;
|
||||
}
|
||||
|
||||
public static MenuTag getGCPadMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("gcpad", subtype);
|
||||
}
|
||||
|
||||
public static MenuTag getWiimoteMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("wiimote", subtype);
|
||||
}
|
||||
|
||||
public static MenuTag getWiimoteExtensionMenuTag(int subtype)
|
||||
{
|
||||
return getMenuTag("wiimote_extension", subtype);
|
||||
}
|
||||
|
||||
private static MenuTag getMenuTag(String tag, int subtype)
|
||||
{
|
||||
for (MenuTag menuTag : MenuTag.values())
|
||||
{
|
||||
if (menuTag.tag.equals(tag) && menuTag.subType == subtype) return menuTag;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("You are asking for a menu that is not available or " +
|
||||
"passing a wrong subtype");
|
||||
}
|
||||
throw new IllegalArgumentException("You are asking for a menu that is not available or " +
|
||||
"passing a wrong subtype");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,247 +15,248 @@ import android.view.MenuItem;
|
|||
import android.widget.Toast;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.SettingSection;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
|
||||
{
|
||||
private static final String ARG_MENU_TAG = "menu_tag";
|
||||
private static final String ARG_GAME_ID = "game_id";
|
||||
private static final String FRAGMENT_TAG = "settings";
|
||||
private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this);
|
||||
private static final String ARG_MENU_TAG = "menu_tag";
|
||||
private static final String ARG_GAME_ID = "game_id";
|
||||
private static final String FRAGMENT_TAG = "settings";
|
||||
private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this);
|
||||
|
||||
private ProgressDialog dialog;
|
||||
private ProgressDialog dialog;
|
||||
|
||||
public static void launch(Context context, MenuTag menuTag, String gameId)
|
||||
{
|
||||
Intent settings = new Intent(context, SettingsActivity.class);
|
||||
settings.putExtra(ARG_MENU_TAG, menuTag);
|
||||
settings.putExtra(ARG_GAME_ID, gameId);
|
||||
context.startActivity(settings);
|
||||
}
|
||||
public static void launch(Context context, MenuTag menuTag, String gameId)
|
||||
{
|
||||
Intent settings = new Intent(context, SettingsActivity.class);
|
||||
settings.putExtra(ARG_MENU_TAG, menuTag);
|
||||
settings.putExtra(ARG_GAME_ID, gameId);
|
||||
context.startActivity(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_settings);
|
||||
setContentView(R.layout.activity_settings);
|
||||
|
||||
Intent launcher = getIntent();
|
||||
String gameID = launcher.getStringExtra(ARG_GAME_ID);
|
||||
MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
|
||||
mPresenter.onCreate(savedInstanceState, menuTag, gameID);
|
||||
}
|
||||
Intent launcher = getIntent();
|
||||
String gameID = launcher.getStringExtra(ARG_GAME_ID);
|
||||
MenuTag menuTag = (MenuTag) launcher.getSerializableExtra(ARG_MENU_TAG);
|
||||
mPresenter.onCreate(savedInstanceState, menuTag, gameID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_settings, menu);
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_settings, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
return mPresenter.handleOptionsItem(item.getItemId());
|
||||
}
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
return mPresenter.handleOptionsItem(item.getItemId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
// Critical: If super method is not called, rotations will be busted.
|
||||
super.onSaveInstanceState(outState);
|
||||
mPresenter.saveState(outState);
|
||||
}
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
// Critical: If super method is not called, rotations will be busted.
|
||||
super.onSaveInstanceState(outState);
|
||||
mPresenter.saveState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mPresenter.onStart();
|
||||
}
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mPresenter.onStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is called, the user has left the settings screen (potentially through the
|
||||
* home button) and will expect their changes to be persisted. So we kick off an
|
||||
* IntentService which will do so on a background thread.
|
||||
*/
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
/**
|
||||
* If this is called, the user has left the settings screen (potentially through the
|
||||
* home button) and will expect their changes to be persisted. So we kick off an
|
||||
* IntentService which will do so on a background thread.
|
||||
*/
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
|
||||
mPresenter.onStop(isFinishing());
|
||||
}
|
||||
mPresenter.onStop(isFinishing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed()
|
||||
{
|
||||
mPresenter.onBackPressed();
|
||||
}
|
||||
@Override
|
||||
public void onBackPressed()
|
||||
{
|
||||
mPresenter.onBackPressed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameID)
|
||||
{
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
@Override
|
||||
public void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack,
|
||||
String gameID)
|
||||
{
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
|
||||
if (addToStack)
|
||||
{
|
||||
if (areSystemAnimationsEnabled())
|
||||
{
|
||||
transaction.setCustomAnimations(
|
||||
R.animator.settings_enter,
|
||||
R.animator.settings_exit,
|
||||
R.animator.settings_pop_enter,
|
||||
R.animator.setttings_pop_exit);
|
||||
}
|
||||
if (addToStack)
|
||||
{
|
||||
if (areSystemAnimationsEnabled())
|
||||
{
|
||||
transaction.setCustomAnimations(
|
||||
R.animator.settings_enter,
|
||||
R.animator.settings_exit,
|
||||
R.animator.settings_pop_enter,
|
||||
R.animator.setttings_pop_exit);
|
||||
}
|
||||
|
||||
transaction.addToBackStack(null);
|
||||
mPresenter.addToStack();
|
||||
}
|
||||
transaction.replace(R.id.frame_content, SettingsFragment.newInstance(menuTag, gameID, extras), FRAGMENT_TAG);
|
||||
transaction.addToBackStack(null);
|
||||
mPresenter.addToStack();
|
||||
}
|
||||
transaction.replace(R.id.frame_content, SettingsFragment.newInstance(menuTag, gameID, extras),
|
||||
FRAGMENT_TAG);
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
private boolean areSystemAnimationsEnabled()
|
||||
{
|
||||
float duration = Settings.Global.getFloat(
|
||||
getContentResolver(),
|
||||
Settings.Global.ANIMATOR_DURATION_SCALE, 1);
|
||||
float transition = Settings.Global.getFloat(
|
||||
getContentResolver(),
|
||||
Settings.Global.TRANSITION_ANIMATION_SCALE, 1);
|
||||
return duration != 0 && transition != 0;
|
||||
}
|
||||
private boolean areSystemAnimationsEnabled()
|
||||
{
|
||||
float duration = Settings.Global.getFloat(
|
||||
getContentResolver(),
|
||||
Settings.Global.ANIMATOR_DURATION_SCALE, 1);
|
||||
float transition = Settings.Global.getFloat(
|
||||
getContentResolver(),
|
||||
Settings.Global.TRANSITION_ANIMATION_SCALE, 1);
|
||||
return duration != 0 && transition != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
receiver,
|
||||
filter);
|
||||
DirectoryInitializationService.startService(this);
|
||||
}
|
||||
@Override
|
||||
public void startDirectoryInitializationService(DirectoryStateReceiver receiver,
|
||||
IntentFilter filter)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
receiver,
|
||||
filter);
|
||||
DirectoryInitializationService.startService(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
|
||||
}
|
||||
@Override
|
||||
public void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showLoading()
|
||||
{
|
||||
if (dialog == null)
|
||||
{
|
||||
dialog = new ProgressDialog(this);
|
||||
dialog.setMessage(getString(R.string.load_settings));
|
||||
dialog.setIndeterminate(true);
|
||||
}
|
||||
@Override
|
||||
public void showLoading()
|
||||
{
|
||||
if (dialog == null)
|
||||
{
|
||||
dialog = new ProgressDialog(this);
|
||||
dialog.setMessage(getString(R.string.load_settings));
|
||||
dialog.setIndeterminate(true);
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideLoading()
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
@Override
|
||||
public void hideLoading()
|
||||
{
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPermissionNeededHint()
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
@Override
|
||||
public void showPermissionNeededHint()
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showExternalStorageNotMountedHint()
|
||||
{
|
||||
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
@Override
|
||||
public void showExternalStorageNotMountedHint()
|
||||
{
|
||||
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.dolphinemu.dolphinemu.features.settings.model.Settings getSettings()
|
||||
{
|
||||
return mPresenter.getSettings();
|
||||
}
|
||||
@Override
|
||||
public org.dolphinemu.dolphinemu.features.settings.model.Settings getSettings()
|
||||
{
|
||||
return mPresenter.getSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSettings(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
mPresenter.setSettings(settings);
|
||||
}
|
||||
@Override
|
||||
public void setSettings(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
mPresenter.setSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingsFileLoaded(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
SettingsFragmentView fragment = getFragment();
|
||||
@Override
|
||||
public void onSettingsFileLoaded(
|
||||
org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
SettingsFragmentView fragment = getFragment();
|
||||
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.onSettingsFileLoaded(settings);
|
||||
}
|
||||
}
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.onSettingsFileLoaded(settings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingsFileNotFound()
|
||||
{
|
||||
SettingsFragmentView fragment = getFragment();
|
||||
@Override
|
||||
public void onSettingsFileNotFound()
|
||||
{
|
||||
SettingsFragmentView fragment = getFragment();
|
||||
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.loadDefaultSettings();
|
||||
}
|
||||
}
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.loadDefaultSettings();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showToastMessage(String message)
|
||||
{
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@Override
|
||||
public void showToastMessage(String message)
|
||||
{
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popBackStack()
|
||||
{
|
||||
getSupportFragmentManager().popBackStackImmediate();
|
||||
}
|
||||
@Override
|
||||
public void popBackStack()
|
||||
{
|
||||
getSupportFragmentManager().popBackStackImmediate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mPresenter.onSettingChanged();
|
||||
}
|
||||
@Override
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mPresenter.onSettingChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGcPadSettingChanged(MenuTag key, int value)
|
||||
{
|
||||
mPresenter.onGcPadSettingChanged(key, value);
|
||||
}
|
||||
@Override
|
||||
public void onGcPadSettingChanged(MenuTag key, int value)
|
||||
{
|
||||
mPresenter.onGcPadSettingChanged(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWiimoteSettingChanged(MenuTag section, int value)
|
||||
{
|
||||
mPresenter.onWiimoteSettingChanged(section, value);
|
||||
}
|
||||
@Override
|
||||
public void onWiimoteSettingChanged(MenuTag section, int value)
|
||||
{
|
||||
mPresenter.onWiimoteSettingChanged(section, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mPresenter.onExtensionSettingChanged(menuTag, value);
|
||||
}
|
||||
@Override
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mPresenter.onExtensionSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
private SettingsFragment getFragment()
|
||||
{
|
||||
return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
|
||||
}
|
||||
private SettingsFragment getFragment()
|
||||
{
|
||||
return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,194 +13,197 @@ import org.dolphinemu.dolphinemu.utils.Log;
|
|||
|
||||
public final class SettingsActivityPresenter
|
||||
{
|
||||
private static final String KEY_SHOULD_SAVE = "should_save";
|
||||
private static final String KEY_SHOULD_SAVE = "should_save";
|
||||
|
||||
private SettingsActivityView mView;
|
||||
private SettingsActivityView mView;
|
||||
|
||||
private Settings mSettings = new Settings();
|
||||
private Settings mSettings = new Settings();
|
||||
|
||||
private int mStackCount;
|
||||
private int mStackCount;
|
||||
|
||||
private boolean mShouldSave;
|
||||
private boolean mShouldSave;
|
||||
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
private MenuTag menuTag;
|
||||
private String gameId;
|
||||
private MenuTag menuTag;
|
||||
private String gameId;
|
||||
|
||||
SettingsActivityPresenter(SettingsActivityView view)
|
||||
SettingsActivityPresenter(SettingsActivityView view)
|
||||
{
|
||||
mView = view;
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId)
|
||||
{
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
mView = view;
|
||||
this.menuTag = menuTag;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
else
|
||||
{
|
||||
mShouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
|
||||
}
|
||||
}
|
||||
|
||||
public void onStart()
|
||||
{
|
||||
prepareDolphinDirectoriesIfNeeded();
|
||||
}
|
||||
|
||||
private void loadSettingsUI()
|
||||
{
|
||||
if (mSettings.isEmpty())
|
||||
{
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
mSettings.loadSettings(gameId, mView);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSettings.loadSettings(mView);
|
||||
}
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState, MenuTag menuTag, String gameId)
|
||||
mView.showSettingsFragment(menuTag, null, false, gameId);
|
||||
mView.onSettingsFileLoaded(mSettings);
|
||||
}
|
||||
|
||||
private void prepareDolphinDirectoriesIfNeeded()
|
||||
{
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
this.menuTag = menuTag;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
else
|
||||
{
|
||||
mShouldSave = savedInstanceState.getBoolean(KEY_SHOULD_SAVE);
|
||||
}
|
||||
loadSettingsUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
mView.showLoading();
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState ==
|
||||
DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
mView.hideLoading();
|
||||
loadSettingsUI();
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
mView.showPermissionNeededHint();
|
||||
mView.hideLoading();
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
mView.showExternalStorageNotMountedHint();
|
||||
mView.hideLoading();
|
||||
}
|
||||
});
|
||||
|
||||
mView.startDirectoryInitializationService(directoryStateReceiver, statusIntentFilter);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSettings(Settings settings)
|
||||
{
|
||||
mSettings = settings;
|
||||
}
|
||||
|
||||
public Settings getSettings()
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
public void onStop(boolean finishing)
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
mView.stopListeningToDirectoryInitializationService(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
public void onStart()
|
||||
if (mSettings != null && finishing && mShouldSave)
|
||||
{
|
||||
prepareDolphinDirectoriesIfNeeded();
|
||||
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
|
||||
mSettings.saveSettings(mView);
|
||||
}
|
||||
}
|
||||
|
||||
public void addToStack()
|
||||
{
|
||||
mStackCount++;
|
||||
}
|
||||
|
||||
public void onBackPressed()
|
||||
{
|
||||
if (mStackCount > 0)
|
||||
{
|
||||
mView.popBackStack();
|
||||
mStackCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
mView.finish();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean handleOptionsItem(int itemId)
|
||||
{
|
||||
switch (itemId)
|
||||
{
|
||||
case R.id.menu_save_exit:
|
||||
mView.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void loadSettingsUI()
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mShouldSave = true;
|
||||
}
|
||||
|
||||
public void saveState(Bundle outState)
|
||||
{
|
||||
outState.putBoolean(KEY_SHOULD_SAVE, mShouldSave);
|
||||
}
|
||||
|
||||
public void onGcPadSettingChanged(MenuTag key, int value)
|
||||
{
|
||||
if (value != 0) // Not disabled
|
||||
{
|
||||
if (mSettings.isEmpty())
|
||||
{
|
||||
if (!TextUtils.isEmpty(gameId))
|
||||
{
|
||||
mSettings.loadSettings(gameId, mView);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSettings.loadSettings(mView);
|
||||
}
|
||||
}
|
||||
|
||||
mView.showSettingsFragment(menuTag, null, false, gameId);
|
||||
mView.onSettingsFileLoaded(mSettings);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value / 6);
|
||||
mView.showSettingsFragment(key, bundle, true, gameId);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareDolphinDirectoriesIfNeeded()
|
||||
public void onWiimoteSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
loadSettingsUI();
|
||||
}
|
||||
else
|
||||
{
|
||||
mView.showLoading();
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
case 1:
|
||||
mView.showSettingsFragment(menuTag, null, true, gameId);
|
||||
break;
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
mView.hideLoading();
|
||||
loadSettingsUI();
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
mView.showPermissionNeededHint();
|
||||
mView.hideLoading();
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
mView.showExternalStorageNotMountedHint();
|
||||
mView.hideLoading();
|
||||
}
|
||||
});
|
||||
|
||||
mView.startDirectoryInitializationService(directoryStateReceiver, statusIntentFilter);
|
||||
}
|
||||
case 2:
|
||||
mView.showToastMessage("Please make sure Continuous Scanning is enabled in Core Settings.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void setSettings(Settings settings)
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
if (value != 0) // None
|
||||
{
|
||||
mSettings = settings;
|
||||
}
|
||||
|
||||
public Settings getSettings()
|
||||
{
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
public void onStop(boolean finishing)
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
mView.stopListeningToDirectoryInitializationService(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
if (mSettings != null && finishing && mShouldSave)
|
||||
{
|
||||
Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI...");
|
||||
mSettings.saveSettings(mView);
|
||||
}
|
||||
}
|
||||
|
||||
public void addToStack()
|
||||
{
|
||||
mStackCount++;
|
||||
}
|
||||
|
||||
public void onBackPressed()
|
||||
{
|
||||
if (mStackCount > 0)
|
||||
{
|
||||
mView.popBackStack();
|
||||
mStackCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
mView.finish();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean handleOptionsItem(int itemId)
|
||||
{
|
||||
switch (itemId)
|
||||
{
|
||||
case R.id.menu_save_exit:
|
||||
mView.finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mShouldSave = true;
|
||||
}
|
||||
|
||||
public void saveState(Bundle outState)
|
||||
{
|
||||
outState.putBoolean(KEY_SHOULD_SAVE, mShouldSave);
|
||||
}
|
||||
|
||||
public void onGcPadSettingChanged(MenuTag key, int value)
|
||||
{
|
||||
if (value != 0) // Not disabled
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value / 6);
|
||||
mView.showSettingsFragment(key, bundle, true, gameId);
|
||||
}
|
||||
}
|
||||
|
||||
public void onWiimoteSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 1:
|
||||
mView.showSettingsFragment(menuTag, null, true, gameId);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mView.showToastMessage("Please make sure Continuous Scanning is enabled in Core Settings.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
if (value != 0) // None
|
||||
{
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
|
||||
mView.showSettingsFragment(menuTag, bundle, true, gameId);
|
||||
}
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt(SettingsFragmentPresenter.ARG_CONTROLLER_TYPE, value);
|
||||
mView.showSettingsFragment(menuTag, bundle, true, gameId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,126 +11,126 @@ import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
|
|||
*/
|
||||
public interface SettingsActivityView
|
||||
{
|
||||
/**
|
||||
* Show a new SettingsFragment.
|
||||
*
|
||||
* @param menuTag Identifier for the settings group that should be displayed.
|
||||
* @param addToStack Whether or not this fragment should replace a previous one.
|
||||
*/
|
||||
void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameId);
|
||||
/**
|
||||
* Show a new SettingsFragment.
|
||||
*
|
||||
* @param menuTag Identifier for the settings group that should be displayed.
|
||||
* @param addToStack Whether or not this fragment should replace a previous one.
|
||||
*/
|
||||
void showSettingsFragment(MenuTag menuTag, Bundle extras, boolean addToStack, String gameId);
|
||||
|
||||
/**
|
||||
* Called by a contained Fragment to get access to the Setting HashMap
|
||||
* loaded from disk, so that each Fragment doesn't need to perform its own
|
||||
* read operation.
|
||||
*
|
||||
* @return A possibly null HashMap of Settings.
|
||||
*/
|
||||
Settings getSettings();
|
||||
/**
|
||||
* Called by a contained Fragment to get access to the Setting HashMap
|
||||
* loaded from disk, so that each Fragment doesn't need to perform its own
|
||||
* read operation.
|
||||
*
|
||||
* @return A possibly null HashMap of Settings.
|
||||
*/
|
||||
Settings getSettings();
|
||||
|
||||
/**
|
||||
* Used to provide the Activity with Settings HashMaps if a Fragment already
|
||||
* has one; for example, if a rotation occurs, the Fragment will not be killed,
|
||||
* but the Activity will, so the Activity needs to have its HashMaps resupplied.
|
||||
*
|
||||
* @param settings The ArrayList of all the Settings HashMaps.
|
||||
*/
|
||||
void setSettings(Settings settings);
|
||||
/**
|
||||
* Used to provide the Activity with Settings HashMaps if a Fragment already
|
||||
* has one; for example, if a rotation occurs, the Fragment will not be killed,
|
||||
* but the Activity will, so the Activity needs to have its HashMaps resupplied.
|
||||
*
|
||||
* @param settings The ArrayList of all the Settings HashMaps.
|
||||
*/
|
||||
void setSettings(Settings settings);
|
||||
|
||||
/**
|
||||
* Called when an asynchronous load operation completes.
|
||||
*
|
||||
* @param settings The (possibly null) result of the ini load operation.
|
||||
*/
|
||||
void onSettingsFileLoaded(Settings settings);
|
||||
/**
|
||||
* Called when an asynchronous load operation completes.
|
||||
*
|
||||
* @param settings The (possibly null) result of the ini load operation.
|
||||
*/
|
||||
void onSettingsFileLoaded(Settings settings);
|
||||
|
||||
/**
|
||||
* Called when an asynchronous load operation fails.
|
||||
*/
|
||||
void onSettingsFileNotFound();
|
||||
/**
|
||||
* Called when an asynchronous load operation fails.
|
||||
*/
|
||||
void onSettingsFileNotFound();
|
||||
|
||||
/**
|
||||
* Display a popup text message on screen.
|
||||
*
|
||||
* @param message The contents of the onscreen message.
|
||||
*/
|
||||
void showToastMessage(String message);
|
||||
/**
|
||||
* Display a popup text message on screen.
|
||||
*
|
||||
* @param message The contents of the onscreen message.
|
||||
*/
|
||||
void showToastMessage(String message);
|
||||
|
||||
/**
|
||||
* Show the previous fragment.
|
||||
*/
|
||||
void popBackStack();
|
||||
/**
|
||||
* Show the previous fragment.
|
||||
*/
|
||||
void popBackStack();
|
||||
|
||||
/**
|
||||
* End the activity.
|
||||
*/
|
||||
void finish();
|
||||
/**
|
||||
* End the activity.
|
||||
*/
|
||||
void finish();
|
||||
|
||||
/**
|
||||
* Called by a containing Fragment to tell the Activity that a setting was changed;
|
||||
* unless this has been called, the Activity will not save to disk.
|
||||
*/
|
||||
void onSettingChanged();
|
||||
/**
|
||||
* Called by a containing Fragment to tell the Activity that a setting was changed;
|
||||
* unless this has been called, the Activity will not save to disk.
|
||||
*/
|
||||
void onSettingChanged();
|
||||
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that a GCPad's setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the GCPad that was modified.
|
||||
* @param value New setting for the GCPad.
|
||||
*/
|
||||
void onGcPadSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that a GCPad's setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the GCPad that was modified.
|
||||
* @param value New setting for the GCPad.
|
||||
*/
|
||||
void onGcPadSettingChanged(MenuTag menuTag, int value);
|
||||
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that a Wiimote's setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for Wiimote that was modified.
|
||||
* @param value New setting for the Wiimote.
|
||||
*/
|
||||
void onWiimoteSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that a Wiimote's setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for Wiimote that was modified.
|
||||
* @param value New setting for the Wiimote.
|
||||
*/
|
||||
void onWiimoteSettingChanged(MenuTag menuTag, int value);
|
||||
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that an extension setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the extension that was modified.
|
||||
* @param value New setting for the extension.
|
||||
*/
|
||||
void onExtensionSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Called by a containing Fragment to tell the containing Activity that an extension setting
|
||||
* was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the extension that was modified.
|
||||
* @param value New setting for the extension.
|
||||
*/
|
||||
void onExtensionSettingChanged(MenuTag menuTag, int value);
|
||||
|
||||
/**
|
||||
* Show loading dialog while loading the settings
|
||||
*/
|
||||
void showLoading();
|
||||
/**
|
||||
* Show loading dialog while loading the settings
|
||||
*/
|
||||
void showLoading();
|
||||
|
||||
/**
|
||||
* Hide the loading the dialog
|
||||
*/
|
||||
void hideLoading();
|
||||
/**
|
||||
* Hide the loading the dialog
|
||||
*/
|
||||
void hideLoading();
|
||||
|
||||
/**
|
||||
* Show a hint to the user that the app needs write to external storage access
|
||||
*/
|
||||
void showPermissionNeededHint();
|
||||
/**
|
||||
* Show a hint to the user that the app needs write to external storage access
|
||||
*/
|
||||
void showPermissionNeededHint();
|
||||
|
||||
/**
|
||||
* Show a hint to the user that the app needs the external storage to be mounted
|
||||
*/
|
||||
void showExternalStorageNotMountedHint();
|
||||
/**
|
||||
* Show a hint to the user that the app needs the external storage to be mounted
|
||||
*/
|
||||
void showExternalStorageNotMountedHint();
|
||||
|
||||
/**
|
||||
* Start the DirectoryInitializationService and listen for the result.
|
||||
*
|
||||
* @param receiver the broadcast receiver for the DirectoryInitializationService
|
||||
* @param filter the Intent broadcasts to be received.
|
||||
*/
|
||||
void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter);
|
||||
/**
|
||||
* Start the DirectoryInitializationService and listen for the result.
|
||||
*
|
||||
* @param receiver the broadcast receiver for the DirectoryInitializationService
|
||||
* @param filter the Intent broadcasts to be received.
|
||||
*/
|
||||
void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter);
|
||||
|
||||
/**
|
||||
* Stop listening to the DirectoryInitializationService.
|
||||
*
|
||||
* @param receiver The broadcast receiver to unregister.
|
||||
*/
|
||||
void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver);
|
||||
/**
|
||||
* Stop listening to the DirectoryInitializationService.
|
||||
*
|
||||
* @param receiver The broadcast receiver to unregister.
|
||||
*/
|
||||
void stopListeningToDirectoryInitializationService(DirectoryStateReceiver receiver);
|
||||
}
|
||||
|
|
|
@ -33,406 +33,417 @@ import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SettingViewHold
|
|||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SingleChoiceViewHolder;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SliderViewHolder;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.viewholder.SubmenuViewHolder;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
|
||||
import org.dolphinemu.dolphinemu.utils.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public final class SettingsAdapter extends RecyclerView.Adapter<SettingViewHolder>
|
||||
implements DialogInterface.OnClickListener, SeekBar.OnSeekBarChangeListener
|
||||
implements DialogInterface.OnClickListener, SeekBar.OnSeekBarChangeListener
|
||||
{
|
||||
private SettingsFragmentView mView;
|
||||
private Context mContext;
|
||||
private ArrayList<SettingsItem> mSettings;
|
||||
private SettingsFragmentView mView;
|
||||
private Context mContext;
|
||||
private ArrayList<SettingsItem> mSettings;
|
||||
|
||||
private SettingsItem mClickedItem;
|
||||
private int mSeekbarProgress;
|
||||
private SettingsItem mClickedItem;
|
||||
private int mSeekbarProgress;
|
||||
|
||||
private AlertDialog mDialog;
|
||||
private TextView mTextSliderValue;
|
||||
private AlertDialog mDialog;
|
||||
private TextView mTextSliderValue;
|
||||
|
||||
public SettingsAdapter(SettingsFragmentView view, Context context)
|
||||
{
|
||||
mView = view;
|
||||
mContext = context;
|
||||
}
|
||||
public SettingsAdapter(SettingsFragmentView view, Context context)
|
||||
{
|
||||
mView = view;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SettingViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
View view;
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
@Override
|
||||
public SettingViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
View view;
|
||||
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||
|
||||
switch (viewType)
|
||||
{
|
||||
case SettingsItem.TYPE_HEADER:
|
||||
view = inflater.inflate(R.layout.list_item_settings_header, parent, false);
|
||||
return new HeaderViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_CHECKBOX:
|
||||
view = inflater.inflate(R.layout.list_item_setting_checkbox, parent, false);
|
||||
return new CheckBoxSettingViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_STRING_SINGLE_CHOICE:
|
||||
case SettingsItem.TYPE_SINGLE_CHOICE:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SingleChoiceViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_SLIDER:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SliderViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_SUBMENU:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SubmenuViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_INPUT_BINDING:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new InputBindingSettingViewHolder(view, this, mContext);
|
||||
|
||||
default:
|
||||
Log.error("[SettingsAdapter] Invalid view type: " + viewType);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(SettingViewHolder holder, int position)
|
||||
{
|
||||
holder.bind(getItem(position));
|
||||
}
|
||||
|
||||
private SettingsItem getItem(int position)
|
||||
{
|
||||
return mSettings.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
if (mSettings != null)
|
||||
{
|
||||
return mSettings.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
return getItem(position).getType();
|
||||
}
|
||||
|
||||
public void setSettings(ArrayList<SettingsItem> settings)
|
||||
{
|
||||
mSettings = settings;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void onBooleanClick(CheckBoxSetting item, int position, boolean checked)
|
||||
{
|
||||
BooleanSetting setting = item.setChecked(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();
|
||||
}
|
||||
|
||||
public void onSingleChoiceClick(SingleChoiceSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
|
||||
int value = getSelectionForSingleChoiceValue(item);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setSingleChoiceItems(item.getChoicesId(), value, this);
|
||||
|
||||
mDialog = builder.show();
|
||||
}
|
||||
|
||||
public void onStringSingleChoiceClick(StringSingleChoiceSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setSingleChoiceItems(item.getChoicesId(), item.getSelectValueIndex(), this);
|
||||
|
||||
mDialog = builder.show();
|
||||
}
|
||||
|
||||
public void onSliderClick(SliderSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
mSeekbarProgress = item.getSelectedValue();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(mView.getActivity());
|
||||
View view = inflater.inflate(R.layout.dialog_seekbar, null);
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setView(view);
|
||||
builder.setPositiveButton(R.string.ok, this);
|
||||
builder.setNegativeButton(R.string.cancel, this);
|
||||
mDialog = builder.show();
|
||||
|
||||
mTextSliderValue = (TextView) view.findViewById(R.id.text_value);
|
||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
||||
|
||||
TextView units = (TextView) view.findViewById(R.id.text_units);
|
||||
units.setText(item.getUnits());
|
||||
|
||||
SeekBar seekbar = (SeekBar) view.findViewById(R.id.seekbar);
|
||||
|
||||
seekbar.setMax(item.getMax());
|
||||
seekbar.setProgress(mSeekbarProgress);
|
||||
seekbar.setKeyProgressIncrement(5);
|
||||
|
||||
seekbar.setOnSeekBarChangeListener(this);
|
||||
}
|
||||
|
||||
public void onSubmenuClick(SubmenuSetting item)
|
||||
{
|
||||
mView.loadSubMenu(item.getMenuKey());
|
||||
}
|
||||
|
||||
public void onInputBindingClick(final InputBindingSetting item, final int position)
|
||||
{
|
||||
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item);
|
||||
dialog.setTitle(R.string.input_binding);
|
||||
dialog.setMessage(String.format(mContext.getString(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.setValue("");
|
||||
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.remove(item.getKey());
|
||||
editor.apply();
|
||||
});
|
||||
dialog.setOnDismissListener(dialog1 ->
|
||||
{
|
||||
StringSetting setting = new StringSetting(item.getKey(), item.getSection(), item.getValue());
|
||||
notifyItemChanged(position);
|
||||
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
|
||||
mView.onSettingChanged();
|
||||
});
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
if (mClickedItem instanceof SingleChoiceSetting)
|
||||
{
|
||||
SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem;
|
||||
|
||||
int value = getValueForSingleChoiceSelection(scSetting, which);
|
||||
MenuTag menuTag = scSetting.getMenuTag();
|
||||
if(menuTag != null)
|
||||
{
|
||||
if (menuTag.isGCPadMenu())
|
||||
{
|
||||
mView.onGcPadSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
if (menuTag.isWiimoteMenu())
|
||||
{
|
||||
mView.onWiimoteSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
if (menuTag.isWiimoteExtensionMenu())
|
||||
{
|
||||
mView.onExtensionSettingChanged(menuTag, 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scSetting.getKey().equals(SettingsFile.KEY_VIDEO_BACKEND_INDEX))
|
||||
{
|
||||
putVideoBackendSetting(which);
|
||||
}
|
||||
else if (scSetting.getKey().equals(SettingsFile.KEY_WIIMOTE_EXTENSION))
|
||||
{
|
||||
putExtensionSetting(which, Character.getNumericValue(scSetting.getSection().charAt(scSetting.getSection().length() - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
else if (mClickedItem instanceof StringSingleChoiceSetting)
|
||||
{
|
||||
StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
|
||||
String value = scSetting.getValueAt(which);
|
||||
StringSetting setting = scSetting.setSelectedValue(value);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
else if (mClickedItem instanceof SliderSetting)
|
||||
{
|
||||
SliderSetting sliderSetting = (SliderSetting) mClickedItem;
|
||||
if (sliderSetting.getSetting() instanceof FloatSetting)
|
||||
{
|
||||
float value;
|
||||
|
||||
if (sliderSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)
|
||||
|| sliderSetting.getKey().equals(SettingsFile.KEY_SPEED_LIMIT))
|
||||
{
|
||||
value = mSeekbarProgress / 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (float) mSeekbarProgress;
|
||||
}
|
||||
|
||||
FloatSetting setting = sliderSetting.setSelectedValue(value);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IntSetting setting = sliderSetting.setSelectedValue(mSeekbarProgress);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mView.onSettingChanged();
|
||||
mClickedItem = null;
|
||||
mSeekbarProgress = -1;
|
||||
}
|
||||
|
||||
public void closeDialog()
|
||||
{
|
||||
if (mDialog != null)
|
||||
{
|
||||
mDialog.dismiss();
|
||||
mDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
mSeekbarProgress = progress;
|
||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which)
|
||||
{
|
||||
int valuesId = item.getValuesId();
|
||||
|
||||
if (valuesId > 0)
|
||||
{
|
||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
||||
return valuesArray[which];
|
||||
}
|
||||
else
|
||||
{
|
||||
return which;
|
||||
}
|
||||
}
|
||||
|
||||
private int getSelectionForSingleChoiceValue(SingleChoiceSetting item)
|
||||
{
|
||||
int value = item.getSelectedValue();
|
||||
int valuesId = item.getValuesId();
|
||||
|
||||
if (valuesId > 0)
|
||||
{
|
||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
||||
for (int index = 0; index < valuesArray.length; index++)
|
||||
{
|
||||
int current = valuesArray[index];
|
||||
if (current == value)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void putVideoBackendSetting(int which)
|
||||
switch (viewType)
|
||||
{
|
||||
StringSetting gfxBackend = null;
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE, "OGL");
|
||||
break;
|
||||
case SettingsItem.TYPE_HEADER:
|
||||
view = inflater.inflate(R.layout.list_item_settings_header, parent, false);
|
||||
return new HeaderViewHolder(view, this);
|
||||
|
||||
case 1:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE, "Vulkan");
|
||||
break;
|
||||
case SettingsItem.TYPE_CHECKBOX:
|
||||
view = inflater.inflate(R.layout.list_item_setting_checkbox, parent, false);
|
||||
return new CheckBoxSettingViewHolder(view, this);
|
||||
|
||||
case 2:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE, "Software Renderer");
|
||||
break;
|
||||
case SettingsItem.TYPE_STRING_SINGLE_CHOICE:
|
||||
case SettingsItem.TYPE_SINGLE_CHOICE:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SingleChoiceViewHolder(view, this);
|
||||
|
||||
case 3:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE, "Null");
|
||||
break;
|
||||
}
|
||||
case SettingsItem.TYPE_SLIDER:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SliderViewHolder(view, this);
|
||||
|
||||
mView.putSetting(gfxBackend);
|
||||
case SettingsItem.TYPE_SUBMENU:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new SubmenuViewHolder(view, this);
|
||||
|
||||
case SettingsItem.TYPE_INPUT_BINDING:
|
||||
view = inflater.inflate(R.layout.list_item_setting, parent, false);
|
||||
return new InputBindingSettingViewHolder(view, this, mContext);
|
||||
|
||||
default:
|
||||
Log.error("[SettingsAdapter] Invalid view type: " + viewType);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(SettingViewHolder holder, int position)
|
||||
{
|
||||
holder.bind(getItem(position));
|
||||
}
|
||||
|
||||
private SettingsItem getItem(int position)
|
||||
{
|
||||
return mSettings.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
if (mSettings != null)
|
||||
{
|
||||
return mSettings.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position)
|
||||
{
|
||||
return getItem(position).getType();
|
||||
}
|
||||
|
||||
public void setSettings(ArrayList<SettingsItem> settings)
|
||||
{
|
||||
mSettings = settings;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void onBooleanClick(CheckBoxSetting item, int position, boolean checked)
|
||||
{
|
||||
BooleanSetting setting = item.setChecked(checked);
|
||||
notifyItemChanged(position);
|
||||
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
|
||||
private void putExtensionSetting(int which, int wiimoteNumber)
|
||||
{
|
||||
StringSetting extension = new StringSetting(SettingsFile.KEY_WIIMOTE_EXTENSION, Settings.SECTION_WIIMOTE + wiimoteNumber, mContext.getResources().getStringArray(R.array.wiimoteExtensionsEntries)[which]);
|
||||
mView.putSetting(extension);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
public void onSingleChoiceClick(SingleChoiceSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
|
||||
int value = getSelectionForSingleChoiceValue(item);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setSingleChoiceItems(item.getChoicesId(), value, this);
|
||||
|
||||
mDialog = builder.show();
|
||||
}
|
||||
|
||||
public void onStringSingleChoiceClick(StringSingleChoiceSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setSingleChoiceItems(item.getChoicesId(), item.getSelectValueIndex(), this);
|
||||
|
||||
mDialog = builder.show();
|
||||
}
|
||||
|
||||
public void onSliderClick(SliderSetting item)
|
||||
{
|
||||
mClickedItem = item;
|
||||
mSeekbarProgress = item.getSelectedValue();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity());
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(mView.getActivity());
|
||||
View view = inflater.inflate(R.layout.dialog_seekbar, null);
|
||||
|
||||
builder.setTitle(item.getNameId());
|
||||
builder.setView(view);
|
||||
builder.setPositiveButton(R.string.ok, this);
|
||||
builder.setNegativeButton(R.string.cancel, this);
|
||||
mDialog = builder.show();
|
||||
|
||||
mTextSliderValue = (TextView) view.findViewById(R.id.text_value);
|
||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
||||
|
||||
TextView units = (TextView) view.findViewById(R.id.text_units);
|
||||
units.setText(item.getUnits());
|
||||
|
||||
SeekBar seekbar = (SeekBar) view.findViewById(R.id.seekbar);
|
||||
|
||||
seekbar.setMax(item.getMax());
|
||||
seekbar.setProgress(mSeekbarProgress);
|
||||
seekbar.setKeyProgressIncrement(5);
|
||||
|
||||
seekbar.setOnSeekBarChangeListener(this);
|
||||
}
|
||||
|
||||
public void onSubmenuClick(SubmenuSetting item)
|
||||
{
|
||||
mView.loadSubMenu(item.getMenuKey());
|
||||
}
|
||||
|
||||
public void onInputBindingClick(final InputBindingSetting item, final int position)
|
||||
{
|
||||
final MotionAlertDialog dialog = new MotionAlertDialog(mContext, item);
|
||||
dialog.setTitle(R.string.input_binding);
|
||||
dialog.setMessage(String.format(mContext.getString(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.setValue("");
|
||||
|
||||
SharedPreferences sharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||
editor.remove(item.getKey());
|
||||
editor.apply();
|
||||
});
|
||||
dialog.setOnDismissListener(dialog1 ->
|
||||
{
|
||||
StringSetting setting = new StringSetting(item.getKey(), item.getSection(), item.getValue());
|
||||
notifyItemChanged(position);
|
||||
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
|
||||
mView.onSettingChanged();
|
||||
});
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
if (mClickedItem instanceof SingleChoiceSetting)
|
||||
{
|
||||
SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem;
|
||||
|
||||
int value = getValueForSingleChoiceSelection(scSetting, which);
|
||||
MenuTag menuTag = scSetting.getMenuTag();
|
||||
if (menuTag != null)
|
||||
{
|
||||
if (menuTag.isGCPadMenu())
|
||||
{
|
||||
mView.onGcPadSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
if (menuTag.isWiimoteMenu())
|
||||
{
|
||||
mView.onWiimoteSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
if (menuTag.isWiimoteExtensionMenu())
|
||||
{
|
||||
mView.onExtensionSettingChanged(menuTag, 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scSetting.getKey().equals(SettingsFile.KEY_VIDEO_BACKEND_INDEX))
|
||||
{
|
||||
putVideoBackendSetting(which);
|
||||
}
|
||||
else if (scSetting.getKey().equals(SettingsFile.KEY_WIIMOTE_EXTENSION))
|
||||
{
|
||||
putExtensionSetting(which, Character.getNumericValue(
|
||||
scSetting.getSection().charAt(scSetting.getSection().length() - 1)));
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
else if (mClickedItem instanceof StringSingleChoiceSetting)
|
||||
{
|
||||
StringSingleChoiceSetting scSetting = (StringSingleChoiceSetting) mClickedItem;
|
||||
String value = scSetting.getValueAt(which);
|
||||
StringSetting setting = scSetting.setSelectedValue(value);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
|
||||
closeDialog();
|
||||
}
|
||||
else if (mClickedItem instanceof SliderSetting)
|
||||
{
|
||||
SliderSetting sliderSetting = (SliderSetting) mClickedItem;
|
||||
if (sliderSetting.getSetting() instanceof FloatSetting)
|
||||
{
|
||||
float value;
|
||||
|
||||
if (sliderSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)
|
||||
|| sliderSetting.getKey().equals(SettingsFile.KEY_SPEED_LIMIT))
|
||||
{
|
||||
value = mSeekbarProgress / 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = (float) mSeekbarProgress;
|
||||
}
|
||||
|
||||
FloatSetting setting = sliderSetting.setSelectedValue(value);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IntSetting setting = sliderSetting.setSelectedValue(mSeekbarProgress);
|
||||
if (setting != null)
|
||||
{
|
||||
mView.putSetting(setting);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mView.onSettingChanged();
|
||||
mClickedItem = null;
|
||||
mSeekbarProgress = -1;
|
||||
}
|
||||
|
||||
public void closeDialog()
|
||||
{
|
||||
if (mDialog != null)
|
||||
{
|
||||
mDialog.dismiss();
|
||||
mDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
|
||||
{
|
||||
mSeekbarProgress = progress;
|
||||
mTextSliderValue.setText(String.valueOf(mSeekbarProgress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar)
|
||||
{
|
||||
}
|
||||
|
||||
private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which)
|
||||
{
|
||||
int valuesId = item.getValuesId();
|
||||
|
||||
if (valuesId > 0)
|
||||
{
|
||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
||||
return valuesArray[which];
|
||||
}
|
||||
else
|
||||
{
|
||||
return which;
|
||||
}
|
||||
}
|
||||
|
||||
private int getSelectionForSingleChoiceValue(SingleChoiceSetting item)
|
||||
{
|
||||
int value = item.getSelectedValue();
|
||||
int valuesId = item.getValuesId();
|
||||
|
||||
if (valuesId > 0)
|
||||
{
|
||||
int[] valuesArray = mContext.getResources().getIntArray(valuesId);
|
||||
for (int index = 0; index < valuesArray.length; index++)
|
||||
{
|
||||
int current = valuesArray[index];
|
||||
if (current == value)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void putVideoBackendSetting(int which)
|
||||
{
|
||||
StringSetting gfxBackend = null;
|
||||
switch (which)
|
||||
{
|
||||
case 0:
|
||||
gfxBackend =
|
||||
new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE, "OGL");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE,
|
||||
"Vulkan");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE,
|
||||
"Software Renderer");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
gfxBackend = new StringSetting(SettingsFile.KEY_VIDEO_BACKEND, Settings.SECTION_INI_CORE,
|
||||
"Null");
|
||||
break;
|
||||
}
|
||||
|
||||
mView.putSetting(gfxBackend);
|
||||
}
|
||||
|
||||
private void putExtensionSetting(int which, int wiimoteNumber)
|
||||
{
|
||||
StringSetting extension = new StringSetting(SettingsFile.KEY_WIIMOTE_EXTENSION,
|
||||
Settings.SECTION_WIIMOTE + wiimoteNumber,
|
||||
mContext.getResources().getStringArray(R.array.wiimoteExtensionsEntries)[which]);
|
||||
mView.putSetting(extension);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,170 +20,173 @@ import java.util.ArrayList;
|
|||
|
||||
public final class SettingsFragment extends Fragment implements SettingsFragmentView
|
||||
{
|
||||
private static final String ARGUMENT_MENU_TAG = "menu_tag";
|
||||
private static final String ARGUMENT_GAME_ID = "game_id";
|
||||
private static final String ARGUMENT_MENU_TAG = "menu_tag";
|
||||
private static final String ARGUMENT_GAME_ID = "game_id";
|
||||
|
||||
private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this);
|
||||
private SettingsActivityView mActivity;
|
||||
private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this);
|
||||
private SettingsActivityView mActivity;
|
||||
|
||||
private SettingsAdapter mAdapter;
|
||||
private SettingsAdapter mAdapter;
|
||||
|
||||
public static Fragment newInstance(MenuTag menuTag, String gameId, Bundle extras)
|
||||
{
|
||||
SettingsFragment fragment = new SettingsFragment();
|
||||
public static Fragment newInstance(MenuTag menuTag, String gameId, Bundle extras)
|
||||
{
|
||||
SettingsFragment fragment = new SettingsFragment();
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
if(extras != null)
|
||||
{
|
||||
arguments.putAll(extras);
|
||||
}
|
||||
Bundle arguments = new Bundle();
|
||||
if (extras != null)
|
||||
{
|
||||
arguments.putAll(extras);
|
||||
}
|
||||
|
||||
arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag);
|
||||
arguments.putString(ARGUMENT_GAME_ID, gameId);
|
||||
arguments.putSerializable(ARGUMENT_MENU_TAG, menuTag);
|
||||
arguments.putString(ARGUMENT_GAME_ID, gameId);
|
||||
|
||||
fragment.setArguments(arguments);
|
||||
return fragment;
|
||||
}
|
||||
fragment.setArguments(arguments);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
super.onAttach(context);
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
super.onAttach(context);
|
||||
|
||||
mActivity = (SettingsActivityView) context;
|
||||
mPresenter.onAttach();
|
||||
}
|
||||
mActivity = (SettingsActivityView) context;
|
||||
mPresenter.onAttach();
|
||||
}
|
||||
|
||||
/**
|
||||
* This version of onAttach is needed for versions below Marshmallow.
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
/**
|
||||
* This version of onAttach is needed for versions below Marshmallow.
|
||||
*
|
||||
* @param activity
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(Activity activity)
|
||||
{
|
||||
super.onAttach(activity);
|
||||
|
||||
mActivity = (SettingsActivityView) activity;
|
||||
mPresenter.onAttach();
|
||||
}
|
||||
mActivity = (SettingsActivityView) activity;
|
||||
mPresenter.onAttach();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setRetainInstance(true);
|
||||
Bundle args = getArguments();
|
||||
MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
|
||||
String gameId = getArguments().getString(ARGUMENT_GAME_ID);
|
||||
setRetainInstance(true);
|
||||
Bundle args = getArguments();
|
||||
MenuTag menuTag = (MenuTag) args.getSerializable(ARGUMENT_MENU_TAG);
|
||||
String gameId = getArguments().getString(ARGUMENT_GAME_ID);
|
||||
|
||||
mAdapter = new SettingsAdapter(this, getActivity());
|
||||
mAdapter = new SettingsAdapter(this, getActivity());
|
||||
|
||||
mPresenter.onCreate(menuTag, gameId, args);
|
||||
}
|
||||
mPresenter.onCreate(menuTag, gameId, args);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_settings, container, false);
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
return inflater.inflate(R.layout.fragment_settings, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
LinearLayoutManager manager = new LinearLayoutManager(getActivity());
|
||||
|
||||
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list_settings);
|
||||
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list_settings);
|
||||
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setLayoutManager(manager);
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null));
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setLayoutManager(manager);
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null));
|
||||
|
||||
SettingsActivityView activity = (SettingsActivityView) getActivity();
|
||||
mPresenter.onViewCreated(activity.getSettings());
|
||||
}
|
||||
SettingsActivityView activity = (SettingsActivityView) getActivity();
|
||||
mPresenter.onViewCreated(activity.getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach()
|
||||
{
|
||||
super.onDetach();
|
||||
mActivity = null;
|
||||
@Override
|
||||
public void onDetach()
|
||||
{
|
||||
super.onDetach();
|
||||
mActivity = null;
|
||||
|
||||
if (mAdapter != null)
|
||||
{
|
||||
mAdapter.closeDialog();
|
||||
}
|
||||
}
|
||||
if (mAdapter != null)
|
||||
{
|
||||
mAdapter.closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingsFileLoaded(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
mPresenter.setSettings(settings);
|
||||
}
|
||||
@Override
|
||||
public void onSettingsFileLoaded(
|
||||
org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
mPresenter.setSettings(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void passSettingsToActivity(org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
if (mActivity != null)
|
||||
{
|
||||
mActivity.setSettings(settings);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void passSettingsToActivity(
|
||||
org.dolphinemu.dolphinemu.features.settings.model.Settings settings)
|
||||
{
|
||||
if (mActivity != null)
|
||||
{
|
||||
mActivity.setSettings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showSettingsList(ArrayList<SettingsItem> settingsList)
|
||||
{
|
||||
mAdapter.setSettings(settingsList);
|
||||
}
|
||||
@Override
|
||||
public void showSettingsList(ArrayList<SettingsItem> settingsList)
|
||||
{
|
||||
mAdapter.setSettings(settingsList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadDefaultSettings()
|
||||
{
|
||||
mPresenter.loadDefaultSettings();
|
||||
}
|
||||
@Override
|
||||
public void loadDefaultSettings()
|
||||
{
|
||||
mPresenter.loadDefaultSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadSubMenu(MenuTag menuKey)
|
||||
{
|
||||
mActivity.showSettingsFragment(menuKey, null, true, getArguments().getString(ARGUMENT_GAME_ID));
|
||||
}
|
||||
@Override
|
||||
public void loadSubMenu(MenuTag menuKey)
|
||||
{
|
||||
mActivity.showSettingsFragment(menuKey, null, true, getArguments().getString(ARGUMENT_GAME_ID));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showToastMessage(String message)
|
||||
{
|
||||
mActivity.showToastMessage(message);
|
||||
}
|
||||
@Override
|
||||
public void showToastMessage(String message)
|
||||
{
|
||||
mActivity.showToastMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putSetting(Setting setting)
|
||||
{
|
||||
mPresenter.putSetting(setting);
|
||||
}
|
||||
@Override
|
||||
public void putSetting(Setting setting)
|
||||
{
|
||||
mPresenter.putSetting(setting);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mActivity.onSettingChanged();
|
||||
}
|
||||
@Override
|
||||
public void onSettingChanged()
|
||||
{
|
||||
mActivity.onSettingChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGcPadSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onGcPadSettingChanged(menuTag, value);
|
||||
}
|
||||
@Override
|
||||
public void onGcPadSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onGcPadSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWiimoteSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onWiimoteSettingChanged(menuTag, value);
|
||||
}
|
||||
@Override
|
||||
public void onWiimoteSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onWiimoteSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onExtensionSettingChanged(menuTag, value);
|
||||
}
|
||||
@Override
|
||||
public void onExtensionSettingChanged(MenuTag menuTag, int value)
|
||||
{
|
||||
mActivity.onExtensionSettingChanged(menuTag, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,89 +14,89 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public interface SettingsFragmentView
|
||||
{
|
||||
/**
|
||||
* Called by the containing Activity to notify the Fragment that an
|
||||
* asynchronous load operation completed.
|
||||
*
|
||||
* @param settings The (possibly null) result of the ini load operation.
|
||||
*/
|
||||
void onSettingsFileLoaded(Settings settings);
|
||||
/**
|
||||
* Called by the containing Activity to notify the Fragment that an
|
||||
* asynchronous load operation completed.
|
||||
*
|
||||
* @param settings The (possibly null) result of the ini load operation.
|
||||
*/
|
||||
void onSettingsFileLoaded(Settings settings);
|
||||
|
||||
/**
|
||||
* Pass a settings HashMap to the containing activity, so that it can
|
||||
* share the HashMap with other SettingsFragments; useful so that rotations
|
||||
* do not require an additional load operation.
|
||||
*
|
||||
* @param settings An ArrayList containing all the settings HashMaps.
|
||||
*/
|
||||
void passSettingsToActivity(Settings settings);
|
||||
/**
|
||||
* Pass a settings HashMap to the containing activity, so that it can
|
||||
* share the HashMap with other SettingsFragments; useful so that rotations
|
||||
* do not require an additional load operation.
|
||||
*
|
||||
* @param settings An ArrayList containing all the settings HashMaps.
|
||||
*/
|
||||
void passSettingsToActivity(Settings settings);
|
||||
|
||||
/**
|
||||
* Pass an ArrayList to the View so that it can be displayed on screen.
|
||||
*
|
||||
* @param settingsList The result of converting the HashMap to an ArrayList
|
||||
*/
|
||||
void showSettingsList(ArrayList<SettingsItem> settingsList);
|
||||
/**
|
||||
* Pass an ArrayList to the View so that it can be displayed on screen.
|
||||
*
|
||||
* @param settingsList The result of converting the HashMap to an ArrayList
|
||||
*/
|
||||
void showSettingsList(ArrayList<SettingsItem> settingsList);
|
||||
|
||||
/**
|
||||
* Called by the containing Activity when an asynchronous load operation fails.
|
||||
* Instructs the Fragment to load the settings screen with defaults selected.
|
||||
*/
|
||||
void loadDefaultSettings();
|
||||
/**
|
||||
* Called by the containing Activity when an asynchronous load operation fails.
|
||||
* Instructs the Fragment to load the settings screen with defaults selected.
|
||||
*/
|
||||
void loadDefaultSettings();
|
||||
|
||||
/**
|
||||
* @return The Fragment's containing activity.
|
||||
*/
|
||||
FragmentActivity getActivity();
|
||||
/**
|
||||
* @return The Fragment's containing activity.
|
||||
*/
|
||||
FragmentActivity getActivity();
|
||||
|
||||
/**
|
||||
* Tell the Fragment to tell the containing Activity to show a new
|
||||
* Fragment containing a submenu of settings.
|
||||
*
|
||||
* @param menuKey Identifier for the settings group that should be shown.
|
||||
*/
|
||||
void loadSubMenu(MenuTag menuKey);
|
||||
/**
|
||||
* Tell the Fragment to tell the containing Activity to show a new
|
||||
* Fragment containing a submenu of settings.
|
||||
*
|
||||
* @param menuKey Identifier for the settings group that should be shown.
|
||||
*/
|
||||
void loadSubMenu(MenuTag menuKey);
|
||||
|
||||
/**
|
||||
* Tell the Fragment to tell the containing activity to display a toast message.
|
||||
*
|
||||
* @param message Text to be shown in the Toast
|
||||
*/
|
||||
void showToastMessage(String message);
|
||||
/**
|
||||
* Tell the Fragment to tell the containing activity to display a toast message.
|
||||
*
|
||||
* @param message Text to be shown in the Toast
|
||||
*/
|
||||
void showToastMessage(String message);
|
||||
|
||||
/**
|
||||
* Have the fragment add a setting to the HashMap.
|
||||
*
|
||||
* @param setting The (possibly previously missing) new setting.
|
||||
*/
|
||||
void putSetting(Setting setting);
|
||||
/**
|
||||
* Have the fragment add a setting to the HashMap.
|
||||
*
|
||||
* @param setting The (possibly previously missing) new setting.
|
||||
*/
|
||||
void putSetting(Setting setting);
|
||||
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a setting was modified.
|
||||
*/
|
||||
void onSettingChanged();
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a setting was modified.
|
||||
*/
|
||||
void onSettingChanged();
|
||||
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a GCPad's setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the GCPad that was modified.
|
||||
* @param value New setting for the GCPad.
|
||||
*/
|
||||
void onGcPadSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a GCPad's setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the GCPad that was modified.
|
||||
* @param value New setting for the GCPad.
|
||||
*/
|
||||
void onGcPadSettingChanged(MenuTag menuTag, int value);
|
||||
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a Wiimote's setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for Wiimote that was modified.
|
||||
* @param value New setting for the Wiimote.
|
||||
*/
|
||||
void onWiimoteSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that a Wiimote's setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for Wiimote that was modified.
|
||||
* @param value New setting for the Wiimote.
|
||||
*/
|
||||
void onWiimoteSettingChanged(MenuTag menuTag, int value);
|
||||
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that an extension setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the extension that was modified.
|
||||
* @param value New setting for the extension.
|
||||
*/
|
||||
void onExtensionSettingChanged(MenuTag menuTag, int value);
|
||||
/**
|
||||
* Have the fragment tell the containing Activity that an extension setting was modified.
|
||||
*
|
||||
* @param menuTag Identifier for the extension that was modified.
|
||||
* @param value New setting for the extension.
|
||||
*/
|
||||
void onExtensionSettingChanged(MenuTag menuTag, int value);
|
||||
}
|
||||
|
|
|
@ -9,48 +9,48 @@ import android.widget.FrameLayout;
|
|||
*/
|
||||
public final class SettingsFrameLayout extends FrameLayout
|
||||
{
|
||||
private float mVisibleness = 1.0f;
|
||||
private float mVisibleness = 1.0f;
|
||||
|
||||
public SettingsFrameLayout(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
public SettingsFrameLayout(Context context)
|
||||
{
|
||||
super(context);
|
||||
}
|
||||
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
}
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr)
|
||||
{
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr)
|
||||
{
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
|
||||
{
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
public SettingsFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
|
||||
{
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public float getYFraction()
|
||||
{
|
||||
return getY() / getHeight();
|
||||
}
|
||||
public float getYFraction()
|
||||
{
|
||||
return getY() / getHeight();
|
||||
}
|
||||
|
||||
public void setYFraction(float yFraction)
|
||||
{
|
||||
final int height = getHeight();
|
||||
setY((height > 0) ? (yFraction * height) : -9999);
|
||||
}
|
||||
public void setYFraction(float yFraction)
|
||||
{
|
||||
final int height = getHeight();
|
||||
setY((height > 0) ? (yFraction * height) : -9999);
|
||||
}
|
||||
|
||||
public float getVisibleness()
|
||||
{
|
||||
return mVisibleness;
|
||||
}
|
||||
public float getVisibleness()
|
||||
{
|
||||
return mVisibleness;
|
||||
}
|
||||
|
||||
public void setVisibleness(float visibleness)
|
||||
{
|
||||
setScaleX(visibleness);
|
||||
setScaleY(visibleness);
|
||||
setAlpha(visibleness);
|
||||
}
|
||||
public void setVisibleness(float visibleness)
|
||||
{
|
||||
setScaleX(visibleness);
|
||||
setScaleY(visibleness);
|
||||
setAlpha(visibleness);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,46 +11,46 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class CheckBoxSettingViewHolder extends SettingViewHolder
|
||||
{
|
||||
private CheckBoxSetting mItem;
|
||||
private CheckBoxSetting mItem;
|
||||
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
|
||||
private CheckBox mCheckbox;
|
||||
private CheckBox mCheckbox;
|
||||
|
||||
public CheckBoxSettingViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
public CheckBoxSettingViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
mCheckbox = (CheckBox) root.findViewById(R.id.checkbox);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
mCheckbox = (CheckBox) root.findViewById(R.id.checkbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (CheckBoxSetting) item;
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (CheckBoxSetting) item;
|
||||
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
|
||||
mCheckbox.setChecked(mItem.isChecked());
|
||||
}
|
||||
mCheckbox.setChecked(mItem.isChecked());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
mCheckbox.toggle();
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
mCheckbox.toggle();
|
||||
|
||||
getAdapter().onBooleanClick(mItem, getAdapterPosition(), mCheckbox.isChecked());
|
||||
}
|
||||
getAdapter().onBooleanClick(mItem, getAdapterPosition(), mCheckbox.isChecked());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,29 +9,29 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class HeaderViewHolder extends SettingViewHolder
|
||||
{
|
||||
private TextView mHeaderName;
|
||||
private TextView mHeaderName;
|
||||
|
||||
public HeaderViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
itemView.setOnClickListener(null);
|
||||
}
|
||||
public HeaderViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
itemView.setOnClickListener(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mHeaderName = (TextView) root.findViewById(R.id.text_header_name);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mHeaderName = (TextView) root.findViewById(R.id.text_header_name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mHeaderName.setText(item.getNameId());
|
||||
}
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mHeaderName.setText(item.getNameId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
|
@ -13,41 +13,41 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class InputBindingSettingViewHolder extends SettingViewHolder
|
||||
{
|
||||
private InputBindingSetting mItem;
|
||||
private InputBindingSetting mItem;
|
||||
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
|
||||
private Context mContext;
|
||||
private Context mContext;
|
||||
|
||||
public InputBindingSettingViewHolder(View itemView, SettingsAdapter adapter, Context context)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
public InputBindingSettingViewHolder(View itemView, SettingsAdapter adapter, Context context)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
|
||||
mContext = context;
|
||||
}
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
|
||||
mItem = (InputBindingSetting) item;
|
||||
mItem = (InputBindingSetting) item;
|
||||
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingDescription.setText(sharedPreferences.getString(mItem.getKey(), ""));
|
||||
}
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingDescription.setText(sharedPreferences.getString(mItem.getKey(), ""));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onInputBindingClick(mItem, getAdapterPosition());
|
||||
}
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onInputBindingClick(mItem, getAdapterPosition());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,46 +6,47 @@ import android.view.View;
|
|||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
||||
|
||||
public abstract class SettingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
|
||||
public abstract class SettingViewHolder extends RecyclerView.ViewHolder
|
||||
implements View.OnClickListener
|
||||
{
|
||||
private SettingsAdapter mAdapter;
|
||||
private SettingsAdapter mAdapter;
|
||||
|
||||
public SettingViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView);
|
||||
public SettingViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
mAdapter = adapter;
|
||||
mAdapter = adapter;
|
||||
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnClickListener(this);
|
||||
|
||||
findViews(itemView);
|
||||
}
|
||||
findViews(itemView);
|
||||
}
|
||||
|
||||
protected SettingsAdapter getAdapter()
|
||||
{
|
||||
return mAdapter;
|
||||
}
|
||||
protected SettingsAdapter getAdapter()
|
||||
{
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets handles to all this ViewHolder's child views using their XML-defined identifiers.
|
||||
*
|
||||
* @param root The newly inflated top-level view.
|
||||
*/
|
||||
protected abstract void findViews(View root);
|
||||
/**
|
||||
* Gets handles to all this ViewHolder's child views using their XML-defined identifiers.
|
||||
*
|
||||
* @param root The newly inflated top-level view.
|
||||
*/
|
||||
protected abstract void findViews(View root);
|
||||
|
||||
/**
|
||||
* Called by the adapter to set this ViewHolder's child views to display the list item
|
||||
* it must now represent.
|
||||
*
|
||||
* @param item The list item that should be represented by this ViewHolder.
|
||||
*/
|
||||
public abstract void bind(SettingsItem item);
|
||||
/**
|
||||
* Called by the adapter to set this ViewHolder's child views to display the list item
|
||||
* it must now represent.
|
||||
*
|
||||
* @param item The list item that should be represented by this ViewHolder.
|
||||
*/
|
||||
public abstract void bind(SettingsItem item);
|
||||
|
||||
/**
|
||||
* Called when this ViewHolder's view is clicked on. Implementations should usually pass
|
||||
* this event up to the adapter.
|
||||
*
|
||||
* @param clicked The view that was clicked on.
|
||||
*/
|
||||
public abstract void onClick(View clicked);
|
||||
/**
|
||||
* Called when this ViewHolder's view is clicked on. Implementations should usually pass
|
||||
* this event up to the adapter.
|
||||
*
|
||||
* @param clicked The view that was clicked on.
|
||||
*/
|
||||
public abstract void onClick(View clicked);
|
||||
}
|
||||
|
|
|
@ -11,46 +11,46 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class SingleChoiceViewHolder extends SettingViewHolder
|
||||
{
|
||||
private SettingsItem mItem;
|
||||
private SettingsItem mItem;
|
||||
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
|
||||
public SingleChoiceViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
public SingleChoiceViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = item;
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = item;
|
||||
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
if (mItem instanceof SingleChoiceSetting)
|
||||
{
|
||||
getAdapter().onSingleChoiceClick((SingleChoiceSetting) mItem);
|
||||
}
|
||||
else if (mItem instanceof StringSingleChoiceSetting)
|
||||
{
|
||||
getAdapter().onStringSingleChoiceClick((StringSingleChoiceSetting) mItem);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
if (mItem instanceof SingleChoiceSetting)
|
||||
{
|
||||
getAdapter().onSingleChoiceClick((SingleChoiceSetting) mItem);
|
||||
}
|
||||
else if (mItem instanceof StringSingleChoiceSetting)
|
||||
{
|
||||
getAdapter().onStringSingleChoiceClick((StringSingleChoiceSetting) mItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,40 +10,40 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class SliderViewHolder extends SettingViewHolder
|
||||
{
|
||||
private SliderSetting mItem;
|
||||
private SliderSetting mItem;
|
||||
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
|
||||
public SliderViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
public SliderViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (SliderSetting) item;
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (SliderSetting) item;
|
||||
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onSliderClick(mItem);
|
||||
}
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onSliderClick(mItem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,39 +10,39 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
|
|||
|
||||
public final class SubmenuViewHolder extends SettingViewHolder
|
||||
{
|
||||
private SubmenuSetting mItem;
|
||||
private SubmenuSetting mItem;
|
||||
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
private TextView mTextSettingName;
|
||||
private TextView mTextSettingDescription;
|
||||
|
||||
public SubmenuViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
public SubmenuViewHolder(View itemView, SettingsAdapter adapter)
|
||||
{
|
||||
super(itemView, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
@Override
|
||||
protected void findViews(View root)
|
||||
{
|
||||
mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name);
|
||||
mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (SubmenuSetting) item;
|
||||
@Override
|
||||
public void bind(SettingsItem item)
|
||||
{
|
||||
mItem = (SubmenuSetting) item;
|
||||
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
mTextSettingName.setText(item.getNameId());
|
||||
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
if (item.getDescriptionId() > 0)
|
||||
{
|
||||
mTextSettingDescription.setText(item.getDescriptionId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onSubmenuClick(mItem);
|
||||
}
|
||||
@Override
|
||||
public void onClick(View clicked)
|
||||
{
|
||||
getAdapter().onSubmenuClick(mItem);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -10,13 +10,13 @@ import java.io.File;
|
|||
|
||||
public class CustomFilePickerFragment extends FilePickerFragment
|
||||
{
|
||||
@NonNull
|
||||
@Override
|
||||
public Uri toUri(@NonNull final File file)
|
||||
{
|
||||
return FileProvider
|
||||
.getUriForFile(getContext(),
|
||||
getContext().getApplicationContext().getPackageName() + ".filesprovider",
|
||||
file);
|
||||
}
|
||||
@NonNull
|
||||
@Override
|
||||
public Uri toUri(@NonNull final File file)
|
||||
{
|
||||
return FileProvider
|
||||
.getUriForFile(getContext(),
|
||||
getContext().getApplicationContext().getPackageName() + ".filesprovider",
|
||||
file);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,433 +30,438 @@ import java.io.File;
|
|||
|
||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
|
||||
{
|
||||
private static final String KEY_GAMEPATH = "gamepath";
|
||||
private static final String KEY_GAMEPATH = "gamepath";
|
||||
|
||||
private SharedPreferences mPreferences;
|
||||
private SharedPreferences mPreferences;
|
||||
|
||||
private InputOverlay mInputOverlay;
|
||||
private InputOverlay mInputOverlay;
|
||||
|
||||
private EmulationState mEmulationState;
|
||||
private EmulationState mEmulationState;
|
||||
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
private DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
private EmulationActivity activity;
|
||||
private EmulationActivity activity;
|
||||
|
||||
public static EmulationFragment newInstance(String gamePath)
|
||||
{
|
||||
public static EmulationFragment newInstance(String gamePath)
|
||||
{
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(KEY_GAMEPATH, gamePath);
|
||||
Bundle args = new Bundle();
|
||||
args.putString(KEY_GAMEPATH, gamePath);
|
||||
|
||||
EmulationFragment fragment = new EmulationFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
EmulationFragment fragment = new EmulationFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
super.onAttach(context);
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
super.onAttach(context);
|
||||
|
||||
if (context instanceof EmulationActivity)
|
||||
{
|
||||
activity = (EmulationActivity)context;
|
||||
NativeLibrary.setEmulationActivity((EmulationActivity) context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("EmulationFragment must have EmulationActivity parent");
|
||||
}
|
||||
}
|
||||
if (context instanceof EmulationActivity)
|
||||
{
|
||||
activity = (EmulationActivity) context;
|
||||
NativeLibrary.setEmulationActivity((EmulationActivity) context);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("EmulationFragment must have EmulationActivity parent");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize anything that doesn't depend on the layout / views in here.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
/**
|
||||
* Initialize anything that doesn't depend on the layout / views in here.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// So this fragment doesn't restart on configuration changes; i.e. rotation.
|
||||
setRetainInstance(true);
|
||||
// So this fragment doesn't restart on configuration changes; i.e. rotation.
|
||||
setRetainInstance(true);
|
||||
|
||||
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
|
||||
String gamePath = getArguments().getString(KEY_GAMEPATH);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
boolean firstOpen = preferences.getBoolean(StartupHandler.NEW_SESSION, true);
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(StartupHandler.NEW_SESSION, false);
|
||||
sPrefsEditor.apply();
|
||||
mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath(), firstOpen);
|
||||
}
|
||||
String gamePath = getArguments().getString(KEY_GAMEPATH);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
boolean firstOpen = preferences.getBoolean(StartupHandler.NEW_SESSION, true);
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(StartupHandler.NEW_SESSION, false);
|
||||
sPrefsEditor.apply();
|
||||
mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath(), firstOpen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the UI and start emulation in here.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
||||
/**
|
||||
* Initialize the UI and start emulation in here.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View contents = inflater.inflate(R.layout.fragment_emulation, container, false);
|
||||
|
||||
SurfaceView surfaceView = contents.findViewById(R.id.surface_emulation);
|
||||
surfaceView.getHolder().addCallback(this);
|
||||
SurfaceView surfaceView = contents.findViewById(R.id.surface_emulation);
|
||||
surfaceView.getHolder().addCallback(this);
|
||||
|
||||
mInputOverlay = contents.findViewById(R.id.surface_input_overlay);
|
||||
if (mInputOverlay != null)
|
||||
{
|
||||
// If the input overlay was previously disabled, then don't show it.
|
||||
if (!mPreferences.getBoolean("showInputOverlay", true))
|
||||
{
|
||||
mInputOverlay.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
mInputOverlay = contents.findViewById(R.id.surface_input_overlay);
|
||||
if (mInputOverlay != null)
|
||||
{
|
||||
// If the input overlay was previously disabled, then don't show it.
|
||||
if (!mPreferences.getBoolean("showInputOverlay", true))
|
||||
{
|
||||
mInputOverlay.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
Button doneButton = contents.findViewById(R.id.done_control_config);
|
||||
if (doneButton != null)
|
||||
{
|
||||
doneButton.setOnClickListener(v -> stopConfiguringControls());
|
||||
}
|
||||
Button doneButton = contents.findViewById(R.id.done_control_config);
|
||||
if (doneButton != null)
|
||||
{
|
||||
doneButton.setOnClickListener(v -> stopConfiguringControls());
|
||||
}
|
||||
|
||||
// The new Surface created here will get passed to the native code via onSurfaceChanged.
|
||||
// The new Surface created here will get passed to the native code via onSurfaceChanged.
|
||||
|
||||
return contents;
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
mEmulationState.run(activity.isActivityRecreated());
|
||||
}
|
||||
else
|
||||
{
|
||||
setupDolphinDirectoriesThenStartEmulation();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
if (DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
mEmulationState.run(activity.isActivityRecreated());
|
||||
}
|
||||
else
|
||||
{
|
||||
setupDolphinDirectoriesThenStartEmulation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
if (directoryStateReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
mEmulationState.pause();
|
||||
super.onPause();
|
||||
}
|
||||
mEmulationState.pause();
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach()
|
||||
{
|
||||
NativeLibrary.clearEmulationActivity();
|
||||
super.onDetach();
|
||||
}
|
||||
@Override
|
||||
public void onDetach()
|
||||
{
|
||||
NativeLibrary.clearEmulationActivity();
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
private void setupDolphinDirectoriesThenStartEmulation() {
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
private void setupDolphinDirectoriesThenStartEmulation()
|
||||
{
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
mEmulationState.run(activity.isActivityRecreated());
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
else if (directoryInitializationState == DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
Toast.makeText(getContext(), R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
directoryStateReceiver =
|
||||
new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState ==
|
||||
DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
mEmulationState.run(activity.isActivityRecreated());
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
|
||||
{
|
||||
Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
else if (directoryInitializationState ==
|
||||
DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
|
||||
{
|
||||
Toast.makeText(getContext(), R.string.external_storage_not_mounted,
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
DirectoryInitializationService.startService(getActivity());
|
||||
}
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
DirectoryInitializationService.startService(getActivity());
|
||||
}
|
||||
|
||||
public void toggleInputOverlayVisibility()
|
||||
{
|
||||
SharedPreferences.Editor editor = mPreferences.edit();
|
||||
public void toggleInputOverlayVisibility()
|
||||
{
|
||||
SharedPreferences.Editor editor = mPreferences.edit();
|
||||
|
||||
// If the overlay is currently set to INVISIBLE
|
||||
if (!mPreferences.getBoolean("showInputOverlay", false))
|
||||
{
|
||||
// Set it to VISIBLE
|
||||
mInputOverlay.setVisibility(View.VISIBLE);
|
||||
editor.putBoolean("showInputOverlay", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set it to INVISIBLE
|
||||
mInputOverlay.setVisibility(View.GONE);
|
||||
editor.putBoolean("showInputOverlay", false);
|
||||
}
|
||||
// If the overlay is currently set to INVISIBLE
|
||||
if (!mPreferences.getBoolean("showInputOverlay", false))
|
||||
{
|
||||
// Set it to VISIBLE
|
||||
mInputOverlay.setVisibility(View.VISIBLE);
|
||||
editor.putBoolean("showInputOverlay", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set it to INVISIBLE
|
||||
mInputOverlay.setVisibility(View.GONE);
|
||||
editor.putBoolean("showInputOverlay", false);
|
||||
}
|
||||
|
||||
editor.apply();
|
||||
}
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
public void refreshInputOverlay()
|
||||
{
|
||||
mInputOverlay.refreshControls();
|
||||
}
|
||||
public void refreshInputOverlay()
|
||||
{
|
||||
mInputOverlay.refreshControls();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder)
|
||||
{
|
||||
// We purposely don't do anything here.
|
||||
// All work is done in surfaceChanged, which we are guaranteed to get even for surface creation.
|
||||
}
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder)
|
||||
{
|
||||
// We purposely don't do anything here.
|
||||
// All work is done in surfaceChanged, which we are guaranteed to get even for surface creation.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
|
||||
mEmulationState.newSurface(holder.getSurface());
|
||||
}
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
|
||||
mEmulationState.newSurface(holder.getSurface());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder)
|
||||
{
|
||||
mEmulationState.clearSurface();
|
||||
}
|
||||
@Override
|
||||
public void surfaceDestroyed(SurfaceHolder holder)
|
||||
{
|
||||
mEmulationState.clearSurface();
|
||||
}
|
||||
|
||||
public void stopEmulation()
|
||||
{
|
||||
mEmulationState.stop();
|
||||
}
|
||||
public void stopEmulation()
|
||||
{
|
||||
mEmulationState.stop();
|
||||
}
|
||||
|
||||
public void startConfiguringControls()
|
||||
{
|
||||
getView().findViewById(R.id.done_control_config).setVisibility(View.VISIBLE);
|
||||
mInputOverlay.setIsInEditMode(true);
|
||||
}
|
||||
public void startConfiguringControls()
|
||||
{
|
||||
getView().findViewById(R.id.done_control_config).setVisibility(View.VISIBLE);
|
||||
mInputOverlay.setIsInEditMode(true);
|
||||
}
|
||||
|
||||
public void stopConfiguringControls()
|
||||
{
|
||||
getView().findViewById(R.id.done_control_config).setVisibility(View.GONE);
|
||||
mInputOverlay.setIsInEditMode(false);
|
||||
}
|
||||
public void stopConfiguringControls()
|
||||
{
|
||||
getView().findViewById(R.id.done_control_config).setVisibility(View.GONE);
|
||||
mInputOverlay.setIsInEditMode(false);
|
||||
}
|
||||
|
||||
public boolean isConfiguringControls()
|
||||
{
|
||||
return mInputOverlay.isInEditMode();
|
||||
}
|
||||
public boolean isConfiguringControls()
|
||||
{
|
||||
return mInputOverlay.isInEditMode();
|
||||
}
|
||||
|
||||
private static class EmulationState
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
STOPPED, RUNNING, PAUSED
|
||||
}
|
||||
private static class EmulationState
|
||||
{
|
||||
private enum State
|
||||
{
|
||||
STOPPED, RUNNING, PAUSED
|
||||
}
|
||||
|
||||
private final String mGamePath;
|
||||
private Thread mEmulationThread;
|
||||
private State state;
|
||||
private Surface mSurface;
|
||||
private boolean mRunWhenSurfaceIsValid;
|
||||
private boolean loadPreviousTemporaryState;
|
||||
private boolean firstOpen;
|
||||
private final String temporaryStatePath;
|
||||
private final String mGamePath;
|
||||
private Thread mEmulationThread;
|
||||
private State state;
|
||||
private Surface mSurface;
|
||||
private boolean mRunWhenSurfaceIsValid;
|
||||
private boolean loadPreviousTemporaryState;
|
||||
private boolean firstOpen;
|
||||
private final String temporaryStatePath;
|
||||
|
||||
EmulationState(String gamePath, String temporaryStatePath, boolean firstOpen)
|
||||
{
|
||||
this.firstOpen = firstOpen;
|
||||
mGamePath = gamePath;
|
||||
this.temporaryStatePath = temporaryStatePath;
|
||||
// Starting state is stopped.
|
||||
state = State.STOPPED;
|
||||
}
|
||||
EmulationState(String gamePath, String temporaryStatePath, boolean firstOpen)
|
||||
{
|
||||
this.firstOpen = firstOpen;
|
||||
mGamePath = gamePath;
|
||||
this.temporaryStatePath = temporaryStatePath;
|
||||
// Starting state is stopped.
|
||||
state = State.STOPPED;
|
||||
}
|
||||
|
||||
// Getters for the current state
|
||||
// Getters for the current state
|
||||
|
||||
public synchronized boolean isStopped()
|
||||
{
|
||||
return state == State.STOPPED;
|
||||
}
|
||||
public synchronized boolean isStopped()
|
||||
{
|
||||
return state == State.STOPPED;
|
||||
}
|
||||
|
||||
public synchronized boolean isPaused()
|
||||
{
|
||||
return state == State.PAUSED;
|
||||
}
|
||||
public synchronized boolean isPaused()
|
||||
{
|
||||
return state == State.PAUSED;
|
||||
}
|
||||
|
||||
public synchronized boolean isRunning()
|
||||
{
|
||||
return state == State.RUNNING;
|
||||
}
|
||||
public synchronized boolean isRunning()
|
||||
{
|
||||
return state == State.RUNNING;
|
||||
}
|
||||
|
||||
// State changing methods
|
||||
// State changing methods
|
||||
|
||||
public synchronized void stop()
|
||||
{
|
||||
if (state != State.STOPPED)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Stopping emulation.");
|
||||
state = State.STOPPED;
|
||||
NativeLibrary.StopEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Stop called while already stopped.");
|
||||
}
|
||||
}
|
||||
public synchronized void stop()
|
||||
{
|
||||
if (state != State.STOPPED)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Stopping emulation.");
|
||||
state = State.STOPPED;
|
||||
NativeLibrary.StopEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Stop called while already stopped.");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void pause()
|
||||
{
|
||||
if (state != State.PAUSED)
|
||||
{
|
||||
state = State.PAUSED;
|
||||
Log.debug("[EmulationFragment] Pausing emulation.");
|
||||
public synchronized void pause()
|
||||
{
|
||||
if (state != State.PAUSED)
|
||||
{
|
||||
state = State.PAUSED;
|
||||
Log.debug("[EmulationFragment] Pausing emulation.");
|
||||
|
||||
// Release the surface before pausing, since emulation has to be running for that.
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
NativeLibrary.PauseEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Pause called while already paused.");
|
||||
}
|
||||
}
|
||||
// Release the surface before pausing, since emulation has to be running for that.
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
NativeLibrary.PauseEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Pause called while already paused.");
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void run(boolean isActivityRecreated)
|
||||
{
|
||||
if (isActivityRecreated)
|
||||
{
|
||||
if (NativeLibrary.IsRunning())
|
||||
{
|
||||
loadPreviousTemporaryState = false;
|
||||
state = State.PAUSED;
|
||||
deleteFile(temporaryStatePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadPreviousTemporaryState = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] activity resumed or fresh start");
|
||||
loadPreviousTemporaryState = false;
|
||||
// activity resumed without being killed or this is the first run
|
||||
deleteFile(temporaryStatePath);
|
||||
}
|
||||
public synchronized void run(boolean isActivityRecreated)
|
||||
{
|
||||
if (isActivityRecreated)
|
||||
{
|
||||
if (NativeLibrary.IsRunning())
|
||||
{
|
||||
loadPreviousTemporaryState = false;
|
||||
state = State.PAUSED;
|
||||
deleteFile(temporaryStatePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadPreviousTemporaryState = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] activity resumed or fresh start");
|
||||
loadPreviousTemporaryState = false;
|
||||
// activity resumed without being killed or this is the first run
|
||||
deleteFile(temporaryStatePath);
|
||||
}
|
||||
|
||||
// If the surface is set, run now. Otherwise, wait for it to get set.
|
||||
if (mSurface != null)
|
||||
{
|
||||
runWithValidSurface();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRunWhenSurfaceIsValid = true;
|
||||
}
|
||||
}
|
||||
// If the surface is set, run now. Otherwise, wait for it to get set.
|
||||
if (mSurface != null)
|
||||
{
|
||||
runWithValidSurface();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRunWhenSurfaceIsValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Surface callbacks
|
||||
public synchronized void newSurface(Surface surface)
|
||||
{
|
||||
mSurface = surface;
|
||||
if (mRunWhenSurfaceIsValid)
|
||||
{
|
||||
runWithValidSurface();
|
||||
}
|
||||
}
|
||||
// Surface callbacks
|
||||
public synchronized void newSurface(Surface surface)
|
||||
{
|
||||
mSurface = surface;
|
||||
if (mRunWhenSurfaceIsValid)
|
||||
{
|
||||
runWithValidSurface();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void clearSurface()
|
||||
{
|
||||
if (mSurface == null)
|
||||
{
|
||||
Log.warning("[EmulationFragment] clearSurface called, but surface already null.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mSurface = null;
|
||||
Log.debug("[EmulationFragment] Surface destroyed.");
|
||||
public synchronized void clearSurface()
|
||||
{
|
||||
if (mSurface == null)
|
||||
{
|
||||
Log.warning("[EmulationFragment] clearSurface called, but surface already null.");
|
||||
}
|
||||
else
|
||||
{
|
||||
mSurface = null;
|
||||
Log.debug("[EmulationFragment] Surface destroyed.");
|
||||
|
||||
if (state == State.RUNNING)
|
||||
{
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
state = State.PAUSED;
|
||||
}
|
||||
else if (state == State.PAUSED)
|
||||
{
|
||||
Log.warning("[EmulationFragment] Surface cleared while emulation paused.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Surface cleared while emulation stopped.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state == State.RUNNING)
|
||||
{
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
state = State.PAUSED;
|
||||
}
|
||||
else if (state == State.PAUSED)
|
||||
{
|
||||
Log.warning("[EmulationFragment] Surface cleared while emulation paused.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("[EmulationFragment] Surface cleared while emulation stopped.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void runWithValidSurface()
|
||||
{
|
||||
mRunWhenSurfaceIsValid = false;
|
||||
if (state == State.STOPPED)
|
||||
{
|
||||
mEmulationThread = new Thread(() ->
|
||||
{
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
if (loadPreviousTemporaryState)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Starting emulation thread from previous state.");
|
||||
NativeLibrary.Run(mGamePath, temporaryStatePath, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.");
|
||||
NativeLibrary.Run(mGamePath, firstOpen);
|
||||
}
|
||||
}, "NativeEmulation");
|
||||
mEmulationThread.start();
|
||||
private void runWithValidSurface()
|
||||
{
|
||||
mRunWhenSurfaceIsValid = false;
|
||||
if (state == State.STOPPED)
|
||||
{
|
||||
mEmulationThread = new Thread(() ->
|
||||
{
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
if (loadPreviousTemporaryState)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Starting emulation thread from previous state.");
|
||||
NativeLibrary.Run(mGamePath, temporaryStatePath, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.");
|
||||
NativeLibrary.Run(mGamePath, firstOpen);
|
||||
}
|
||||
}, "NativeEmulation");
|
||||
mEmulationThread.start();
|
||||
|
||||
}
|
||||
else if (state == State.PAUSED)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Resuming emulation.");
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
NativeLibrary.UnPauseEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] Bug, run called while already running.");
|
||||
}
|
||||
state = State.RUNNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state == State.PAUSED)
|
||||
{
|
||||
Log.debug("[EmulationFragment] Resuming emulation.");
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
NativeLibrary.UnPauseEmulation();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.debug("[EmulationFragment] Bug, run called while already running.");
|
||||
}
|
||||
state = State.RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
public void saveTemporaryState()
|
||||
{
|
||||
NativeLibrary.SaveStateAs(getTemporaryStateFilePath(), true);
|
||||
}
|
||||
public void saveTemporaryState()
|
||||
{
|
||||
NativeLibrary.SaveStateAs(getTemporaryStateFilePath(), true);
|
||||
}
|
||||
|
||||
private String getTemporaryStateFilePath()
|
||||
{
|
||||
return getContext().getFilesDir() + File.separator + "temp.sav";
|
||||
}
|
||||
private String getTemporaryStateFilePath()
|
||||
{
|
||||
return getContext().getFilesDir() + File.separator + "temp.sav";
|
||||
}
|
||||
|
||||
private static void deleteFile(String path)
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = new File(path);
|
||||
file.delete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// fail safely
|
||||
}
|
||||
}
|
||||
private static void deleteFile(String path)
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = new File(path);
|
||||
file.delete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// fail safely
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,62 +16,68 @@ import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
|||
|
||||
public final class MenuFragment extends Fragment implements View.OnClickListener
|
||||
{
|
||||
private static final String KEY_TITLE = "title";
|
||||
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
|
||||
static {
|
||||
buttonsActionsMap.append(R.id.menu_take_screenshot, EmulationActivity.MENU_ACTION_TAKE_SCREENSHOT);
|
||||
buttonsActionsMap.append(R.id.menu_quicksave, EmulationActivity.MENU_ACTION_QUICK_SAVE);
|
||||
buttonsActionsMap.append(R.id.menu_quickload, EmulationActivity.MENU_ACTION_QUICK_LOAD);
|
||||
buttonsActionsMap.append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT);
|
||||
buttonsActionsMap.append(R.id.menu_emulation_load_root, EmulationActivity.MENU_ACTION_LOAD_ROOT);
|
||||
buttonsActionsMap.append(R.id.menu_refresh_wiimotes, EmulationActivity.MENU_ACTION_REFRESH_WIIMOTES);
|
||||
buttonsActionsMap.append(R.id.menu_change_disc, EmulationActivity.MENU_ACTION_CHANGE_DISC);
|
||||
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
|
||||
}
|
||||
private static final String KEY_TITLE = "title";
|
||||
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
|
||||
|
||||
public static MenuFragment newInstance(String title)
|
||||
{
|
||||
MenuFragment fragment = new MenuFragment();
|
||||
static
|
||||
{
|
||||
buttonsActionsMap
|
||||
.append(R.id.menu_take_screenshot, EmulationActivity.MENU_ACTION_TAKE_SCREENSHOT);
|
||||
buttonsActionsMap.append(R.id.menu_quicksave, EmulationActivity.MENU_ACTION_QUICK_SAVE);
|
||||
buttonsActionsMap.append(R.id.menu_quickload, EmulationActivity.MENU_ACTION_QUICK_LOAD);
|
||||
buttonsActionsMap
|
||||
.append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT);
|
||||
buttonsActionsMap
|
||||
.append(R.id.menu_emulation_load_root, EmulationActivity.MENU_ACTION_LOAD_ROOT);
|
||||
buttonsActionsMap
|
||||
.append(R.id.menu_refresh_wiimotes, EmulationActivity.MENU_ACTION_REFRESH_WIIMOTES);
|
||||
buttonsActionsMap.append(R.id.menu_change_disc, EmulationActivity.MENU_ACTION_CHANGE_DISC);
|
||||
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
|
||||
}
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putSerializable(KEY_TITLE, title);
|
||||
fragment.setArguments(arguments);
|
||||
public static MenuFragment newInstance(String title)
|
||||
{
|
||||
MenuFragment fragment = new MenuFragment();
|
||||
|
||||
return fragment;
|
||||
}
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putSerializable(KEY_TITLE, title);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_ingame_menu, container, false);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
LinearLayout options = (LinearLayout) rootView.findViewById(R.id.layout_options);
|
||||
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++)
|
||||
{
|
||||
Button button = (Button) options.getChildAt(childIndex);
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_ingame_menu, container, false);
|
||||
|
||||
button.setOnClickListener(this);
|
||||
}
|
||||
LinearLayout options = (LinearLayout) rootView.findViewById(R.id.layout_options);
|
||||
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++)
|
||||
{
|
||||
Button button = (Button) options.getChildAt(childIndex);
|
||||
|
||||
TextView titleText = rootView.findViewById(R.id.text_game_title);
|
||||
String title = getArguments().getString(KEY_TITLE);
|
||||
if (title != null)
|
||||
{
|
||||
titleText.setText(title);
|
||||
}
|
||||
button.setOnClickListener(this);
|
||||
}
|
||||
|
||||
return rootView;
|
||||
}
|
||||
TextView titleText = rootView.findViewById(R.id.text_game_title);
|
||||
String title = getArguments().getString(KEY_TITLE);
|
||||
if (title != null)
|
||||
{
|
||||
titleText.setText(title);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WrongConstant")
|
||||
@Override
|
||||
public void onClick(View button)
|
||||
{
|
||||
int action = buttonsActionsMap.get(button.getId());
|
||||
if (action >= 0)
|
||||
{
|
||||
((EmulationActivity) getActivity()).handleMenuAction(action);
|
||||
}
|
||||
}
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WrongConstant")
|
||||
@Override
|
||||
public void onClick(View button)
|
||||
{
|
||||
int action = buttonsActionsMap.get(button.getId());
|
||||
if (action >= 0)
|
||||
{
|
||||
((EmulationActivity) getActivity()).handleMenuAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,86 +15,104 @@ import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
|||
|
||||
public final class SaveLoadStateFragment extends Fragment implements View.OnClickListener
|
||||
{
|
||||
public enum SaveOrLoad
|
||||
{
|
||||
SAVE, LOAD
|
||||
}
|
||||
public enum SaveOrLoad
|
||||
{
|
||||
SAVE, LOAD
|
||||
}
|
||||
|
||||
private static final String KEY_SAVEORLOAD = "saveorload";
|
||||
private static SparseIntArray saveButtonsActionsMap = new SparseIntArray();
|
||||
static {
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_1, EmulationActivity.MENU_ACTION_SAVE_SLOT1);
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_2, EmulationActivity.MENU_ACTION_SAVE_SLOT2);
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_3, EmulationActivity.MENU_ACTION_SAVE_SLOT3);
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_4, EmulationActivity.MENU_ACTION_SAVE_SLOT4);
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_5, EmulationActivity.MENU_ACTION_SAVE_SLOT5);
|
||||
saveButtonsActionsMap.append(R.id.loadsave_state_button_6, EmulationActivity.MENU_ACTION_SAVE_SLOT6);
|
||||
}
|
||||
private static SparseIntArray loadButtonsActionsMap = new SparseIntArray();
|
||||
static {
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_1, EmulationActivity.MENU_ACTION_LOAD_SLOT1);
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_2, EmulationActivity.MENU_ACTION_LOAD_SLOT2);
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_3, EmulationActivity.MENU_ACTION_LOAD_SLOT3);
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_4, EmulationActivity.MENU_ACTION_LOAD_SLOT4);
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_5, EmulationActivity.MENU_ACTION_LOAD_SLOT5);
|
||||
loadButtonsActionsMap.append(R.id.loadsave_state_button_6, EmulationActivity.MENU_ACTION_LOAD_SLOT6);
|
||||
}
|
||||
private SaveOrLoad mSaveOrLoad;
|
||||
private static final String KEY_SAVEORLOAD = "saveorload";
|
||||
private static SparseIntArray saveButtonsActionsMap = new SparseIntArray();
|
||||
|
||||
public static SaveLoadStateFragment newInstance(SaveOrLoad saveOrLoad)
|
||||
{
|
||||
SaveLoadStateFragment fragment = new SaveLoadStateFragment();
|
||||
static
|
||||
{
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_1, EmulationActivity.MENU_ACTION_SAVE_SLOT1);
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_2, EmulationActivity.MENU_ACTION_SAVE_SLOT2);
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_3, EmulationActivity.MENU_ACTION_SAVE_SLOT3);
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_4, EmulationActivity.MENU_ACTION_SAVE_SLOT4);
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_5, EmulationActivity.MENU_ACTION_SAVE_SLOT5);
|
||||
saveButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_6, EmulationActivity.MENU_ACTION_SAVE_SLOT6);
|
||||
}
|
||||
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putSerializable(KEY_SAVEORLOAD, saveOrLoad);
|
||||
fragment.setArguments(arguments);
|
||||
private static SparseIntArray loadButtonsActionsMap = new SparseIntArray();
|
||||
|
||||
return fragment;
|
||||
}
|
||||
static
|
||||
{
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_1, EmulationActivity.MENU_ACTION_LOAD_SLOT1);
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_2, EmulationActivity.MENU_ACTION_LOAD_SLOT2);
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_3, EmulationActivity.MENU_ACTION_LOAD_SLOT3);
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_4, EmulationActivity.MENU_ACTION_LOAD_SLOT4);
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_5, EmulationActivity.MENU_ACTION_LOAD_SLOT5);
|
||||
loadButtonsActionsMap
|
||||
.append(R.id.loadsave_state_button_6, EmulationActivity.MENU_ACTION_LOAD_SLOT6);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
private SaveOrLoad mSaveOrLoad;
|
||||
|
||||
mSaveOrLoad = (SaveOrLoad) getArguments().getSerializable(KEY_SAVEORLOAD);
|
||||
}
|
||||
public static SaveLoadStateFragment newInstance(SaveOrLoad saveOrLoad)
|
||||
{
|
||||
SaveLoadStateFragment fragment = new SaveLoadStateFragment();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_saveload_state, container, false);
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putSerializable(KEY_SAVEORLOAD, saveOrLoad);
|
||||
fragment.setArguments(arguments);
|
||||
|
||||
GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots);
|
||||
for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++)
|
||||
{
|
||||
Button button = (Button) grid.getChildAt(childIndex);
|
||||
button.setOnClickListener(this);
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
|
||||
// So that item clicked to start this Fragment is no longer the focused item.
|
||||
grid.requestFocus();
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
mSaveOrLoad = (SaveOrLoad) getArguments().getSerializable(KEY_SAVEORLOAD);
|
||||
}
|
||||
|
||||
@SuppressWarnings("WrongConstant")
|
||||
@Override
|
||||
public void onClick(View button)
|
||||
{
|
||||
int action = 0;
|
||||
switch(mSaveOrLoad)
|
||||
{
|
||||
case SAVE:
|
||||
action = saveButtonsActionsMap.get(button.getId(), -1);
|
||||
break;
|
||||
case LOAD:
|
||||
action = loadButtonsActionsMap.get(button.getId(), -1);
|
||||
}
|
||||
if (action >= 0)
|
||||
{
|
||||
((EmulationActivity) getActivity()).handleMenuAction(action);
|
||||
}
|
||||
}
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_saveload_state, container, false);
|
||||
|
||||
GridLayout grid = (GridLayout) rootView.findViewById(R.id.grid_state_slots);
|
||||
for (int childIndex = 0; childIndex < grid.getChildCount(); childIndex++)
|
||||
{
|
||||
Button button = (Button) grid.getChildAt(childIndex);
|
||||
button.setOnClickListener(this);
|
||||
}
|
||||
|
||||
// So that item clicked to start this Fragment is no longer the focused item.
|
||||
grid.requestFocus();
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@SuppressWarnings("WrongConstant")
|
||||
@Override
|
||||
public void onClick(View button)
|
||||
{
|
||||
int action = 0;
|
||||
switch (mSaveOrLoad)
|
||||
{
|
||||
case SAVE:
|
||||
action = saveButtonsActionsMap.get(button.getId(), -1);
|
||||
break;
|
||||
case LOAD:
|
||||
action = loadButtonsActionsMap.get(button.getId(), -1);
|
||||
}
|
||||
if (action >= 0)
|
||||
{
|
||||
((EmulationActivity) getActivity()).handleMenuAction(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,50 +1,56 @@
|
|||
package org.dolphinemu.dolphinemu.model;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Environment;
|
||||
|
||||
import org.dolphinemu.dolphinemu.utils.CoverHelper;
|
||||
|
||||
public class GameFile
|
||||
{
|
||||
private long mPointer; // Do not rename or move without editing the native code
|
||||
private long mPointer; // Do not rename or move without editing the native code
|
||||
|
||||
private GameFile(long pointer)
|
||||
{
|
||||
mPointer = pointer;
|
||||
}
|
||||
private GameFile(long pointer)
|
||||
{
|
||||
mPointer = pointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public native void finalize();
|
||||
@Override
|
||||
public native void finalize();
|
||||
|
||||
public native int getPlatform();
|
||||
public native String getTitle();
|
||||
public native String getDescription();
|
||||
public native String getCompany();
|
||||
public native int getCountry();
|
||||
public native int getRegion();
|
||||
public native String getPath();
|
||||
public native String getGameId();
|
||||
public native int[] getBanner();
|
||||
public native int getBannerWidth();
|
||||
public native int getBannerHeight();
|
||||
public native int getPlatform();
|
||||
|
||||
public String getCoverPath()
|
||||
{
|
||||
return Environment.getExternalStorageDirectory().getPath() +
|
||||
"/dolphin-emu/Cache/GameCovers/" + getGameId() + ".png";
|
||||
}
|
||||
public native String getTitle();
|
||||
|
||||
public String getCustomCoverPath()
|
||||
{
|
||||
return getPath().substring(0, getPath().lastIndexOf(".")) + ".cover.png";
|
||||
}
|
||||
public native String getDescription();
|
||||
|
||||
public String getScreenshotPath()
|
||||
{
|
||||
String gameId = getGameId();
|
||||
return "file://" + Environment.getExternalStorageDirectory().getPath() +
|
||||
"/dolphin-emu/ScreenShots/" + gameId + "/" + gameId + "-1.png";
|
||||
}
|
||||
public native String getCompany();
|
||||
|
||||
public native int getCountry();
|
||||
|
||||
public native int getRegion();
|
||||
|
||||
public native String getPath();
|
||||
|
||||
public native String getGameId();
|
||||
|
||||
public native int[] getBanner();
|
||||
|
||||
public native int getBannerWidth();
|
||||
|
||||
public native int getBannerHeight();
|
||||
|
||||
public String getCoverPath()
|
||||
{
|
||||
return Environment.getExternalStorageDirectory().getPath() +
|
||||
"/dolphin-emu/Cache/GameCovers/" + getGameId() + ".png";
|
||||
}
|
||||
|
||||
public String getCustomCoverPath()
|
||||
{
|
||||
return getPath().substring(0, getPath().lastIndexOf(".")) + ".cover.png";
|
||||
}
|
||||
|
||||
public String getScreenshotPath()
|
||||
{
|
||||
String gameId = getGameId();
|
||||
return "file://" + Environment.getExternalStorageDirectory().getPath() +
|
||||
"/dolphin-emu/ScreenShots/" + gameId + "/" + gameId + "-1.png";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,80 +10,86 @@ import java.util.Set;
|
|||
|
||||
public class GameFileCache
|
||||
{
|
||||
private static final String GAME_FOLDER_PATHS_PREFERENCE = "gameFolderPaths";
|
||||
private static final Set<String> EMPTY_SET = new HashSet<>();
|
||||
private static final String GAME_FOLDER_PATHS_PREFERENCE = "gameFolderPaths";
|
||||
private static final Set<String> EMPTY_SET = new HashSet<>();
|
||||
|
||||
private long mPointer; // Do not rename or move without editing the native code
|
||||
private long mPointer; // Do not rename or move without editing the native code
|
||||
|
||||
public GameFileCache(String path)
|
||||
{
|
||||
mPointer = newGameFileCache(path);
|
||||
}
|
||||
public GameFileCache(String path)
|
||||
{
|
||||
mPointer = newGameFileCache(path);
|
||||
}
|
||||
|
||||
private static native long newGameFileCache(String path);
|
||||
private static native long newGameFileCache(String path);
|
||||
|
||||
@Override
|
||||
public native void finalize();
|
||||
@Override
|
||||
public native void finalize();
|
||||
|
||||
public static void addGameFolder(String path, Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
Set<String> newFolderPaths = new HashSet<>(folderPaths);
|
||||
newFolderPaths.add(path);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||
editor.apply();
|
||||
}
|
||||
public static void addGameFolder(String path, Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
Set<String> newFolderPaths = new HashSet<>(folderPaths);
|
||||
newFolderPaths.add(path);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void removeNonExistentGameFolders(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
Set<String> newFolderPaths = new HashSet<>();
|
||||
for (String folderPath : folderPaths)
|
||||
{
|
||||
File folder = new File(folderPath);
|
||||
if (folder.exists())
|
||||
{
|
||||
newFolderPaths.add(folderPath);
|
||||
}
|
||||
}
|
||||
private void removeNonExistentGameFolders(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPaths = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
Set<String> newFolderPaths = new HashSet<>();
|
||||
for (String folderPath : folderPaths)
|
||||
{
|
||||
File folder = new File(folderPath);
|
||||
if (folder.exists())
|
||||
{
|
||||
newFolderPaths.add(folderPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (folderPaths.size() != newFolderPaths.size())
|
||||
{
|
||||
// One or more folders are being deleted
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
if (folderPaths.size() != newFolderPaths.size())
|
||||
{
|
||||
// One or more folders are being deleted
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putStringSet(GAME_FOLDER_PATHS_PREFERENCE, newFolderPaths);
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans through the file system and updates the cache to match.
|
||||
* @return true if the cache was modified
|
||||
*/
|
||||
public boolean scanLibrary(Context context)
|
||||
{
|
||||
removeNonExistentGameFolders(context);
|
||||
/**
|
||||
* Scans through the file system and updates the cache to match.
|
||||
*
|
||||
* @return true if the cache was modified
|
||||
*/
|
||||
public boolean scanLibrary(Context context)
|
||||
{
|
||||
removeNonExistentGameFolders(context);
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPathsSet = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
String[] folderPaths = folderPathsSet.toArray(new String[folderPathsSet.size()]);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Set<String> folderPathsSet = preferences.getStringSet(GAME_FOLDER_PATHS_PREFERENCE, EMPTY_SET);
|
||||
String[] folderPaths = folderPathsSet.toArray(new String[folderPathsSet.size()]);
|
||||
|
||||
boolean cacheChanged = update(folderPaths);
|
||||
cacheChanged |= updateAdditionalMetadata();
|
||||
if (cacheChanged)
|
||||
{
|
||||
save();
|
||||
}
|
||||
return cacheChanged;
|
||||
}
|
||||
boolean cacheChanged = update(folderPaths);
|
||||
cacheChanged |= updateAdditionalMetadata();
|
||||
if (cacheChanged)
|
||||
{
|
||||
save();
|
||||
}
|
||||
return cacheChanged;
|
||||
}
|
||||
|
||||
public native GameFile[] getAllGames();
|
||||
public native GameFile addOrGet(String gamePath);
|
||||
private native boolean update(String[] folderPaths);
|
||||
private native boolean updateAdditionalMetadata();
|
||||
public native boolean load();
|
||||
private native boolean save();
|
||||
public native GameFile[] getAllGames();
|
||||
|
||||
public native GameFile addOrGet(String gamePath);
|
||||
|
||||
private native boolean update(String[] folderPaths);
|
||||
|
||||
private native boolean updateAdditionalMetadata();
|
||||
|
||||
public native boolean load();
|
||||
|
||||
private native boolean save();
|
||||
}
|
||||
|
|
|
@ -6,59 +6,59 @@ package org.dolphinemu.dolphinemu.model;
|
|||
public class HomeScreenChannel
|
||||
{
|
||||
|
||||
private long channelId;
|
||||
private String name;
|
||||
private String description;
|
||||
private String appLinkIntentUri;
|
||||
private long channelId;
|
||||
private String name;
|
||||
private String description;
|
||||
private String appLinkIntentUri;
|
||||
|
||||
public HomeScreenChannel()
|
||||
{
|
||||
}
|
||||
public HomeScreenChannel()
|
||||
{
|
||||
}
|
||||
|
||||
public HomeScreenChannel(String name, String description, String appLinkIntentUri)
|
||||
{
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.appLinkIntentUri = appLinkIntentUri;
|
||||
}
|
||||
public HomeScreenChannel(String name, String description, String appLinkIntentUri)
|
||||
{
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.appLinkIntentUri = appLinkIntentUri;
|
||||
}
|
||||
|
||||
public long getChannelId()
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
public long getChannelId()
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(long channelId)
|
||||
{
|
||||
this.channelId = channelId;
|
||||
}
|
||||
public void setChannelId(long channelId)
|
||||
{
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
public void setName(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
public String getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
public void setDescription(String description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getAppLinkIntentUri()
|
||||
{
|
||||
return appLinkIntentUri;
|
||||
}
|
||||
public String getAppLinkIntentUri()
|
||||
{
|
||||
return appLinkIntentUri;
|
||||
}
|
||||
|
||||
public void setAppLinkIntentUri(String appLinkIntentUri)
|
||||
{
|
||||
this.appLinkIntentUri = appLinkIntentUri;
|
||||
}
|
||||
public void setAppLinkIntentUri(String appLinkIntentUri)
|
||||
{
|
||||
this.appLinkIntentUri = appLinkIntentUri;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,29 +2,29 @@ package org.dolphinemu.dolphinemu.model;
|
|||
|
||||
public final class TvSettingsItem
|
||||
{
|
||||
private final int mItemId;
|
||||
private final int mIconId;
|
||||
private final int mLabelId;
|
||||
private final int mItemId;
|
||||
private final int mIconId;
|
||||
private final int mLabelId;
|
||||
|
||||
public TvSettingsItem(int itemId, int iconId, int labelId)
|
||||
{
|
||||
mItemId = itemId;
|
||||
mIconId = iconId;
|
||||
mLabelId = labelId;
|
||||
}
|
||||
public TvSettingsItem(int itemId, int iconId, int labelId)
|
||||
{
|
||||
mItemId = itemId;
|
||||
mIconId = iconId;
|
||||
mLabelId = labelId;
|
||||
}
|
||||
|
||||
public int getItemId()
|
||||
{
|
||||
return mItemId;
|
||||
}
|
||||
public int getItemId()
|
||||
{
|
||||
return mItemId;
|
||||
}
|
||||
|
||||
public int getIconId()
|
||||
{
|
||||
return mIconId;
|
||||
}
|
||||
public int getIconId()
|
||||
{
|
||||
return mIconId;
|
||||
}
|
||||
|
||||
public int getLabelId()
|
||||
{
|
||||
return mLabelId;
|
||||
}
|
||||
public int getLabelId()
|
||||
{
|
||||
return mLabelId;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,117 +19,119 @@ import android.view.MotionEvent;
|
|||
*/
|
||||
public final class InputOverlayDrawableButton
|
||||
{
|
||||
// The ID identifying what type of button this Drawable represents.
|
||||
private int mButtonType;
|
||||
private int mTrackId;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private BitmapDrawable mDefaultStateBitmap;
|
||||
private BitmapDrawable mPressedStateBitmap;
|
||||
private boolean mPressedState = false;
|
||||
// The ID identifying what type of button this Drawable represents.
|
||||
private int mButtonType;
|
||||
private int mTrackId;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private BitmapDrawable mDefaultStateBitmap;
|
||||
private BitmapDrawable mPressedStateBitmap;
|
||||
private boolean mPressedState = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param defaultStateBitmap {@link Bitmap} to use with the default state Drawable.
|
||||
* @param pressedStateBitmap {@link Bitmap} to use with the pressed state Drawable.
|
||||
* @param buttonType Identifier for this type of button.
|
||||
*/
|
||||
public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap, Bitmap pressedStateBitmap, int buttonType)
|
||||
{
|
||||
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
|
||||
mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap);
|
||||
mButtonType = buttonType;
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param defaultStateBitmap {@link Bitmap} to use with the default state Drawable.
|
||||
* @param pressedStateBitmap {@link Bitmap} to use with the pressed state Drawable.
|
||||
* @param buttonType Identifier for this type of button.
|
||||
*/
|
||||
public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap,
|
||||
Bitmap pressedStateBitmap, int buttonType)
|
||||
{
|
||||
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
|
||||
mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap);
|
||||
mButtonType = buttonType;
|
||||
|
||||
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
|
||||
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
|
||||
}
|
||||
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
|
||||
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this InputOverlayDrawableButton's button ID.
|
||||
*
|
||||
* @return this InputOverlayDrawableButton's button ID.
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return mButtonType;
|
||||
}
|
||||
/**
|
||||
* Gets this InputOverlayDrawableButton's button ID.
|
||||
*
|
||||
* @return this InputOverlayDrawableButton's button ID.
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return mButtonType;
|
||||
}
|
||||
|
||||
public void setTrackId(int trackId)
|
||||
{
|
||||
mTrackId = trackId;
|
||||
}
|
||||
public void setTrackId(int trackId)
|
||||
{
|
||||
mTrackId = trackId;
|
||||
}
|
||||
|
||||
public int getTrackId()
|
||||
{
|
||||
return mTrackId;
|
||||
}
|
||||
public int getTrackId()
|
||||
{
|
||||
return mTrackId;
|
||||
}
|
||||
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int)event.getX(pointerIndex);
|
||||
int fingerPositionY = (int)event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mControlPositionX += fingerPositionX - mPreviousTouchX;
|
||||
mControlPositionY += fingerPositionY - mPreviousTouchY;
|
||||
setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX, getHeight() + mControlPositionY);
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int) event.getX(pointerIndex);
|
||||
int fingerPositionY = (int) event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mControlPositionX += fingerPositionX - mPreviousTouchX;
|
||||
mControlPositionY += fingerPositionY - mPreviousTouchY;
|
||||
setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX,
|
||||
getHeight() + mControlPositionY);
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
getCurrentStateBitmapDrawable().draw(canvas);
|
||||
}
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
getCurrentStateBitmapDrawable().draw(canvas);
|
||||
}
|
||||
|
||||
private BitmapDrawable getCurrentStateBitmapDrawable()
|
||||
{
|
||||
return mPressedState ? mPressedStateBitmap : mDefaultStateBitmap;
|
||||
}
|
||||
private BitmapDrawable getCurrentStateBitmapDrawable()
|
||||
{
|
||||
return mPressedState ? mPressedStateBitmap : mDefaultStateBitmap;
|
||||
}
|
||||
|
||||
public void setBounds(int left, int top, int right, int bottom)
|
||||
{
|
||||
mDefaultStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedStateBitmap.setBounds(left, top, right, bottom);
|
||||
}
|
||||
public void setBounds(int left, int top, int right, int bottom)
|
||||
{
|
||||
mDefaultStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedStateBitmap.setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mDefaultStateBitmap.getBounds();
|
||||
}
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mDefaultStateBitmap.getBounds();
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
public int getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
public int getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
public void setPressedState(boolean isPressed)
|
||||
{
|
||||
mPressedState = isPressed;
|
||||
}
|
||||
public void setPressedState(boolean isPressed)
|
||||
{
|
||||
mPressedState = isPressed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,183 +19,188 @@ import android.view.MotionEvent;
|
|||
*/
|
||||
public final class InputOverlayDrawableDpad
|
||||
{
|
||||
// The ID identifying what type of button this Drawable represents.
|
||||
private int[] mButtonType = new int[4];
|
||||
private int mTrackId;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private BitmapDrawable mDefaultStateBitmap;
|
||||
private BitmapDrawable mPressedOneDirectionStateBitmap;
|
||||
private BitmapDrawable mPressedTwoDirectionsStateBitmap;
|
||||
private int mPressState = STATE_DEFAULT;
|
||||
// The ID identifying what type of button this Drawable represents.
|
||||
private int[] mButtonType = new int[4];
|
||||
private int mTrackId;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private BitmapDrawable mDefaultStateBitmap;
|
||||
private BitmapDrawable mPressedOneDirectionStateBitmap;
|
||||
private BitmapDrawable mPressedTwoDirectionsStateBitmap;
|
||||
private int mPressState = STATE_DEFAULT;
|
||||
|
||||
public static final int STATE_DEFAULT = 0;
|
||||
public static final int STATE_PRESSED_UP = 1;
|
||||
public static final int STATE_PRESSED_DOWN = 2;
|
||||
public static final int STATE_PRESSED_LEFT = 3;
|
||||
public static final int STATE_PRESSED_RIGHT = 4;
|
||||
public static final int STATE_PRESSED_UP_LEFT = 5;
|
||||
public static final int STATE_PRESSED_UP_RIGHT = 6;
|
||||
public static final int STATE_PRESSED_DOWN_LEFT = 7;
|
||||
public static final int STATE_PRESSED_DOWN_RIGHT = 8;
|
||||
public static final int STATE_DEFAULT = 0;
|
||||
public static final int STATE_PRESSED_UP = 1;
|
||||
public static final int STATE_PRESSED_DOWN = 2;
|
||||
public static final int STATE_PRESSED_LEFT = 3;
|
||||
public static final int STATE_PRESSED_RIGHT = 4;
|
||||
public static final int STATE_PRESSED_UP_LEFT = 5;
|
||||
public static final int STATE_PRESSED_UP_RIGHT = 6;
|
||||
public static final int STATE_PRESSED_DOWN_LEFT = 7;
|
||||
public static final int STATE_PRESSED_DOWN_RIGHT = 8;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param defaultStateBitmap {@link Bitmap} of the default state.
|
||||
* @param pressedOneDirectionStateBitmap {@link Bitmap} of the pressed state in one direction.
|
||||
* @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction.
|
||||
* @param buttonUp Identifier for the up button.
|
||||
* @param buttonDown Identifier for the down button.
|
||||
* @param buttonLeft Identifier for the left button.
|
||||
* @param buttonRight Identifier for the right button.
|
||||
*/
|
||||
public InputOverlayDrawableDpad(Resources res,
|
||||
Bitmap defaultStateBitmap,
|
||||
Bitmap pressedOneDirectionStateBitmap,
|
||||
Bitmap pressedTwoDirectionsStateBitmap,
|
||||
int buttonUp, int buttonDown,
|
||||
int buttonLeft, int buttonRight)
|
||||
{
|
||||
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
|
||||
mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap);
|
||||
mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap);
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param defaultStateBitmap {@link Bitmap} of the default state.
|
||||
* @param pressedOneDirectionStateBitmap {@link Bitmap} of the pressed state in one direction.
|
||||
* @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction.
|
||||
* @param buttonUp Identifier for the up button.
|
||||
* @param buttonDown Identifier for the down button.
|
||||
* @param buttonLeft Identifier for the left button.
|
||||
* @param buttonRight Identifier for the right button.
|
||||
*/
|
||||
public InputOverlayDrawableDpad(Resources res,
|
||||
Bitmap defaultStateBitmap,
|
||||
Bitmap pressedOneDirectionStateBitmap,
|
||||
Bitmap pressedTwoDirectionsStateBitmap,
|
||||
int buttonUp, int buttonDown,
|
||||
int buttonLeft, int buttonRight)
|
||||
{
|
||||
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
|
||||
mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap);
|
||||
mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap);
|
||||
|
||||
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
|
||||
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
|
||||
mWidth = mDefaultStateBitmap.getIntrinsicWidth();
|
||||
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
|
||||
|
||||
mButtonType[0] = buttonUp;
|
||||
mButtonType[1] = buttonDown;
|
||||
mButtonType[2] = buttonLeft;
|
||||
mButtonType[3] = buttonRight;
|
||||
}
|
||||
mButtonType[0] = buttonUp;
|
||||
mButtonType[1] = buttonDown;
|
||||
mButtonType[2] = buttonLeft;
|
||||
mButtonType[3] = buttonRight;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
int px = mControlPositionX + (getWidth()/2);
|
||||
int py = mControlPositionY + (getHeight()/2);
|
||||
switch (mPressState) {
|
||||
case STATE_DEFAULT:
|
||||
mDefaultStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_UP:
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(90, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN:
|
||||
canvas.save();
|
||||
canvas.rotate(180, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_LEFT:
|
||||
canvas.save();
|
||||
canvas.rotate(270, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_UP_LEFT:
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_UP_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(90, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(180, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN_LEFT:
|
||||
canvas.save();
|
||||
canvas.rotate(270, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
int px = mControlPositionX + (getWidth() / 2);
|
||||
int py = mControlPositionY + (getHeight() / 2);
|
||||
switch (mPressState)
|
||||
{
|
||||
case STATE_DEFAULT:
|
||||
mDefaultStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_UP:
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(90, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN:
|
||||
canvas.save();
|
||||
canvas.rotate(180, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_LEFT:
|
||||
canvas.save();
|
||||
canvas.rotate(270, px, py);
|
||||
mPressedOneDirectionStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_UP_LEFT:
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
break;
|
||||
case STATE_PRESSED_UP_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(90, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN_RIGHT:
|
||||
canvas.save();
|
||||
canvas.rotate(180, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
case STATE_PRESSED_DOWN_LEFT:
|
||||
canvas.save();
|
||||
canvas.rotate(270, px, py);
|
||||
mPressedTwoDirectionsStateBitmap.draw(canvas);
|
||||
canvas.restore();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets one of the InputOverlayDrawableDpad's button IDs.
|
||||
*
|
||||
* @return the requested InputOverlayDrawableDpad's button ID.
|
||||
*/
|
||||
public int getId(int direction)
|
||||
{
|
||||
return mButtonType[direction];
|
||||
}
|
||||
/**
|
||||
* Gets one of the InputOverlayDrawableDpad's button IDs.
|
||||
*
|
||||
* @return the requested InputOverlayDrawableDpad's button ID.
|
||||
*/
|
||||
public int getId(int direction)
|
||||
{
|
||||
return mButtonType[direction];
|
||||
}
|
||||
|
||||
public void setTrackId(int trackId)
|
||||
{
|
||||
mTrackId = trackId;
|
||||
}
|
||||
public void setTrackId(int trackId)
|
||||
{
|
||||
mTrackId = trackId;
|
||||
}
|
||||
|
||||
public int getTrackId()
|
||||
{
|
||||
return mTrackId;
|
||||
}
|
||||
public int getTrackId()
|
||||
{
|
||||
return mTrackId;
|
||||
}
|
||||
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int)event.getX(pointerIndex);
|
||||
int fingerPositionY = (int)event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mControlPositionX += fingerPositionX - mPreviousTouchX;
|
||||
mControlPositionY += fingerPositionY - mPreviousTouchY;
|
||||
setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX, getHeight() + mControlPositionY);
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int) event.getX(pointerIndex);
|
||||
int fingerPositionY = (int) event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
mControlPositionX += fingerPositionX - mPreviousTouchX;
|
||||
mControlPositionY += fingerPositionY - mPreviousTouchY;
|
||||
setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX,
|
||||
getHeight() + mControlPositionY);
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
|
||||
public void setBounds(int left, int top, int right, int bottom)
|
||||
{
|
||||
mDefaultStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedOneDirectionStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom);
|
||||
}
|
||||
public void setBounds(int left, int top, int right, int bottom)
|
||||
{
|
||||
mDefaultStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedOneDirectionStateBitmap.setBounds(left, top, right, bottom);
|
||||
mPressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom);
|
||||
}
|
||||
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mDefaultStateBitmap.getBounds();
|
||||
}
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mDefaultStateBitmap.getBounds();
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
public int getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
public int getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
public void setState(int pressState) {
|
||||
mPressState = pressState;
|
||||
}
|
||||
public void setState(int pressState)
|
||||
{
|
||||
mPressState = pressState;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
package org.dolphinemu.dolphinemu.overlay;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -21,246 +20,258 @@ import android.view.MotionEvent;
|
|||
*/
|
||||
public final class InputOverlayDrawableJoystick
|
||||
{
|
||||
private SharedPreferences mPreferences;
|
||||
private SharedPreferences mPreferences;
|
||||
|
||||
private final int[] axisIDs = {0, 0, 0, 0};
|
||||
private final float[] axises = {0f, 0f};
|
||||
private int trackId = -1;
|
||||
private int mJoystickType;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private Rect mVirtBounds;
|
||||
private Rect mOrigBounds;
|
||||
private BitmapDrawable mOuterBitmap;
|
||||
private BitmapDrawable mDefaultStateInnerBitmap;
|
||||
private BitmapDrawable mPressedStateInnerBitmap;
|
||||
private BitmapDrawable mBoundsBoxBitmap;
|
||||
private boolean mPressedState = false;
|
||||
private final int[] axisIDs = {0, 0, 0, 0};
|
||||
private final float[] axises = {0f, 0f};
|
||||
private int trackId = -1;
|
||||
private int mJoystickType;
|
||||
private int mControlPositionX, mControlPositionY;
|
||||
private int mPreviousTouchX, mPreviousTouchY;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
private Rect mVirtBounds;
|
||||
private Rect mOrigBounds;
|
||||
private BitmapDrawable mOuterBitmap;
|
||||
private BitmapDrawable mDefaultStateInnerBitmap;
|
||||
private BitmapDrawable mPressedStateInnerBitmap;
|
||||
private BitmapDrawable mBoundsBoxBitmap;
|
||||
private boolean mPressedState = false;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick.
|
||||
* @param bitmapInnerDefault {@link Bitmap} which represents the default inner movable part of the joystick.
|
||||
* @param bitmapInnerPressed {@link Bitmap} which represents the pressed inner movable part of the joystick.
|
||||
* @param rectOuter {@link Rect} which represents the outer joystick bounds.
|
||||
* @param rectInner {@link Rect} which represents the inner joystick bounds.
|
||||
* @param joystick Identifier for which joystick this is.
|
||||
*/
|
||||
public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter,
|
||||
Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed,
|
||||
Rect rectOuter, Rect rectInner, int joystick, SharedPreferences prefsHandle)
|
||||
{
|
||||
axisIDs[0] = joystick + 1;
|
||||
axisIDs[1] = joystick + 2;
|
||||
axisIDs[2] = joystick + 3;
|
||||
axisIDs[3] = joystick + 4;
|
||||
mJoystickType = joystick;
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param res {@link Resources} instance.
|
||||
* @param bitmapOuter {@link Bitmap} which represents the outer non-movable part of the joystick.
|
||||
* @param bitmapInnerDefault {@link Bitmap} which represents the default inner movable part of the joystick.
|
||||
* @param bitmapInnerPressed {@link Bitmap} which represents the pressed inner movable part of the joystick.
|
||||
* @param rectOuter {@link Rect} which represents the outer joystick bounds.
|
||||
* @param rectInner {@link Rect} which represents the inner joystick bounds.
|
||||
* @param joystick Identifier for which joystick this is.
|
||||
*/
|
||||
public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter,
|
||||
Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed,
|
||||
Rect rectOuter, Rect rectInner, int joystick, SharedPreferences prefsHandle)
|
||||
{
|
||||
axisIDs[0] = joystick + 1;
|
||||
axisIDs[1] = joystick + 2;
|
||||
axisIDs[2] = joystick + 3;
|
||||
axisIDs[3] = joystick + 4;
|
||||
mJoystickType = joystick;
|
||||
|
||||
mPreferences = prefsHandle;
|
||||
mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
|
||||
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
|
||||
mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed);
|
||||
mBoundsBoxBitmap = new BitmapDrawable(res, bitmapOuter);
|
||||
mWidth = bitmapOuter.getWidth();
|
||||
mHeight = bitmapOuter.getHeight();
|
||||
mPreferences = prefsHandle;
|
||||
mOuterBitmap = new BitmapDrawable(res, bitmapOuter);
|
||||
mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault);
|
||||
mPressedStateInnerBitmap = new BitmapDrawable(res, bitmapInnerPressed);
|
||||
mBoundsBoxBitmap = new BitmapDrawable(res, bitmapOuter);
|
||||
mWidth = bitmapOuter.getWidth();
|
||||
mHeight = bitmapOuter.getHeight();
|
||||
|
||||
setBounds(rectOuter);
|
||||
mDefaultStateInnerBitmap.setBounds(rectInner);
|
||||
mPressedStateInnerBitmap.setBounds(rectInner);
|
||||
mVirtBounds = getBounds();
|
||||
mOrigBounds = mOuterBitmap.copyBounds();
|
||||
mBoundsBoxBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
SetInnerBounds();
|
||||
}
|
||||
setBounds(rectOuter);
|
||||
mDefaultStateInnerBitmap.setBounds(rectInner);
|
||||
mPressedStateInnerBitmap.setBounds(rectInner);
|
||||
mVirtBounds = getBounds();
|
||||
mOrigBounds = mOuterBitmap.copyBounds();
|
||||
mBoundsBoxBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
SetInnerBounds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this InputOverlayDrawableJoystick's button ID.
|
||||
*
|
||||
* @return this InputOverlayDrawableJoystick's button ID.
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return mJoystickType;
|
||||
}
|
||||
/**
|
||||
* Gets this InputOverlayDrawableJoystick's button ID.
|
||||
*
|
||||
* @return this InputOverlayDrawableJoystick's button ID.
|
||||
*/
|
||||
public int getId()
|
||||
{
|
||||
return mJoystickType;
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
mOuterBitmap.draw(canvas);
|
||||
getCurrentStateBitmapDrawable().draw(canvas);
|
||||
mBoundsBoxBitmap.draw(canvas);
|
||||
}
|
||||
public void draw(Canvas canvas)
|
||||
{
|
||||
mOuterBitmap.draw(canvas);
|
||||
getCurrentStateBitmapDrawable().draw(canvas);
|
||||
mBoundsBoxBitmap.draw(canvas);
|
||||
}
|
||||
|
||||
public void TrackEvent(MotionEvent event)
|
||||
{
|
||||
boolean reCenter = mPreferences.getBoolean("joystickRelCenter", true);
|
||||
int pointerIndex = event.getActionIndex();
|
||||
public void TrackEvent(MotionEvent event)
|
||||
{
|
||||
boolean reCenter = mPreferences.getBoolean("joystickRelCenter", true);
|
||||
int pointerIndex = event.getActionIndex();
|
||||
|
||||
switch(event.getAction() & MotionEvent.ACTION_MASK)
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
|
||||
{
|
||||
mPressedState = true;
|
||||
mOuterBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setAlpha(255);
|
||||
if (reCenter)
|
||||
{
|
||||
getVirtBounds().offset((int)event.getX(pointerIndex) - getVirtBounds().centerX(), (int)event.getY(pointerIndex) - getVirtBounds().centerY());
|
||||
}
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
trackId = event.getPointerId(pointerIndex);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (trackId == event.getPointerId(pointerIndex))
|
||||
{
|
||||
mPressedState = false;
|
||||
axises[0] = axises[1] = 0.0f;
|
||||
mOuterBitmap.setAlpha(255);
|
||||
mBoundsBoxBitmap.setAlpha(0);
|
||||
setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, mOrigBounds.bottom));
|
||||
setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, mOrigBounds.bottom));
|
||||
SetInnerBounds();
|
||||
trackId = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK)
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex)))
|
||||
{
|
||||
mPressedState = true;
|
||||
mOuterBitmap.setAlpha(0);
|
||||
mBoundsBoxBitmap.setAlpha(255);
|
||||
if (reCenter)
|
||||
{
|
||||
getVirtBounds().offset((int) event.getX(pointerIndex) - getVirtBounds().centerX(),
|
||||
(int) event.getY(pointerIndex) - getVirtBounds().centerY());
|
||||
}
|
||||
mBoundsBoxBitmap.setBounds(getVirtBounds());
|
||||
trackId = event.getPointerId(pointerIndex);
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
if (trackId == event.getPointerId(pointerIndex))
|
||||
{
|
||||
mPressedState = false;
|
||||
axises[0] = axises[1] = 0.0f;
|
||||
mOuterBitmap.setAlpha(255);
|
||||
mBoundsBoxBitmap.setAlpha(0);
|
||||
setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right,
|
||||
mOrigBounds.bottom));
|
||||
setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right,
|
||||
mOrigBounds.bottom));
|
||||
SetInnerBounds();
|
||||
trackId = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (trackId == -1)
|
||||
return;
|
||||
if (trackId == -1)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < event.getPointerCount(); i++)
|
||||
{
|
||||
if (trackId == event.getPointerId(i))
|
||||
{
|
||||
float touchX = event.getX(i);
|
||||
float touchY = event.getY(i);
|
||||
float maxY = getVirtBounds().bottom;
|
||||
float maxX = getVirtBounds().right;
|
||||
touchX -= getVirtBounds().centerX();
|
||||
maxX -= getVirtBounds().centerX();
|
||||
touchY -= getVirtBounds().centerY();
|
||||
maxY -= getVirtBounds().centerY();
|
||||
final float AxisX = touchX / maxX;
|
||||
final float AxisY = touchY / maxY;
|
||||
axises[0] = AxisY;
|
||||
axises[1] = AxisX;
|
||||
for (int i = 0; i < event.getPointerCount(); i++)
|
||||
{
|
||||
if (trackId == event.getPointerId(i))
|
||||
{
|
||||
float touchX = event.getX(i);
|
||||
float touchY = event.getY(i);
|
||||
float maxY = getVirtBounds().bottom;
|
||||
float maxX = getVirtBounds().right;
|
||||
touchX -= getVirtBounds().centerX();
|
||||
maxX -= getVirtBounds().centerX();
|
||||
touchY -= getVirtBounds().centerY();
|
||||
maxY -= getVirtBounds().centerY();
|
||||
final float AxisX = touchX / maxX;
|
||||
final float AxisY = touchY / maxY;
|
||||
axises[0] = AxisY;
|
||||
axises[1] = AxisX;
|
||||
|
||||
SetInnerBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
SetInnerBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int)event.getX(pointerIndex);
|
||||
int fingerPositionY = (int)event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int deltaX = fingerPositionX - mPreviousTouchX;
|
||||
int deltaY = fingerPositionY - mPreviousTouchY;
|
||||
mControlPositionX += deltaX;
|
||||
mControlPositionY += deltaY;
|
||||
setBounds(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
|
||||
setVirtBounds(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
|
||||
SetInnerBounds();
|
||||
setOrigBounds(new Rect(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY)));
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public boolean onConfigureTouch(MotionEvent event)
|
||||
{
|
||||
int pointerIndex = event.getActionIndex();
|
||||
int fingerPositionX = (int) event.getX(pointerIndex);
|
||||
int fingerPositionY = (int) event.getY(pointerIndex);
|
||||
switch (event.getAction())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
int deltaX = fingerPositionX - mPreviousTouchX;
|
||||
int deltaY = fingerPositionY - mPreviousTouchY;
|
||||
mControlPositionX += deltaX;
|
||||
mControlPositionY += deltaY;
|
||||
setBounds(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
|
||||
setVirtBounds(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY));
|
||||
SetInnerBounds();
|
||||
setOrigBounds(new Rect(new Rect(mControlPositionX, mControlPositionY,
|
||||
mOuterBitmap.getIntrinsicWidth() + mControlPositionX,
|
||||
mOuterBitmap.getIntrinsicHeight() + mControlPositionY)));
|
||||
mPreviousTouchX = fingerPositionX;
|
||||
mPreviousTouchY = fingerPositionY;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public float[] getAxisValues()
|
||||
{
|
||||
float[] joyaxises = {0f, 0f, 0f, 0f};
|
||||
joyaxises[1] = Math.min(axises[0], 1.0f);
|
||||
joyaxises[0] = Math.min(axises[0], 0.0f);
|
||||
joyaxises[3] = Math.min(axises[1], 1.0f);
|
||||
joyaxises[2] = Math.min(axises[1], 0.0f);
|
||||
return joyaxises;
|
||||
}
|
||||
public float[] getAxisValues()
|
||||
{
|
||||
float[] joyaxises = {0f, 0f, 0f, 0f};
|
||||
joyaxises[1] = Math.min(axises[0], 1.0f);
|
||||
joyaxises[0] = Math.min(axises[0], 0.0f);
|
||||
joyaxises[3] = Math.min(axises[1], 1.0f);
|
||||
joyaxises[2] = Math.min(axises[1], 0.0f);
|
||||
return joyaxises;
|
||||
}
|
||||
|
||||
public int[] getAxisIDs()
|
||||
{
|
||||
return axisIDs;
|
||||
}
|
||||
public int[] getAxisIDs()
|
||||
{
|
||||
return axisIDs;
|
||||
}
|
||||
|
||||
private void SetInnerBounds()
|
||||
{
|
||||
int X = getVirtBounds().centerX() + (int)((axises[1]) * (getVirtBounds().width() / 2));
|
||||
int Y = getVirtBounds().centerY() + (int)((axises[0]) * (getVirtBounds().height() / 2));
|
||||
private void SetInnerBounds()
|
||||
{
|
||||
int X = getVirtBounds().centerX() + (int) ((axises[1]) * (getVirtBounds().width() / 2));
|
||||
int Y = getVirtBounds().centerY() + (int) ((axises[0]) * (getVirtBounds().height() / 2));
|
||||
|
||||
if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() + (getVirtBounds().width() / 2);
|
||||
if (X < getVirtBounds().centerX() - (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() - (getVirtBounds().width() / 2);
|
||||
if (Y > getVirtBounds().centerY() + (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() + (getVirtBounds().height() / 2);
|
||||
if (Y < getVirtBounds().centerY() - (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() - (getVirtBounds().height() / 2);
|
||||
if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() + (getVirtBounds().width() / 2);
|
||||
if (X < getVirtBounds().centerX() - (getVirtBounds().width() / 2))
|
||||
X = getVirtBounds().centerX() - (getVirtBounds().width() / 2);
|
||||
if (Y > getVirtBounds().centerY() + (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() + (getVirtBounds().height() / 2);
|
||||
if (Y < getVirtBounds().centerY() - (getVirtBounds().height() / 2))
|
||||
Y = getVirtBounds().centerY() - (getVirtBounds().height() / 2);
|
||||
|
||||
int width = mPressedStateInnerBitmap.getBounds().width() / 2;
|
||||
int height = mPressedStateInnerBitmap.getBounds().height() / 2;
|
||||
mDefaultStateInnerBitmap.setBounds(X - width, Y - height, X + width, Y + height);
|
||||
mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds());
|
||||
}
|
||||
int width = mPressedStateInnerBitmap.getBounds().width() / 2;
|
||||
int height = mPressedStateInnerBitmap.getBounds().height() / 2;
|
||||
mDefaultStateInnerBitmap.setBounds(X - width, Y - height, X + width, Y + height);
|
||||
mPressedStateInnerBitmap.setBounds(mDefaultStateInnerBitmap.getBounds());
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
mControlPositionX = x;
|
||||
mControlPositionY = y;
|
||||
}
|
||||
|
||||
private BitmapDrawable getCurrentStateBitmapDrawable()
|
||||
{
|
||||
return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap;
|
||||
}
|
||||
private BitmapDrawable getCurrentStateBitmapDrawable()
|
||||
{
|
||||
return mPressedState ? mPressedStateInnerBitmap : mDefaultStateInnerBitmap;
|
||||
}
|
||||
|
||||
public void setBounds(Rect bounds)
|
||||
{
|
||||
mOuterBitmap.setBounds(bounds);
|
||||
}
|
||||
public void setBounds(Rect bounds)
|
||||
{
|
||||
mOuterBitmap.setBounds(bounds);
|
||||
}
|
||||
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mOuterBitmap.getBounds();
|
||||
}
|
||||
public Rect getBounds()
|
||||
{
|
||||
return mOuterBitmap.getBounds();
|
||||
}
|
||||
|
||||
private void setVirtBounds(Rect bounds) { mVirtBounds = bounds; }
|
||||
private void setVirtBounds(Rect bounds)
|
||||
{
|
||||
mVirtBounds = bounds;
|
||||
}
|
||||
|
||||
private void setOrigBounds(Rect bounds) { mOrigBounds = bounds; }
|
||||
private void setOrigBounds(Rect bounds)
|
||||
{
|
||||
mOrigBounds = bounds;
|
||||
}
|
||||
|
||||
private Rect getVirtBounds() { return mVirtBounds; }
|
||||
private Rect getVirtBounds()
|
||||
{
|
||||
return mVirtBounds;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
public int getWidth()
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
public int getHeight()
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,231 +32,239 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
*/
|
||||
public final class DirectoryInitializationService extends IntentService
|
||||
{
|
||||
public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION";
|
||||
public static final String BROADCAST_ACTION =
|
||||
"org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION";
|
||||
|
||||
public static final String EXTRA_STATE = "directoryState";
|
||||
private static volatile DirectoryInitializationState directoryState = null;
|
||||
private static String userPath;
|
||||
private static String internalPath;
|
||||
private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false);
|
||||
public static final String EXTRA_STATE = "directoryState";
|
||||
private static volatile DirectoryInitializationState directoryState = null;
|
||||
private static String userPath;
|
||||
private static String internalPath;
|
||||
private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false);
|
||||
|
||||
public enum DirectoryInitializationState
|
||||
public enum DirectoryInitializationState
|
||||
{
|
||||
DOLPHIN_DIRECTORIES_INITIALIZED,
|
||||
EXTERNAL_STORAGE_PERMISSION_NEEDED,
|
||||
CANT_FIND_EXTERNAL_STORAGE
|
||||
}
|
||||
|
||||
public DirectoryInitializationService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("DirectoryInitializationService");
|
||||
}
|
||||
|
||||
public static void startService(Context context)
|
||||
{
|
||||
Intent intent = new Intent(context, DirectoryInitializationService.class);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
isDolphinDirectoryInitializationRunning.set(true);
|
||||
|
||||
if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
DOLPHIN_DIRECTORIES_INITIALIZED,
|
||||
EXTERNAL_STORAGE_PERMISSION_NEEDED,
|
||||
CANT_FIND_EXTERNAL_STORAGE
|
||||
}
|
||||
|
||||
public DirectoryInitializationService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("DirectoryInitializationService");
|
||||
}
|
||||
|
||||
public static void startService(Context context)
|
||||
{
|
||||
Intent intent = new Intent(context, DirectoryInitializationService.class);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
isDolphinDirectoryInitializationRunning.set(true);
|
||||
|
||||
if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
if (setDolphinUserDirectory())
|
||||
{
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
if (setDolphinUserDirectory())
|
||||
{
|
||||
initializeInternalStorage();
|
||||
initializeExternalStorage();
|
||||
initializeInternalStorage();
|
||||
initializeExternalStorage();
|
||||
|
||||
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
}
|
||||
else
|
||||
{
|
||||
directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
directoryState = DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED;
|
||||
}
|
||||
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
}
|
||||
|
||||
isDolphinDirectoryInitializationRunning.set(false);
|
||||
sendBroadcastState(directoryState);
|
||||
else
|
||||
{
|
||||
directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
directoryState = DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean setDolphinUserDirectory()
|
||||
isDolphinDirectoryInitializationRunning.set(false);
|
||||
sendBroadcastState(directoryState);
|
||||
}
|
||||
|
||||
private boolean setDolphinUserDirectory()
|
||||
{
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
|
||||
{
|
||||
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
|
||||
{
|
||||
File externalPath = Environment.getExternalStorageDirectory();
|
||||
if (externalPath != null)
|
||||
{
|
||||
userPath = externalPath.getAbsolutePath() + "/dolphin-emu";
|
||||
Log.debug("[DirectoryInitializationService] User Dir: " + userPath);
|
||||
NativeLibrary.SetUserDirectory(userPath);
|
||||
return true;
|
||||
}
|
||||
File externalPath = Environment.getExternalStorageDirectory();
|
||||
if (externalPath != null)
|
||||
{
|
||||
userPath = externalPath.getAbsolutePath() + "/dolphin-emu";
|
||||
Log.debug("[DirectoryInitializationService] User Dir: " + userPath);
|
||||
NativeLibrary.SetUserDirectory(userPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initializeInternalStorage()
|
||||
return false;
|
||||
}
|
||||
|
||||
private void initializeInternalStorage()
|
||||
{
|
||||
File sysDirectory = new File(getFilesDir(), "Sys");
|
||||
internalPath = sysDirectory.getAbsolutePath();
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String revision = NativeLibrary.GetGitRevision();
|
||||
if (!preferences.getString("sysDirectoryVersion", "").equals(revision))
|
||||
{
|
||||
File sysDirectory = new File(getFilesDir(), "Sys");
|
||||
internalPath = sysDirectory.getAbsolutePath();
|
||||
// There is no extracted Sys directory, or there is a Sys directory from another
|
||||
// version of Dolphin that might contain outdated files. Let's (re-)extract Sys.
|
||||
deleteDirectoryRecursively(sysDirectory);
|
||||
copyAssetFolder("Sys", sysDirectory, true);
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
String revision = NativeLibrary.GetGitRevision();
|
||||
if (!preferences.getString("sysDirectoryVersion", "").equals(revision))
|
||||
{
|
||||
// There is no extracted Sys directory, or there is a Sys directory from another
|
||||
// version of Dolphin that might contain outdated files. Let's (re-)extract Sys.
|
||||
deleteDirectoryRecursively(sysDirectory);
|
||||
copyAssetFolder("Sys", sysDirectory, true);
|
||||
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString("sysDirectoryVersion", revision);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
// Let the native code know where the Sys directory is.
|
||||
SetSysDirectory(sysDirectory.getPath());
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString("sysDirectoryVersion", revision);
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void initializeExternalStorage()
|
||||
// Let the native code know where the Sys directory is.
|
||||
SetSysDirectory(sysDirectory.getPath());
|
||||
}
|
||||
|
||||
private void initializeExternalStorage()
|
||||
{
|
||||
// Create User directory structure and copy some NAND files from the extracted Sys directory.
|
||||
CreateUserDirectories();
|
||||
|
||||
// GCPadNew.ini and WiimoteNew.ini must contain specific values in order for controller
|
||||
// input to work as intended (they aren't user configurable), so we overwrite them just
|
||||
// in case the user has tried to modify them manually.
|
||||
//
|
||||
// ...Except WiimoteNew.ini contains the user configurable settings for Wii Remote
|
||||
// extensions in addition to all of its lines that aren't user configurable, so since we
|
||||
// don't want to lose the selected extensions, we don't overwrite that file if it exists.
|
||||
//
|
||||
// TODO: Redo the Android controller system so that we don't have to extract these INIs.
|
||||
String configDirectory = NativeLibrary.GetUserDirectory() + File.separator + "Config";
|
||||
copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true);
|
||||
copyAsset("WiimoteNew.ini", new File(configDirectory, "WiimoteNew.ini"), false);
|
||||
}
|
||||
|
||||
private static void deleteDirectoryRecursively(File file)
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
// Create User directory structure and copy some NAND files from the extracted Sys directory.
|
||||
CreateUserDirectories();
|
||||
|
||||
// GCPadNew.ini and WiimoteNew.ini must contain specific values in order for controller
|
||||
// input to work as intended (they aren't user configurable), so we overwrite them just
|
||||
// in case the user has tried to modify them manually.
|
||||
//
|
||||
// ...Except WiimoteNew.ini contains the user configurable settings for Wii Remote
|
||||
// extensions in addition to all of its lines that aren't user configurable, so since we
|
||||
// don't want to lose the selected extensions, we don't overwrite that file if it exists.
|
||||
//
|
||||
// TODO: Redo the Android controller system so that we don't have to extract these INIs.
|
||||
String configDirectory = NativeLibrary.GetUserDirectory() + File.separator + "Config";
|
||||
copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true);
|
||||
copyAsset("WiimoteNew.ini", new File(configDirectory,"WiimoteNew.ini"), false);
|
||||
for (File child : file.listFiles())
|
||||
deleteDirectoryRecursively(child);
|
||||
}
|
||||
file.delete();
|
||||
}
|
||||
|
||||
private static void deleteDirectoryRecursively(File file)
|
||||
public static boolean areDolphinDirectoriesReady()
|
||||
{
|
||||
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
}
|
||||
|
||||
public static String getUserDirectory()
|
||||
{
|
||||
if (directoryState == null)
|
||||
{
|
||||
if (file.isDirectory())
|
||||
{
|
||||
for (File child : file.listFiles())
|
||||
deleteDirectoryRecursively(child);
|
||||
}
|
||||
file.delete();
|
||||
throw new IllegalStateException("DirectoryInitializationService has to run at least once!");
|
||||
}
|
||||
|
||||
public static boolean areDolphinDirectoriesReady()
|
||||
else if (isDolphinDirectoryInitializationRunning.get())
|
||||
{
|
||||
return directoryState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
|
||||
throw new IllegalStateException(
|
||||
"DirectoryInitializationService has to finish running first!");
|
||||
}
|
||||
return userPath;
|
||||
|
||||
public static String getUserDirectory()
|
||||
}
|
||||
|
||||
public static String getDolphinInternalDirectory()
|
||||
{
|
||||
if (directoryState == null)
|
||||
{
|
||||
if (directoryState == null)
|
||||
{
|
||||
throw new IllegalStateException("DirectoryInitializationService has to run at least once!");
|
||||
}
|
||||
else if (isDolphinDirectoryInitializationRunning.get())
|
||||
{
|
||||
throw new IllegalStateException("DirectoryInitializationService has to finish running first!");
|
||||
}
|
||||
return userPath;
|
||||
|
||||
throw new IllegalStateException("DirectoryInitializationService has to run at least once!");
|
||||
}
|
||||
|
||||
public static String getDolphinInternalDirectory()
|
||||
else if (isDolphinDirectoryInitializationRunning.get())
|
||||
{
|
||||
if (directoryState == null)
|
||||
{
|
||||
throw new IllegalStateException("DirectoryInitializationService has to run at least once!");
|
||||
}
|
||||
else if (isDolphinDirectoryInitializationRunning.get())
|
||||
{
|
||||
throw new IllegalStateException("DirectoryInitializationService has to finish running first!");
|
||||
}
|
||||
return internalPath;
|
||||
|
||||
throw new IllegalStateException(
|
||||
"DirectoryInitializationService has to finish running first!");
|
||||
}
|
||||
return internalPath;
|
||||
|
||||
private void sendBroadcastState(DirectoryInitializationState state)
|
||||
}
|
||||
|
||||
private void sendBroadcastState(DirectoryInitializationState state)
|
||||
{
|
||||
Intent localIntent =
|
||||
new Intent(BROADCAST_ACTION)
|
||||
.putExtra(EXTRA_STATE, state);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
|
||||
}
|
||||
|
||||
private void copyAsset(String asset, File output, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output);
|
||||
|
||||
try
|
||||
{
|
||||
Intent localIntent =
|
||||
new Intent(BROADCAST_ACTION)
|
||||
.putExtra(EXTRA_STATE, state);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
|
||||
if (!output.exists() || overwrite)
|
||||
{
|
||||
InputStream in = getAssets().open(asset);
|
||||
OutputStream out = new FileOutputStream(output);
|
||||
copyFile(in, out);
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void copyAsset(String asset, File output, Boolean overwrite)
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output);
|
||||
|
||||
try
|
||||
{
|
||||
if (!output.exists() || overwrite)
|
||||
{
|
||||
InputStream in = getAssets().open(asset);
|
||||
OutputStream out = new FileOutputStream(output);
|
||||
copyFile(in, out);
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset file: " + asset + e.getMessage());
|
||||
}
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset file: " + asset +
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite)
|
||||
private void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite)
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " +
|
||||
outputFolder);
|
||||
|
||||
try
|
||||
{
|
||||
Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " + outputFolder);
|
||||
|
||||
try
|
||||
boolean createdFolder = false;
|
||||
for (String file : getAssets().list(assetFolder))
|
||||
{
|
||||
if (!createdFolder)
|
||||
{
|
||||
boolean createdFolder = false;
|
||||
for (String file : getAssets().list(assetFolder))
|
||||
{
|
||||
if (!createdFolder)
|
||||
{
|
||||
outputFolder.mkdir();
|
||||
createdFolder = true;
|
||||
}
|
||||
copyAssetFolder(assetFolder + File.separator + file, new File(outputFolder, file), overwrite);
|
||||
copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset folder: " + assetFolder + e.getMessage());
|
||||
outputFolder.mkdir();
|
||||
createdFolder = true;
|
||||
}
|
||||
copyAssetFolder(assetFolder + File.separator + file, new File(outputFolder, file),
|
||||
overwrite);
|
||||
copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFile(InputStream in, OutputStream out) throws IOException
|
||||
catch (IOException e)
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
Log.error("[DirectoryInitializationService] Failed to copy asset folder: " + assetFolder +
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static native void CreateUserDirectories();
|
||||
private static native void SetSysDirectory(String path);
|
||||
private void copyFile(InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
|
||||
while ((read = in.read(buffer)) != -1)
|
||||
{
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
|
||||
private static native void CreateUserDirectories();
|
||||
|
||||
private static native void SetSysDirectory(String path);
|
||||
}
|
||||
|
|
|
@ -20,117 +20,117 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
*/
|
||||
public final class GameFileCacheService extends IntentService
|
||||
{
|
||||
public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED";
|
||||
public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED";
|
||||
|
||||
private static final String ACTION_LOAD = "org.dolphinemu.dolphinemu.LOAD_GAME_FILE_CACHE";
|
||||
private static final String ACTION_RESCAN = "org.dolphinemu.dolphinemu.RESCAN_GAME_FILE_CACHE";
|
||||
private static final String ACTION_LOAD = "org.dolphinemu.dolphinemu.LOAD_GAME_FILE_CACHE";
|
||||
private static final String ACTION_RESCAN = "org.dolphinemu.dolphinemu.RESCAN_GAME_FILE_CACHE";
|
||||
|
||||
private static GameFileCache gameFileCache = null;
|
||||
private static AtomicReference<GameFile[]> gameFiles = new AtomicReference<>(new GameFile[]{});
|
||||
private static GameFileCache gameFileCache = null;
|
||||
private static AtomicReference<GameFile[]> gameFiles = new AtomicReference<>(new GameFile[]{});
|
||||
|
||||
public GameFileCacheService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("GameFileCacheService");
|
||||
}
|
||||
public GameFileCacheService()
|
||||
{
|
||||
// Superclass constructor is called to name the thread on which this service executes.
|
||||
super("GameFileCacheService");
|
||||
}
|
||||
|
||||
public static List<GameFile> getGameFilesForPlatform(Platform platform)
|
||||
{
|
||||
GameFile[] allGames = gameFiles.get();
|
||||
ArrayList<GameFile> platformGames = new ArrayList<>();
|
||||
for (GameFile game : allGames)
|
||||
{
|
||||
if (Platform.fromNativeInt(game.getPlatform()) == platform)
|
||||
{
|
||||
platformGames.add(game);
|
||||
}
|
||||
}
|
||||
return platformGames;
|
||||
}
|
||||
public static List<GameFile> getGameFilesForPlatform(Platform platform)
|
||||
{
|
||||
GameFile[] allGames = gameFiles.get();
|
||||
ArrayList<GameFile> platformGames = new ArrayList<>();
|
||||
for (GameFile game : allGames)
|
||||
{
|
||||
if (Platform.fromNativeInt(game.getPlatform()) == platform)
|
||||
{
|
||||
platformGames.add(game);
|
||||
}
|
||||
}
|
||||
return platformGames;
|
||||
}
|
||||
|
||||
public static GameFile getGameFileByGameId(String gameId)
|
||||
{
|
||||
GameFile[] allGames = gameFiles.get();
|
||||
for (GameFile game : allGames)
|
||||
{
|
||||
if (game.getGameId().equals(gameId))
|
||||
{
|
||||
return game;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static GameFile getGameFileByGameId(String gameId)
|
||||
{
|
||||
GameFile[] allGames = gameFiles.get();
|
||||
for (GameFile game : allGames)
|
||||
{
|
||||
if (game.getGameId().equals(gameId))
|
||||
{
|
||||
return game;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void startService(Context context, String action)
|
||||
{
|
||||
Intent intent = new Intent(context, GameFileCacheService.class);
|
||||
intent.setAction(action);
|
||||
context.startService(intent);
|
||||
}
|
||||
private static void startService(Context context, String action)
|
||||
{
|
||||
Intent intent = new Intent(context, GameFileCacheService.class);
|
||||
intent.setAction(action);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously loads the game file cache from disk without checking
|
||||
* which games are present on the file system.
|
||||
*/
|
||||
public static void startLoad(Context context)
|
||||
{
|
||||
startService(context, ACTION_LOAD);
|
||||
}
|
||||
/**
|
||||
* Asynchronously loads the game file cache from disk without checking
|
||||
* which games are present on the file system.
|
||||
*/
|
||||
public static void startLoad(Context context)
|
||||
{
|
||||
startService(context, ACTION_LOAD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously scans for games in the user's configured folders,
|
||||
* updating the game file cache with the results.
|
||||
* If startLoad hasn't been called before this, this has no effect.
|
||||
*/
|
||||
public static void startRescan(Context context)
|
||||
{
|
||||
startService(context, ACTION_RESCAN);
|
||||
}
|
||||
/**
|
||||
* Asynchronously scans for games in the user's configured folders,
|
||||
* updating the game file cache with the results.
|
||||
* If startLoad hasn't been called before this, this has no effect.
|
||||
*/
|
||||
public static void startRescan(Context context)
|
||||
{
|
||||
startService(context, ACTION_RESCAN);
|
||||
}
|
||||
|
||||
public static GameFile addOrGet(String gamePath)
|
||||
{
|
||||
// The existence of this one function, which is called from one
|
||||
// single place, forces us to use synchronization in onHandleIntent...
|
||||
// A bit annoying, but should be good enough for now
|
||||
synchronized (gameFileCache)
|
||||
{
|
||||
return gameFileCache.addOrGet(gamePath);
|
||||
}
|
||||
}
|
||||
public static GameFile addOrGet(String gamePath)
|
||||
{
|
||||
// The existence of this one function, which is called from one
|
||||
// single place, forces us to use synchronization in onHandleIntent...
|
||||
// A bit annoying, but should be good enough for now
|
||||
synchronized (gameFileCache)
|
||||
{
|
||||
return gameFileCache.addOrGet(gamePath);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
// Load the game list cache if it isn't already loaded, otherwise do nothing
|
||||
if (ACTION_LOAD.equals(intent.getAction()) && gameFileCache == null)
|
||||
{
|
||||
GameFileCache temp = new GameFileCache(getCacheDir() + File.separator + "gamelist.cache");
|
||||
synchronized (temp)
|
||||
{
|
||||
gameFileCache = temp;
|
||||
gameFileCache.load();
|
||||
updateGameFileArray();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
// Load the game list cache if it isn't already loaded, otherwise do nothing
|
||||
if (ACTION_LOAD.equals(intent.getAction()) && gameFileCache == null)
|
||||
{
|
||||
GameFileCache temp = new GameFileCache(getCacheDir() + File.separator + "gamelist.cache");
|
||||
synchronized (temp)
|
||||
{
|
||||
gameFileCache = temp;
|
||||
gameFileCache.load();
|
||||
updateGameFileArray();
|
||||
}
|
||||
}
|
||||
|
||||
// Rescan the file system and update the game list cache with the results
|
||||
if (ACTION_RESCAN.equals(intent.getAction()) && gameFileCache != null)
|
||||
{
|
||||
synchronized (gameFileCache)
|
||||
{
|
||||
if (gameFileCache.scanLibrary(this))
|
||||
{
|
||||
updateGameFileArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rescan the file system and update the game list cache with the results
|
||||
if (ACTION_RESCAN.equals(intent.getAction()) && gameFileCache != null)
|
||||
{
|
||||
synchronized (gameFileCache)
|
||||
{
|
||||
if (gameFileCache.scanLibrary(this))
|
||||
{
|
||||
updateGameFileArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGameFileArray()
|
||||
{
|
||||
GameFile[] gameFilesTemp = gameFileCache.getAllGames();
|
||||
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
|
||||
gameFiles.set(gameFilesTemp);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION));
|
||||
}
|
||||
private void updateGameFileArray()
|
||||
{
|
||||
GameFile[] gameFilesTemp = gameFileCache.getAllGames();
|
||||
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
|
||||
gameFiles.set(gameFilesTemp);
|
||||
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,142 +25,143 @@ import java.util.List;
|
|||
|
||||
public class SyncChannelJobService extends JobService
|
||||
{
|
||||
private static final String TAG = "ChannelJobSvc";
|
||||
private static final String TAG = "ChannelJobSvc";
|
||||
|
||||
private SyncChannelTask mSyncChannelTask;
|
||||
private SyncChannelTask mSyncChannelTask;
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(final JobParameters jobParameters)
|
||||
{
|
||||
Log.d(TAG, "Starting channel creation job");
|
||||
mSyncChannelTask =
|
||||
new SyncChannelTask(getApplicationContext())
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success)
|
||||
{
|
||||
super.onPostExecute(success);
|
||||
jobFinished(jobParameters, !success);
|
||||
}
|
||||
};
|
||||
mSyncChannelTask.execute();
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onStartJob(final JobParameters jobParameters)
|
||||
{
|
||||
Log.d(TAG, "Starting channel creation job");
|
||||
mSyncChannelTask =
|
||||
new SyncChannelTask(getApplicationContext())
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success)
|
||||
{
|
||||
super.onPostExecute(success);
|
||||
jobFinished(jobParameters, !success);
|
||||
}
|
||||
};
|
||||
mSyncChannelTask.execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters jobParameters)
|
||||
{
|
||||
if (mSyncChannelTask != null)
|
||||
{
|
||||
mSyncChannelTask.cancel(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters jobParameters)
|
||||
{
|
||||
if (mSyncChannelTask != null)
|
||||
{
|
||||
mSyncChannelTask.cancel(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class SyncChannelTask extends AsyncTask<Void, Void, Boolean>
|
||||
{
|
||||
private Context context;
|
||||
private static class SyncChannelTask extends AsyncTask<Void, Void, Boolean>
|
||||
{
|
||||
private Context context;
|
||||
|
||||
SyncChannelTask(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
SyncChannelTask(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup channels
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids)
|
||||
{
|
||||
List<HomeScreenChannel> subscriptions;
|
||||
List<Channel> channels = TvUtil.getAllChannels(context);
|
||||
List<Long> channelIds = new ArrayList<>();
|
||||
// Checks if the default channels are added.
|
||||
// If not, create the channels
|
||||
if (!channels.isEmpty())
|
||||
{
|
||||
channels.forEach(channel -> channelIds.add(channel.getId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
subscriptions = TvUtil.createUniversalSubscriptions();
|
||||
for (HomeScreenChannel subscription : subscriptions)
|
||||
{
|
||||
long channelId = createChannel(subscription);
|
||||
channelIds.add(channelId);
|
||||
subscription.setChannelId(channelId);
|
||||
// Only the first channel added can be browsable without user intervention.
|
||||
TvContractCompat.requestChannelBrowsable(context, channelId);
|
||||
}
|
||||
}
|
||||
// Schedule triggers to update programs
|
||||
channelIds.forEach(channel -> TvUtil.scheduleSyncingProgramsForChannel(context, channel));
|
||||
// Update all channels
|
||||
TvUtil.updateAllChannels(context);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Setup channels
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids)
|
||||
{
|
||||
List<HomeScreenChannel> subscriptions;
|
||||
List<Channel> channels = TvUtil.getAllChannels(context);
|
||||
List<Long> channelIds = new ArrayList<>();
|
||||
// Checks if the default channels are added.
|
||||
// If not, create the channels
|
||||
if (!channels.isEmpty())
|
||||
{
|
||||
channels.forEach(channel -> channelIds.add(channel.getId()));
|
||||
}
|
||||
else
|
||||
{
|
||||
subscriptions = TvUtil.createUniversalSubscriptions();
|
||||
for (HomeScreenChannel subscription : subscriptions)
|
||||
{
|
||||
long channelId = createChannel(subscription);
|
||||
channelIds.add(channelId);
|
||||
subscription.setChannelId(channelId);
|
||||
// Only the first channel added can be browsable without user intervention.
|
||||
TvContractCompat.requestChannelBrowsable(context, channelId);
|
||||
}
|
||||
}
|
||||
// Schedule triggers to update programs
|
||||
channelIds.forEach(channel -> TvUtil.scheduleSyncingProgramsForChannel(context, channel));
|
||||
// Update all channels
|
||||
TvUtil.updateAllChannels(context);
|
||||
return true;
|
||||
}
|
||||
|
||||
private long createChannel(HomeScreenChannel subscription)
|
||||
{
|
||||
long channelId = getChannelIdFromTvProvider(context, subscription);
|
||||
if (channelId != -1L)
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
private long createChannel(HomeScreenChannel subscription)
|
||||
{
|
||||
long channelId = getChannelIdFromTvProvider(context, subscription);
|
||||
if (channelId != -1L)
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
|
||||
// Create the channel since it has not been added to the TV Provider.
|
||||
Uri appLinkIntentUri = Uri.parse(subscription.getAppLinkIntentUri());
|
||||
// Create the channel since it has not been added to the TV Provider.
|
||||
Uri appLinkIntentUri = Uri.parse(subscription.getAppLinkIntentUri());
|
||||
|
||||
Channel.Builder builder = new Channel.Builder();
|
||||
builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
|
||||
.setDisplayName(subscription.getName())
|
||||
.setDescription(subscription.getDescription())
|
||||
.setAppLinkIntentUri(appLinkIntentUri);
|
||||
Channel.Builder builder = new Channel.Builder();
|
||||
builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
|
||||
.setDisplayName(subscription.getName())
|
||||
.setDescription(subscription.getDescription())
|
||||
.setAppLinkIntentUri(appLinkIntentUri);
|
||||
|
||||
Log.d(TAG, "Creating channel: " + subscription.getName());
|
||||
Uri channelUrl =
|
||||
context.getContentResolver()
|
||||
.insert(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
builder.build().toContentValues());
|
||||
Log.d(TAG, "Creating channel: " + subscription.getName());
|
||||
Uri channelUrl =
|
||||
context.getContentResolver()
|
||||
.insert(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
builder.build().toContentValues());
|
||||
|
||||
channelId = ContentUris.parseId(channelUrl);
|
||||
Bitmap bitmap = TvUtil.convertToBitmap(context, R.drawable.ic_launcher);
|
||||
ChannelLogoUtils.storeChannelLogo(context, channelId, bitmap);
|
||||
channelId = ContentUris.parseId(channelUrl);
|
||||
Bitmap bitmap = TvUtil.convertToBitmap(context, R.drawable.ic_launcher);
|
||||
ChannelLogoUtils.storeChannelLogo(context, channelId, bitmap);
|
||||
|
||||
return channelId;
|
||||
}
|
||||
return channelId;
|
||||
}
|
||||
|
||||
private long getChannelIdFromTvProvider(Context context, HomeScreenChannel subscription)
|
||||
{
|
||||
Cursor cursor =
|
||||
context.getContentResolver().query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
new String[]{
|
||||
TvContractCompat.Channels._ID,
|
||||
TvContract.Channels.COLUMN_DISPLAY_NAME
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
Channel channel = Channel.fromCursor(cursor);
|
||||
if (subscription.getName().equals(channel.getDisplayName()))
|
||||
{
|
||||
Log.d(
|
||||
TAG,
|
||||
"Channel already exists. Returning channel "
|
||||
+ channel.getId()
|
||||
+ " from TV Provider.");
|
||||
return channel.getId();
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
private long getChannelIdFromTvProvider(Context context, HomeScreenChannel subscription)
|
||||
{
|
||||
Cursor cursor =
|
||||
context.getContentResolver().query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
new String[]{
|
||||
TvContractCompat.Channels._ID,
|
||||
TvContract.Channels.COLUMN_DISPLAY_NAME
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
Channel channel = Channel.fromCursor(cursor);
|
||||
if (subscription.getName().equals(channel.getDisplayName()))
|
||||
{
|
||||
Log.d(
|
||||
TAG,
|
||||
"Channel already exists. Returning channel "
|
||||
+ channel.getId()
|
||||
+ " from TV Provider.");
|
||||
return channel.getId();
|
||||
}
|
||||
}
|
||||
while (cursor.moveToNext());
|
||||
}
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@ package org.dolphinemu.dolphinemu.services;
|
|||
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobService;
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.PersistableBundle;
|
||||
|
@ -25,138 +23,138 @@ import java.util.List;
|
|||
|
||||
public class SyncProgramsJobService extends JobService
|
||||
{
|
||||
private static final String TAG = "SyncProgramsJobService";
|
||||
private static final String TAG = "SyncProgramsJobService";
|
||||
|
||||
private SyncProgramsTask mSyncProgramsTask;
|
||||
private SyncProgramsTask mSyncProgramsTask;
|
||||
|
||||
@Override
|
||||
public boolean onStartJob(final JobParameters jobParameters)
|
||||
{
|
||||
Log.d(TAG, "onStartJob(): " + jobParameters);
|
||||
final long channelId = getChannelId(jobParameters);
|
||||
if (channelId == -1L)
|
||||
{
|
||||
Log.d(TAG, "Failed to find channel");
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean onStartJob(final JobParameters jobParameters)
|
||||
{
|
||||
Log.d(TAG, "onStartJob(): " + jobParameters);
|
||||
final long channelId = getChannelId(jobParameters);
|
||||
if (channelId == -1L)
|
||||
{
|
||||
Log.d(TAG, "Failed to find channel");
|
||||
return false;
|
||||
}
|
||||
|
||||
mSyncProgramsTask =
|
||||
new SyncProgramsTask(getApplicationContext())
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(Boolean finished)
|
||||
{
|
||||
super.onPostExecute(finished);
|
||||
mSyncProgramsTask = null;
|
||||
jobFinished(jobParameters, !finished);
|
||||
}
|
||||
};
|
||||
mSyncProgramsTask.execute(channelId);
|
||||
return true;
|
||||
}
|
||||
mSyncProgramsTask =
|
||||
new SyncProgramsTask(getApplicationContext())
|
||||
{
|
||||
@Override
|
||||
protected void onPostExecute(Boolean finished)
|
||||
{
|
||||
super.onPostExecute(finished);
|
||||
mSyncProgramsTask = null;
|
||||
jobFinished(jobParameters, !finished);
|
||||
}
|
||||
};
|
||||
mSyncProgramsTask.execute(channelId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters jobParameters)
|
||||
{
|
||||
if (mSyncProgramsTask != null)
|
||||
{
|
||||
mSyncProgramsTask.cancel(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters jobParameters)
|
||||
{
|
||||
if (mSyncProgramsTask != null)
|
||||
{
|
||||
mSyncProgramsTask.cancel(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private long getChannelId(JobParameters jobParameters)
|
||||
{
|
||||
PersistableBundle extras = jobParameters.getExtras();
|
||||
return extras.getLong(TvContractCompat.EXTRA_CHANNEL_ID, -1L);
|
||||
}
|
||||
private long getChannelId(JobParameters jobParameters)
|
||||
{
|
||||
PersistableBundle extras = jobParameters.getExtras();
|
||||
return extras.getLong(TvContractCompat.EXTRA_CHANNEL_ID, -1L);
|
||||
}
|
||||
|
||||
private static class SyncProgramsTask extends AsyncTask<Long, Void, Boolean>
|
||||
{
|
||||
private Context context;
|
||||
private List<GameFile> updatePrograms;
|
||||
private static class SyncProgramsTask extends AsyncTask<Long, Void, Boolean>
|
||||
{
|
||||
private Context context;
|
||||
private List<GameFile> updatePrograms;
|
||||
|
||||
private SyncProgramsTask(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
updatePrograms = new ArrayList<>();
|
||||
}
|
||||
private SyncProgramsTask(Context context)
|
||||
{
|
||||
this.context = context;
|
||||
updatePrograms = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which channel to update, get the game files for the channel,
|
||||
* then updates the list
|
||||
*/
|
||||
@Override
|
||||
protected Boolean doInBackground(Long... channelIds)
|
||||
{
|
||||
List<Long> params = Arrays.asList(channelIds);
|
||||
if (!params.isEmpty())
|
||||
{
|
||||
for (Long channelId : params)
|
||||
{
|
||||
Channel channel = TvUtil.getChannelById(context, channelId);
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
if (channel != null && channel.getDisplayName().equals(platform.getHeaderName()))
|
||||
{
|
||||
getGamesByPlatform(platform);
|
||||
syncPrograms(channelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Determines which channel to update, get the game files for the channel,
|
||||
* then updates the list
|
||||
*/
|
||||
@Override
|
||||
protected Boolean doInBackground(Long... channelIds)
|
||||
{
|
||||
List<Long> params = Arrays.asList(channelIds);
|
||||
if (!params.isEmpty())
|
||||
{
|
||||
for (Long channelId : params)
|
||||
{
|
||||
Channel channel = TvUtil.getChannelById(context, channelId);
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
if (channel != null && channel.getDisplayName().equals(platform.getHeaderName()))
|
||||
{
|
||||
getGamesByPlatform(platform);
|
||||
syncPrograms(channelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void getGamesByPlatform(Platform platform)
|
||||
{
|
||||
updatePrograms = GameFileCacheService.getGameFilesForPlatform(platform);
|
||||
}
|
||||
private void getGamesByPlatform(Platform platform)
|
||||
{
|
||||
updatePrograms = GameFileCacheService.getGameFilesForPlatform(platform);
|
||||
}
|
||||
|
||||
private void syncPrograms(long channelId)
|
||||
{
|
||||
Log.d(TAG, "Sync programs for channel: " + channelId);
|
||||
deletePrograms(channelId);
|
||||
createPrograms(channelId);
|
||||
}
|
||||
private void syncPrograms(long channelId)
|
||||
{
|
||||
Log.d(TAG, "Sync programs for channel: " + channelId);
|
||||
deletePrograms(channelId);
|
||||
createPrograms(channelId);
|
||||
}
|
||||
|
||||
private void createPrograms(long channelId)
|
||||
{
|
||||
for (GameFile game : updatePrograms)
|
||||
{
|
||||
PreviewProgram previewProgram = buildProgram(channelId, game);
|
||||
private void createPrograms(long channelId)
|
||||
{
|
||||
for (GameFile game : updatePrograms)
|
||||
{
|
||||
PreviewProgram previewProgram = buildProgram(channelId, game);
|
||||
|
||||
context.getContentResolver()
|
||||
.insert(
|
||||
TvContractCompat.PreviewPrograms.CONTENT_URI,
|
||||
previewProgram.toContentValues());
|
||||
}
|
||||
}
|
||||
context.getContentResolver()
|
||||
.insert(
|
||||
TvContractCompat.PreviewPrograms.CONTENT_URI,
|
||||
previewProgram.toContentValues());
|
||||
}
|
||||
}
|
||||
|
||||
private void deletePrograms(long channelId)
|
||||
{
|
||||
context.getContentResolver().delete(
|
||||
TvContractCompat.buildPreviewProgramsUriForChannel(channelId),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
private void deletePrograms(long channelId)
|
||||
{
|
||||
context.getContentResolver().delete(
|
||||
TvContractCompat.buildPreviewProgramsUriForChannel(channelId),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
|
||||
private PreviewProgram buildProgram(long channelId, GameFile game)
|
||||
{
|
||||
Uri appLinkUri = AppLinkHelper.buildGameUri(channelId, game.getGameId());
|
||||
Uri banner = TvUtil.buildBanner(game, context);
|
||||
if (banner == null)
|
||||
banner = TvUtil.getUriToResource(context, R.drawable.banner_tv);
|
||||
private PreviewProgram buildProgram(long channelId, GameFile game)
|
||||
{
|
||||
Uri appLinkUri = AppLinkHelper.buildGameUri(channelId, game.getGameId());
|
||||
Uri banner = TvUtil.buildBanner(game, context);
|
||||
if (banner == null)
|
||||
banner = TvUtil.getUriToResource(context, R.drawable.banner_tv);
|
||||
|
||||
PreviewProgram.Builder builder = new PreviewProgram.Builder();
|
||||
builder.setChannelId(channelId)
|
||||
.setType(TvContractCompat.PreviewProgramColumns.TYPE_GAME)
|
||||
.setTitle(game.getTitle())
|
||||
.setDescription(game.getDescription())
|
||||
.setPosterArtUri(banner)
|
||||
.setPosterArtAspectRatio(TvContractCompat.PreviewPrograms.ASPECT_RATIO_2_3)
|
||||
.setIntentUri(appLinkUri);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
PreviewProgram.Builder builder = new PreviewProgram.Builder();
|
||||
builder.setChannelId(channelId)
|
||||
.setType(TvContractCompat.PreviewProgramColumns.TYPE_GAME)
|
||||
.setTitle(game.getTitle())
|
||||
.setDescription(game.getDescription())
|
||||
.setPosterArtUri(banner)
|
||||
.setPosterArtAspectRatio(TvContractCompat.PreviewPrograms.ASPECT_RATIO_2_3)
|
||||
.setIntentUri(appLinkUri);
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,15 @@ import android.content.Intent;
|
|||
|
||||
public final class USBPermService extends IntentService
|
||||
{
|
||||
public USBPermService() { super("USBPermService"); }
|
||||
public USBPermService()
|
||||
{
|
||||
super("USBPermService");
|
||||
}
|
||||
|
||||
// Needed when extending IntentService.
|
||||
// We don't care about the results of the intent handler for this.
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent) {}
|
||||
// Needed when extending IntentService.
|
||||
// We don't care about the results of the intent handler for this.
|
||||
@Override
|
||||
protected void onHandleIntent(Intent intent)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,141 +17,141 @@ import android.view.View;
|
|||
public final class DividerItemDecoration extends RecyclerView.ItemDecoration
|
||||
{
|
||||
|
||||
private Drawable mDivider;
|
||||
private boolean mShowFirstDivider = false;
|
||||
private boolean mShowLastDivider = false;
|
||||
private Drawable mDivider;
|
||||
private boolean mShowFirstDivider = false;
|
||||
private boolean mShowLastDivider = false;
|
||||
|
||||
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs)
|
||||
{
|
||||
final TypedArray a = context
|
||||
.obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
|
||||
mDivider = a.getDrawable(0);
|
||||
a.recycle();
|
||||
}
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs)
|
||||
{
|
||||
final TypedArray a = context
|
||||
.obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
|
||||
mDivider = a.getDrawable(0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(context, attrs);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(context, attrs);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Drawable divider)
|
||||
{
|
||||
mDivider = divider;
|
||||
}
|
||||
public DividerItemDecoration(Drawable divider)
|
||||
{
|
||||
mDivider = divider;
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(divider);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(divider);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
||||
RecyclerView.State state)
|
||||
{
|
||||
super.getItemOffsets(outRect, view, parent, state);
|
||||
if (mDivider == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (parent.getChildPosition(view) < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
|
||||
RecyclerView.State state)
|
||||
{
|
||||
super.getItemOffsets(outRect, view, parent, state);
|
||||
if (mDivider == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (parent.getChildPosition(view) < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (getOrientation(parent) == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
outRect.top = mDivider.getIntrinsicHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
outRect.left = mDivider.getIntrinsicWidth();
|
||||
}
|
||||
}
|
||||
if (getOrientation(parent) == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
outRect.top = mDivider.getIntrinsicHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
outRect.left = mDivider.getIntrinsicWidth();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
|
||||
{
|
||||
if (mDivider == null)
|
||||
{
|
||||
super.onDrawOver(c, parent, state);
|
||||
return;
|
||||
}
|
||||
@Override
|
||||
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state)
|
||||
{
|
||||
if (mDivider == null)
|
||||
{
|
||||
super.onDrawOver(c, parent, state);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialization needed to avoid compiler warning
|
||||
int left = 0, right = 0, top = 0, bottom = 0, size;
|
||||
int orientation = getOrientation(parent);
|
||||
int childCount = parent.getChildCount();
|
||||
// Initialization needed to avoid compiler warning
|
||||
int left = 0, right = 0, top = 0, bottom = 0, size;
|
||||
int orientation = getOrientation(parent);
|
||||
int childCount = parent.getChildCount();
|
||||
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
size = mDivider.getIntrinsicHeight();
|
||||
left = parent.getPaddingLeft();
|
||||
right = parent.getWidth() - parent.getPaddingRight();
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
size = mDivider.getIntrinsicWidth();
|
||||
top = parent.getPaddingTop();
|
||||
bottom = parent.getHeight() - parent.getPaddingBottom();
|
||||
}
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
size = mDivider.getIntrinsicHeight();
|
||||
left = parent.getPaddingLeft();
|
||||
right = parent.getWidth() - parent.getPaddingRight();
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
size = mDivider.getIntrinsicWidth();
|
||||
top = parent.getPaddingTop();
|
||||
bottom = parent.getHeight() - parent.getPaddingBottom();
|
||||
}
|
||||
|
||||
for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++)
|
||||
{
|
||||
View child = parent.getChildAt(i);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++)
|
||||
{
|
||||
View child = parent.getChildAt(i);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getTop() - params.topMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
left = child.getLeft() - params.leftMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getTop() - params.topMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
left = child.getLeft() - params.leftMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
|
||||
// show last divider
|
||||
if (mShowLastDivider && childCount > 0)
|
||||
{
|
||||
View child = parent.getChildAt(childCount - 1);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getBottom() + params.bottomMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ // horizontal
|
||||
left = child.getRight() + params.rightMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
}
|
||||
// show last divider
|
||||
if (mShowLastDivider && childCount > 0)
|
||||
{
|
||||
View child = parent.getChildAt(childCount - 1);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getBottom() + params.bottomMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ // horizontal
|
||||
left = child.getRight() + params.rightMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
}
|
||||
|
||||
private int getOrientation(RecyclerView parent)
|
||||
{
|
||||
if (parent.getLayoutManager() instanceof LinearLayoutManager)
|
||||
{
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
|
||||
return layoutManager.getOrientation();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"DividerItemDecoration can only be used with a LinearLayoutManager.");
|
||||
}
|
||||
}
|
||||
private int getOrientation(RecyclerView parent)
|
||||
{
|
||||
if (parent.getLayoutManager() instanceof LinearLayoutManager)
|
||||
{
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
|
||||
return layoutManager.getOrientation();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"DividerItemDecoration can only be used with a LinearLayoutManager.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,11 @@ import android.view.View;
|
|||
*/
|
||||
public final class NVidiaShieldWorkaroundView extends View
|
||||
{
|
||||
public NVidiaShieldWorkaroundView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
public NVidiaShieldWorkaroundView(Context context, AttributeSet attrs)
|
||||
{
|
||||
super(context, attrs);
|
||||
|
||||
// Setting this seems to workaround the bug
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
// Setting this seems to workaround the bug
|
||||
setWillNotDraw(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,70 +11,72 @@ import android.widget.TextView;
|
|||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
|
||||
public class CustomTitleView extends LinearLayout implements TitleViewAdapter.Provider {
|
||||
private final TextView mTitleView;
|
||||
private final View mBadgeView;
|
||||
public class CustomTitleView extends LinearLayout implements TitleViewAdapter.Provider
|
||||
{
|
||||
private final TextView mTitleView;
|
||||
private final View mBadgeView;
|
||||
|
||||
private final TitleViewAdapter mTitleViewAdapter = new TitleViewAdapter() {
|
||||
@Override
|
||||
public View getSearchAffordanceView()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(CharSequence titleText)
|
||||
{
|
||||
CustomTitleView.this.setTitle(titleText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBadgeDrawable(Drawable drawable)
|
||||
{
|
||||
CustomTitleView.this.setBadgeDrawable(drawable);
|
||||
}
|
||||
};
|
||||
|
||||
public CustomTitleView(Context context)
|
||||
private final TitleViewAdapter mTitleViewAdapter = new TitleViewAdapter()
|
||||
{
|
||||
@Override
|
||||
public View getSearchAffordanceView()
|
||||
{
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CustomTitleView(Context context, AttributeSet attrs)
|
||||
{
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
|
||||
{
|
||||
super(context, attrs, defStyle);
|
||||
View root = LayoutInflater.from(context).inflate(R.layout.tv_title, this);
|
||||
mTitleView = (TextView) root.findViewById(R.id.title);
|
||||
mBadgeView = root.findViewById(R.id.badge);
|
||||
}
|
||||
|
||||
public void setTitle(CharSequence title)
|
||||
{
|
||||
if (title != null)
|
||||
{
|
||||
mTitleView.setText(title);
|
||||
mTitleView.setVisibility(View.VISIBLE);
|
||||
mBadgeView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeDrawable(Drawable drawable)
|
||||
{
|
||||
if (drawable != null)
|
||||
{
|
||||
mTitleView.setVisibility(View.GONE);
|
||||
mBadgeView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TitleViewAdapter getTitleViewAdapter()
|
||||
public void setTitle(CharSequence titleText)
|
||||
{
|
||||
return mTitleViewAdapter;
|
||||
CustomTitleView.this.setTitle(titleText);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBadgeDrawable(Drawable drawable)
|
||||
{
|
||||
CustomTitleView.this.setBadgeDrawable(drawable);
|
||||
}
|
||||
};
|
||||
|
||||
public CustomTitleView(Context context)
|
||||
{
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CustomTitleView(Context context, AttributeSet attrs)
|
||||
{
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CustomTitleView(Context context, AttributeSet attrs, int defStyle)
|
||||
{
|
||||
super(context, attrs, defStyle);
|
||||
View root = LayoutInflater.from(context).inflate(R.layout.tv_title, this);
|
||||
mTitleView = (TextView) root.findViewById(R.id.title);
|
||||
mBadgeView = root.findViewById(R.id.badge);
|
||||
}
|
||||
|
||||
public void setTitle(CharSequence title)
|
||||
{
|
||||
if (title != null)
|
||||
{
|
||||
mTitleView.setText(title);
|
||||
mTitleView.setVisibility(View.VISIBLE);
|
||||
mBadgeView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBadgeDrawable(Drawable drawable)
|
||||
{
|
||||
if (drawable != null)
|
||||
{
|
||||
mTitleView.setVisibility(View.GONE);
|
||||
mBadgeView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TitleViewAdapter getTitleViewAdapter()
|
||||
{
|
||||
return mTitleViewAdapter;
|
||||
}
|
||||
}
|
|
@ -17,12 +17,12 @@ import android.widget.Toast;
|
|||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
|
||||
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
|
||||
import org.dolphinemu.dolphinemu.utils.StartupHandler;
|
||||
|
@ -33,206 +33,211 @@ import org.dolphinemu.dolphinemu.utils.StartupHandler;
|
|||
*/
|
||||
public final class MainActivity extends AppCompatActivity implements MainView
|
||||
{
|
||||
private ViewPager mViewPager;
|
||||
private Toolbar mToolbar;
|
||||
private TabLayout mTabLayout;
|
||||
private FloatingActionButton mFab;
|
||||
private ViewPager mViewPager;
|
||||
private Toolbar mToolbar;
|
||||
private TabLayout mTabLayout;
|
||||
private FloatingActionButton mFab;
|
||||
|
||||
private MainPresenter mPresenter = new MainPresenter(this, this);
|
||||
private MainPresenter mPresenter = new MainPresenter(this, this);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
findViews();
|
||||
findViews();
|
||||
|
||||
setSupportActionBar(mToolbar);
|
||||
setSupportActionBar(mToolbar);
|
||||
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
|
||||
// Set up the FAB.
|
||||
mFab.setOnClickListener(view -> mPresenter.onFabClick());
|
||||
// Set up the FAB.
|
||||
mFab.setOnClickListener(view -> mPresenter.onFabClick());
|
||||
|
||||
mPresenter.onCreate();
|
||||
mPresenter.onCreate();
|
||||
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
StartupHandler.HandleInit(this);
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
StartupHandler.HandleInit(this);
|
||||
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
|
||||
getSupportFragmentManager(), this);
|
||||
mViewPager.setAdapter(platformPagerAdapter);
|
||||
mViewPager.setOffscreenPageLimit(platformPagerAdapter.getCount());
|
||||
showGames();
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mViewPager.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
|
||||
getSupportFragmentManager(), this);
|
||||
mViewPager.setAdapter(platformPagerAdapter);
|
||||
mViewPager.setOffscreenPageLimit(platformPagerAdapter.getCount());
|
||||
showGames();
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mViewPager.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mPresenter.addDirIfNeeded(this);
|
||||
}
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mPresenter.addDirIfNeeded(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
mPresenter.onDestroy();
|
||||
}
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
mPresenter.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
StartupHandler.checkSessionReset(this);
|
||||
}
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
StartupHandler.checkSessionReset(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
StartupHandler.setSessionTime(this);
|
||||
}
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
StartupHandler.setSessionTime(this);
|
||||
}
|
||||
|
||||
// TODO: Replace with a ButterKnife injection.
|
||||
private void findViews()
|
||||
{
|
||||
mToolbar = (Toolbar) findViewById(R.id.toolbar_main);
|
||||
mViewPager = (ViewPager) findViewById(R.id.pager_platforms);
|
||||
mTabLayout = (TabLayout) findViewById(R.id.tabs_platforms);
|
||||
mFab = (FloatingActionButton) findViewById(R.id.button_add_directory);
|
||||
}
|
||||
// TODO: Replace with a ButterKnife injection.
|
||||
private void findViews()
|
||||
{
|
||||
mToolbar = (Toolbar) findViewById(R.id.toolbar_main);
|
||||
mViewPager = (ViewPager) findViewById(R.id.pager_platforms);
|
||||
mTabLayout = (TabLayout) findViewById(R.id.tabs_platforms);
|
||||
mFab = (FloatingActionButton) findViewById(R.id.button_add_directory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_game_grid, menu);
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_game_grid, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* MainView
|
||||
*/
|
||||
/**
|
||||
* MainView
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void setVersionString(String version)
|
||||
{
|
||||
mToolbar.setSubtitle(version);
|
||||
}
|
||||
@Override
|
||||
public void setVersionString(String version)
|
||||
{
|
||||
mToolbar.setSubtitle(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshFragmentScreenshot(int fragmentPosition)
|
||||
{
|
||||
// Invalidate Picasso image so that the new screenshot is animated in.
|
||||
Platform platform = Platform.fromPosition(mViewPager.getCurrentItem());
|
||||
PlatformGamesView fragment = getPlatformGamesView(platform);
|
||||
@Override
|
||||
public void refreshFragmentScreenshot(int fragmentPosition)
|
||||
{
|
||||
// Invalidate Picasso image so that the new screenshot is animated in.
|
||||
Platform platform = Platform.fromPosition(mViewPager.getCurrentItem());
|
||||
PlatformGamesView fragment = getPlatformGamesView(platform);
|
||||
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.refreshScreenshotAtPosition(fragmentPosition);
|
||||
}
|
||||
}
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.refreshScreenshotAtPosition(fragmentPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchSettingsActivity(MenuTag menuTag)
|
||||
{
|
||||
SettingsActivity.launch(this, menuTag, "");
|
||||
}
|
||||
@Override
|
||||
public void launchSettingsActivity(MenuTag menuTag)
|
||||
{
|
||||
SettingsActivity.launch(this, menuTag, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchFileListActivity()
|
||||
{
|
||||
FileBrowserHelper.openDirectoryPicker(this);
|
||||
}
|
||||
@Override
|
||||
public void launchFileListActivity()
|
||||
{
|
||||
FileBrowserHelper.openDirectoryPicker(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestCode An int describing whether the Activity that is returning did so successfully.
|
||||
* @param resultCode An int describing what Activity is giving us this callback.
|
||||
* @param result The information the returning Activity is providing us.
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case MainPresenter.REQUEST_ADD_DIRECTORY:
|
||||
// If the user picked a file, as opposed to just backing out.
|
||||
if (resultCode == MainActivity.RESULT_OK)
|
||||
{
|
||||
mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
|
||||
}
|
||||
break;
|
||||
/**
|
||||
* @param requestCode An int describing whether the Activity that is returning did so successfully.
|
||||
* @param resultCode An int describing what Activity is giving us this callback.
|
||||
* @param result The information the returning Activity is providing us.
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case MainPresenter.REQUEST_ADD_DIRECTORY:
|
||||
// If the user picked a file, as opposed to just backing out.
|
||||
if (resultCode == MainActivity.RESULT_OK)
|
||||
{
|
||||
mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
|
||||
}
|
||||
break;
|
||||
|
||||
case MainPresenter.REQUEST_EMULATE_GAME:
|
||||
mPresenter.refreshFragmentScreenshot(resultCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MainPresenter.REQUEST_EMULATE_GAME:
|
||||
mPresenter.refreshFragmentScreenshot(resultCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
DirectoryInitializationService.startService(this);
|
||||
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
|
||||
getSupportFragmentManager(), this);
|
||||
mViewPager.setAdapter(platformPagerAdapter);
|
||||
mViewPager.setOffscreenPageLimit(platformPagerAdapter.getCount());
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
mViewPager.setVisibility(View.VISIBLE);
|
||||
GameFileCacheService.startLoad(this);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
||||
{
|
||||
DirectoryInitializationService.startService(this);
|
||||
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
|
||||
getSupportFragmentManager(), this);
|
||||
mViewPager.setAdapter(platformPagerAdapter);
|
||||
mViewPager.setOffscreenPageLimit(platformPagerAdapter.getCount());
|
||||
mTabLayout.setupWithViewPager(mViewPager);
|
||||
mViewPager.setVisibility(View.VISIBLE);
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the framework whenever any actionbar/toolbar icon is clicked.
|
||||
*
|
||||
* @param item The icon that was clicked on.
|
||||
* @return True if the event was handled, false to bubble it up to the OS.
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
return mPresenter.handleOptionSelection(item.getItemId(), this);
|
||||
}
|
||||
/**
|
||||
* Called by the framework whenever any actionbar/toolbar icon is clicked.
|
||||
*
|
||||
* @param item The icon that was clicked on.
|
||||
* @return True if the event was handled, false to bubble it up to the OS.
|
||||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
return mPresenter.handleOptionSelection(item.getItemId(), this);
|
||||
}
|
||||
|
||||
public void showGames()
|
||||
{
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
PlatformGamesView fragment = getPlatformGamesView(platform);
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.showGames();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void showGames()
|
||||
{
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
PlatformGamesView fragment = getPlatformGamesView(platform);
|
||||
if (fragment != null)
|
||||
{
|
||||
fragment.showGames();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PlatformGamesView getPlatformGamesView(Platform platform)
|
||||
{
|
||||
String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform.toInt();
|
||||
@Nullable
|
||||
private PlatformGamesView getPlatformGamesView(Platform platform)
|
||||
{
|
||||
String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform.toInt();
|
||||
|
||||
return (PlatformGamesView) getSupportFragmentManager().findFragmentByTag(fragmentTag);
|
||||
}
|
||||
return (PlatformGamesView) getSupportFragmentManager().findFragmentByTag(fragmentTag);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,106 +8,106 @@ import android.support.v4.content.LocalBroadcastManager;
|
|||
|
||||
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.model.GameFileCache;
|
||||
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
|
||||
public final class MainPresenter
|
||||
{
|
||||
public static final int REQUEST_ADD_DIRECTORY = 1;
|
||||
public static final int REQUEST_EMULATE_GAME = 2;
|
||||
public static final int REQUEST_ADD_DIRECTORY = 1;
|
||||
public static final int REQUEST_EMULATE_GAME = 2;
|
||||
|
||||
private final MainView mView;
|
||||
private final Context mContext;
|
||||
private BroadcastReceiver mBroadcastReceiver = null;
|
||||
private String mDirToAdd;
|
||||
private final MainView mView;
|
||||
private final Context mContext;
|
||||
private BroadcastReceiver mBroadcastReceiver = null;
|
||||
private String mDirToAdd;
|
||||
|
||||
public MainPresenter(MainView view, Context context)
|
||||
{
|
||||
mView = view;
|
||||
mContext = context;
|
||||
}
|
||||
public MainPresenter(MainView view, Context context)
|
||||
{
|
||||
mView = view;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public void onCreate()
|
||||
{
|
||||
String versionName = BuildConfig.VERSION_NAME;
|
||||
mView.setVersionString(versionName);
|
||||
public void onCreate()
|
||||
{
|
||||
String versionName = BuildConfig.VERSION_NAME;
|
||||
mView.setVersionString(versionName);
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(GameFileCacheService.BROADCAST_ACTION);
|
||||
mBroadcastReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
mView.showGames();
|
||||
}
|
||||
};
|
||||
LocalBroadcastManager.getInstance(mContext).registerReceiver(mBroadcastReceiver, filter);
|
||||
}
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(GameFileCacheService.BROADCAST_ACTION);
|
||||
mBroadcastReceiver = new BroadcastReceiver()
|
||||
{
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
mView.showGames();
|
||||
}
|
||||
};
|
||||
LocalBroadcastManager.getInstance(mContext).registerReceiver(mBroadcastReceiver, filter);
|
||||
}
|
||||
|
||||
public void onDestroy()
|
||||
{
|
||||
if (mBroadcastReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
}
|
||||
public void onDestroy()
|
||||
{
|
||||
if (mBroadcastReceiver != null)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(mBroadcastReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
public void onFabClick()
|
||||
{
|
||||
mView.launchFileListActivity();
|
||||
}
|
||||
public void onFabClick()
|
||||
{
|
||||
mView.launchFileListActivity();
|
||||
}
|
||||
|
||||
public boolean handleOptionSelection(int itemId, Context context)
|
||||
{
|
||||
switch (itemId)
|
||||
{
|
||||
case R.id.menu_settings_core:
|
||||
mView.launchSettingsActivity(MenuTag.CONFIG);
|
||||
return true;
|
||||
public boolean handleOptionSelection(int itemId, Context context)
|
||||
{
|
||||
switch (itemId)
|
||||
{
|
||||
case R.id.menu_settings_core:
|
||||
mView.launchSettingsActivity(MenuTag.CONFIG);
|
||||
return true;
|
||||
|
||||
case R.id.menu_settings_graphics:
|
||||
mView.launchSettingsActivity(MenuTag.GRAPHICS);
|
||||
return true;
|
||||
case R.id.menu_settings_graphics:
|
||||
mView.launchSettingsActivity(MenuTag.GRAPHICS);
|
||||
return true;
|
||||
|
||||
case R.id.menu_settings_gcpad:
|
||||
mView.launchSettingsActivity(MenuTag.GCPAD_TYPE);
|
||||
return true;
|
||||
case R.id.menu_settings_gcpad:
|
||||
mView.launchSettingsActivity(MenuTag.GCPAD_TYPE);
|
||||
return true;
|
||||
|
||||
case R.id.menu_settings_wiimote:
|
||||
mView.launchSettingsActivity(MenuTag.WIIMOTE);
|
||||
return true;
|
||||
case R.id.menu_settings_wiimote:
|
||||
mView.launchSettingsActivity(MenuTag.WIIMOTE);
|
||||
return true;
|
||||
|
||||
case R.id.menu_refresh:
|
||||
GameFileCacheService.startRescan(context);
|
||||
return true;
|
||||
case R.id.menu_refresh:
|
||||
GameFileCacheService.startRescan(context);
|
||||
return true;
|
||||
|
||||
case R.id.button_add_directory:
|
||||
mView.launchFileListActivity();
|
||||
return true;
|
||||
}
|
||||
case R.id.button_add_directory:
|
||||
mView.launchFileListActivity();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addDirIfNeeded(Context context)
|
||||
{
|
||||
if (mDirToAdd != null)
|
||||
{
|
||||
GameFileCache.addGameFolder(mDirToAdd, context);
|
||||
mDirToAdd = null;
|
||||
GameFileCacheService.startRescan(context);
|
||||
}
|
||||
}
|
||||
public void addDirIfNeeded(Context context)
|
||||
{
|
||||
if (mDirToAdd != null)
|
||||
{
|
||||
GameFileCache.addGameFolder(mDirToAdd, context);
|
||||
mDirToAdd = null;
|
||||
GameFileCacheService.startRescan(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDirectorySelected(String dir)
|
||||
{
|
||||
mDirToAdd = dir;
|
||||
}
|
||||
public void onDirectorySelected(String dir)
|
||||
{
|
||||
mDirToAdd = dir;
|
||||
}
|
||||
|
||||
public void refreshFragmentScreenshot(int resultCode)
|
||||
{
|
||||
mView.refreshFragmentScreenshot(resultCode);
|
||||
}
|
||||
public void refreshFragmentScreenshot(int resultCode)
|
||||
{
|
||||
mView.refreshFragmentScreenshot(resultCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,29 +9,29 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
|||
*/
|
||||
public interface MainView
|
||||
{
|
||||
/**
|
||||
* Pass the view the native library's version string. Displaying
|
||||
* it is optional.
|
||||
*
|
||||
* @param version A string pulled from native code.
|
||||
*/
|
||||
void setVersionString(String version);
|
||||
/**
|
||||
* Pass the view the native library's version string. Displaying
|
||||
* it is optional.
|
||||
*
|
||||
* @param version A string pulled from native code.
|
||||
*/
|
||||
void setVersionString(String version);
|
||||
|
||||
/**
|
||||
* Tell the view to tell the currently displayed {@link android.support.v4.app.Fragment}
|
||||
* to refresh the screenshot at the given position in its list of games.
|
||||
*
|
||||
* @param fragmentPosition An index corresponding to the list or grid of games.
|
||||
*/
|
||||
void refreshFragmentScreenshot(int fragmentPosition);
|
||||
/**
|
||||
* Tell the view to tell the currently displayed {@link android.support.v4.app.Fragment}
|
||||
* to refresh the screenshot at the given position in its list of games.
|
||||
*
|
||||
* @param fragmentPosition An index corresponding to the list or grid of games.
|
||||
*/
|
||||
void refreshFragmentScreenshot(int fragmentPosition);
|
||||
|
||||
|
||||
void launchSettingsActivity(MenuTag menuTag);
|
||||
void launchSettingsActivity(MenuTag menuTag);
|
||||
|
||||
void launchFileListActivity();
|
||||
void launchFileListActivity();
|
||||
|
||||
/**
|
||||
* To be called when the game file cache is updated.
|
||||
*/
|
||||
void showGames();
|
||||
/**
|
||||
* To be called when the game file cache is updated.
|
||||
*/
|
||||
void showGames();
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ import org.dolphinemu.dolphinemu.R;
|
|||
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.adapters.GameRowPresenter;
|
||||
import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.model.TvSettingsItem;
|
||||
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
||||
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
|
||||
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
|
||||
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper;
|
||||
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
|
||||
import org.dolphinemu.dolphinemu.utils.StartupHandler;
|
||||
|
@ -35,249 +35,257 @@ import java.util.Collection;
|
|||
|
||||
public final class TvMainActivity extends FragmentActivity implements MainView
|
||||
{
|
||||
private MainPresenter mPresenter = new MainPresenter(this, this);
|
||||
private MainPresenter mPresenter = new MainPresenter(this, this);
|
||||
|
||||
private BrowseSupportFragment mBrowseFragment;
|
||||
private BrowseSupportFragment mBrowseFragment;
|
||||
|
||||
private ArrayObjectAdapter mRowsAdapter;
|
||||
private ArrayObjectAdapter mRowsAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_tv_main);
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_tv_main);
|
||||
|
||||
setupUI();
|
||||
setupUI();
|
||||
|
||||
mPresenter.onCreate();
|
||||
mPresenter.onCreate();
|
||||
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
StartupHandler.HandleInit(this);
|
||||
}
|
||||
// Setup and/or sync channels
|
||||
TvUtil.scheduleSyncingChannel(getApplicationContext());
|
||||
}
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
StartupHandler.HandleInit(this);
|
||||
}
|
||||
// Setup and/or sync channels
|
||||
TvUtil.scheduleSyncingChannel(getApplicationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mPresenter.addDirIfNeeded(this);
|
||||
}
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
mPresenter.addDirIfNeeded(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
mPresenter.onDestroy();
|
||||
}
|
||||
@Override
|
||||
protected void onDestroy()
|
||||
{
|
||||
super.onDestroy();
|
||||
mPresenter.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
StartupHandler.checkSessionReset(this);
|
||||
}
|
||||
@Override
|
||||
protected void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
StartupHandler.checkSessionReset(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
StartupHandler.setSessionTime(this);
|
||||
}
|
||||
@Override
|
||||
protected void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
StartupHandler.setSessionTime(this);
|
||||
}
|
||||
|
||||
void setupUI() {
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
mBrowseFragment = new BrowseSupportFragment();
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.add(R.id.content, mBrowseFragment, "BrowseFragment")
|
||||
.commit();
|
||||
void setupUI()
|
||||
{
|
||||
final FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
mBrowseFragment = new BrowseSupportFragment();
|
||||
fragmentManager
|
||||
.beginTransaction()
|
||||
.add(R.id.content, mBrowseFragment, "BrowseFragment")
|
||||
.commit();
|
||||
|
||||
// Set display parameters for the BrowseFragment
|
||||
mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
|
||||
mBrowseFragment.setBrandColor(ContextCompat.getColor(this, R.color.dolphin_blue_dark));
|
||||
buildRowsAdapter();
|
||||
// Set display parameters for the BrowseFragment
|
||||
mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
|
||||
mBrowseFragment.setBrandColor(ContextCompat.getColor(this, R.color.dolphin_blue_dark));
|
||||
buildRowsAdapter();
|
||||
|
||||
mBrowseFragment.setOnItemViewClickedListener(
|
||||
(itemViewHolder, item, rowViewHolder, row) ->
|
||||
{
|
||||
// Special case: user clicked on a settings row item.
|
||||
if (item instanceof TvSettingsItem)
|
||||
{
|
||||
TvSettingsItem settingsItem = (TvSettingsItem) item;
|
||||
mPresenter.handleOptionSelection(settingsItem.getItemId(), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder;
|
||||
mBrowseFragment.setOnItemViewClickedListener(
|
||||
(itemViewHolder, item, rowViewHolder, row) ->
|
||||
{
|
||||
// Special case: user clicked on a settings row item.
|
||||
if (item instanceof TvSettingsItem)
|
||||
{
|
||||
TvSettingsItem settingsItem = (TvSettingsItem) item;
|
||||
mPresenter.handleOptionSelection(settingsItem.getItemId(), this);
|
||||
}
|
||||
else
|
||||
{
|
||||
TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder;
|
||||
|
||||
// Start the emulation activity and send the path of the clicked ISO to it.
|
||||
EmulationActivity.launch(TvMainActivity.this,
|
||||
holder.gameFile,
|
||||
-1,
|
||||
holder.imageScreenshot);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* MainView
|
||||
*/
|
||||
// Start the emulation activity and send the path of the clicked ISO to it.
|
||||
EmulationActivity.launch(TvMainActivity.this,
|
||||
holder.gameFile,
|
||||
-1,
|
||||
holder.imageScreenshot);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVersionString(String version)
|
||||
{
|
||||
mBrowseFragment.setTitle(version);
|
||||
}
|
||||
/**
|
||||
* MainView
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void refreshFragmentScreenshot(int fragmentPosition)
|
||||
{
|
||||
mRowsAdapter.notifyArrayItemRangeChanged(0, mRowsAdapter.size());
|
||||
}
|
||||
@Override
|
||||
public void setVersionString(String version)
|
||||
{
|
||||
mBrowseFragment.setTitle(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchSettingsActivity(MenuTag menuTag)
|
||||
{
|
||||
SettingsActivity.launch(this, menuTag, "");
|
||||
}
|
||||
@Override
|
||||
public void refreshFragmentScreenshot(int fragmentPosition)
|
||||
{
|
||||
mRowsAdapter.notifyArrayItemRangeChanged(0, mRowsAdapter.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void launchFileListActivity()
|
||||
{
|
||||
FileBrowserHelper.openDirectoryPicker(this);
|
||||
}
|
||||
@Override
|
||||
public void launchSettingsActivity(MenuTag menuTag)
|
||||
{
|
||||
SettingsActivity.launch(this, menuTag, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showGames()
|
||||
{
|
||||
// Kicks off the program services to update all channels
|
||||
TvUtil.updateAllChannels(getApplicationContext());
|
||||
@Override
|
||||
public void launchFileListActivity()
|
||||
{
|
||||
FileBrowserHelper.openDirectoryPicker(this);
|
||||
}
|
||||
|
||||
recreate();
|
||||
}
|
||||
@Override
|
||||
public void showGames()
|
||||
{
|
||||
// Kicks off the program services to update all channels
|
||||
TvUtil.updateAllChannels(getApplicationContext());
|
||||
|
||||
/**
|
||||
* Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity.
|
||||
*
|
||||
* @param requestCode An int describing whether the Activity that is returning did so successfully.
|
||||
* @param resultCode An int describing what Activity is giving us this callback.
|
||||
* @param result The information the returning Activity is providing us.
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case MainPresenter.REQUEST_ADD_DIRECTORY:
|
||||
// If the user picked a file, as opposed to just backing out.
|
||||
if (resultCode == MainActivity.RESULT_OK)
|
||||
{
|
||||
mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
|
||||
}
|
||||
break;
|
||||
recreate();
|
||||
}
|
||||
|
||||
case MainPresenter.REQUEST_EMULATE_GAME:
|
||||
mPresenter.refreshFragmentScreenshot(resultCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity.
|
||||
*
|
||||
* @param requestCode An int describing whether the Activity that is returning did so successfully.
|
||||
* @param resultCode An int describing what Activity is giving us this callback.
|
||||
* @param result The information the returning Activity is providing us.
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case MainPresenter.REQUEST_ADD_DIRECTORY:
|
||||
// If the user picked a file, as opposed to just backing out.
|
||||
if (resultCode == MainActivity.RESULT_OK)
|
||||
{
|
||||
mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedDirectory(result));
|
||||
}
|
||||
break;
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
switch (requestCode) {
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
DirectoryInitializationService.startService(this);
|
||||
GameFileCacheService.startLoad(this);
|
||||
} else {
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case MainPresenter.REQUEST_EMULATE_GAME:
|
||||
mPresenter.refreshFragmentScreenshot(resultCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void buildRowsAdapter()
|
||||
{
|
||||
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
||||
{
|
||||
switch (requestCode)
|
||||
{
|
||||
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
|
||||
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
||||
{
|
||||
DirectoryInitializationService.startService(this);
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
private void buildRowsAdapter()
|
||||
{
|
||||
mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
|
||||
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
ListRow row = buildGamesRow(platform, GameFileCacheService.getGameFilesForPlatform(platform));
|
||||
if (PermissionsHandler.hasWriteAccess(this))
|
||||
{
|
||||
GameFileCacheService.startLoad(this);
|
||||
}
|
||||
|
||||
// Add row to the adapter only if it is not empty.
|
||||
if (row != null)
|
||||
{
|
||||
mRowsAdapter.add(row);
|
||||
}
|
||||
}
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
ListRow row = buildGamesRow(platform, GameFileCacheService.getGameFilesForPlatform(platform));
|
||||
|
||||
mRowsAdapter.add(buildSettingsRow());
|
||||
// Add row to the adapter only if it is not empty.
|
||||
if (row != null)
|
||||
{
|
||||
mRowsAdapter.add(row);
|
||||
}
|
||||
}
|
||||
|
||||
mBrowseFragment.setAdapter(mRowsAdapter);
|
||||
}
|
||||
mRowsAdapter.add(buildSettingsRow());
|
||||
|
||||
private ListRow buildGamesRow(Platform platform, Collection<GameFile> gameFiles)
|
||||
{
|
||||
// If there are no games, don't return a Row.
|
||||
if (gameFiles.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
mBrowseFragment.setAdapter(mRowsAdapter);
|
||||
}
|
||||
|
||||
// Create an adapter for this row.
|
||||
ArrayObjectAdapter row = new ArrayObjectAdapter(new GameRowPresenter());
|
||||
row.addAll(0, gameFiles);
|
||||
private ListRow buildGamesRow(Platform platform, Collection<GameFile> gameFiles)
|
||||
{
|
||||
// If there are no games, don't return a Row.
|
||||
if (gameFiles.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a header for this row.
|
||||
HeaderItem header = new HeaderItem(platform.toInt(), platform.getHeaderName());
|
||||
// Create an adapter for this row.
|
||||
ArrayObjectAdapter row = new ArrayObjectAdapter(new GameRowPresenter());
|
||||
row.addAll(0, gameFiles);
|
||||
|
||||
// Create the row, passing it the filled adapter and the header, and give it to the master adapter.
|
||||
return new ListRow(header, row);
|
||||
}
|
||||
// Create a header for this row.
|
||||
HeaderItem header = new HeaderItem(platform.toInt(), platform.getHeaderName());
|
||||
|
||||
private ListRow buildSettingsRow()
|
||||
{
|
||||
ArrayObjectAdapter rowItems = new ArrayObjectAdapter(new SettingsRowPresenter());
|
||||
// Create the row, passing it the filled adapter and the header, and give it to the master adapter.
|
||||
return new ListRow(header, row);
|
||||
}
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_core,
|
||||
R.drawable.ic_settings_core_tv,
|
||||
R.string.grid_menu_config));
|
||||
private ListRow buildSettingsRow()
|
||||
{
|
||||
ArrayObjectAdapter rowItems = new ArrayObjectAdapter(new SettingsRowPresenter());
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_graphics,
|
||||
R.drawable.ic_settings_graphics_tv,
|
||||
R.string.grid_menu_graphics_settings));
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_core,
|
||||
R.drawable.ic_settings_core_tv,
|
||||
R.string.grid_menu_config));
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_gcpad,
|
||||
R.drawable.ic_settings_gcpad,
|
||||
R.string.grid_menu_gcpad_settings));
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_graphics,
|
||||
R.drawable.ic_settings_graphics_tv,
|
||||
R.string.grid_menu_graphics_settings));
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_wiimote,
|
||||
R.drawable.ic_settings_wiimote,
|
||||
R.string.grid_menu_wiimote_settings));
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_gcpad,
|
||||
R.drawable.ic_settings_gcpad,
|
||||
R.string.grid_menu_gcpad_settings));
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.button_add_directory,
|
||||
R.drawable.ic_add_tv,
|
||||
R.string.add_directory_title));
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_settings_wiimote,
|
||||
R.drawable.ic_settings_wiimote,
|
||||
R.string.grid_menu_wiimote_settings));
|
||||
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_refresh,
|
||||
R.drawable.ic_refresh_tv,
|
||||
R.string.grid_menu_refresh));
|
||||
rowItems.add(new TvSettingsItem(R.id.button_add_directory,
|
||||
R.drawable.ic_add_tv,
|
||||
R.string.add_directory_title));
|
||||
|
||||
// Create a header for this row.
|
||||
HeaderItem header = new HeaderItem(R.string.preferences_settings, getString(R.string.preferences_settings));
|
||||
rowItems.add(new TvSettingsItem(R.id.menu_refresh,
|
||||
R.drawable.ic_refresh_tv,
|
||||
R.string.grid_menu_refresh));
|
||||
|
||||
return new ListRow(header, rowItems);
|
||||
}
|
||||
// Create a header for this row.
|
||||
HeaderItem header =
|
||||
new HeaderItem(R.string.preferences_settings, getString(R.string.preferences_settings));
|
||||
|
||||
return new ListRow(header, rowItems);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,47 @@
|
|||
package org.dolphinemu.dolphinemu.ui.platform;
|
||||
|
||||
/** Enum to represent platform (eg GameCube, Wii). */
|
||||
/**
|
||||
* Enum to represent platform (eg GameCube, Wii).
|
||||
*/
|
||||
public enum Platform
|
||||
{
|
||||
GAMECUBE(0, "GameCube Games"),
|
||||
WII(1, "Wii Games"),
|
||||
WIIWARE(2, "WiiWare Games");
|
||||
GAMECUBE(0, "GameCube Games"),
|
||||
WII(1, "Wii Games"),
|
||||
WIIWARE(2, "WiiWare Games");
|
||||
|
||||
private final int value;
|
||||
private final String headerName;
|
||||
private final int value;
|
||||
private final String headerName;
|
||||
|
||||
Platform(int value, String headerName)
|
||||
{
|
||||
this.value = value;
|
||||
this.headerName = headerName;
|
||||
}
|
||||
Platform(int value, String headerName)
|
||||
{
|
||||
this.value = value;
|
||||
this.headerName = headerName;
|
||||
}
|
||||
|
||||
public static Platform fromInt(int i)
|
||||
{
|
||||
return values()[i];
|
||||
}
|
||||
public static Platform fromInt(int i)
|
||||
{
|
||||
return values()[i];
|
||||
}
|
||||
|
||||
public static Platform fromNativeInt(int i)
|
||||
{
|
||||
// TODO: Proper support for DOL and ELF files
|
||||
boolean in_range = i >= 0 && i < values().length;
|
||||
return values()[in_range ? i : WIIWARE.value];
|
||||
}
|
||||
public static Platform fromNativeInt(int i)
|
||||
{
|
||||
// TODO: Proper support for DOL and ELF files
|
||||
boolean in_range = i >= 0 && i < values().length;
|
||||
return values()[in_range ? i : WIIWARE.value];
|
||||
}
|
||||
|
||||
public static Platform fromPosition(int position)
|
||||
{
|
||||
return values()[position];
|
||||
}
|
||||
public static Platform fromPosition(int position)
|
||||
{
|
||||
return values()[position];
|
||||
}
|
||||
|
||||
public int toInt()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
public int toInt()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getHeaderName()
|
||||
{
|
||||
return headerName;
|
||||
}
|
||||
public String getHeaderName()
|
||||
{
|
||||
return headerName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,85 +11,82 @@ import android.view.ViewGroup;
|
|||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.adapters.GameAdapter;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.services.GameFileCacheService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class PlatformGamesFragment extends Fragment implements PlatformGamesView
|
||||
{
|
||||
private static final String ARG_PLATFORM = "platform";
|
||||
private static final String ARG_PLATFORM = "platform";
|
||||
|
||||
private GameAdapter mAdapter;
|
||||
private RecyclerView mRecyclerView;
|
||||
private GameAdapter mAdapter;
|
||||
private RecyclerView mRecyclerView;
|
||||
|
||||
public static PlatformGamesFragment newInstance(Platform platform)
|
||||
{
|
||||
PlatformGamesFragment fragment = new PlatformGamesFragment();
|
||||
public static PlatformGamesFragment newInstance(Platform platform)
|
||||
{
|
||||
PlatformGamesFragment fragment = new PlatformGamesFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_PLATFORM, platform);
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_PLATFORM, platform);
|
||||
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_grid, container, false);
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View rootView = inflater.inflate(R.layout.fragment_grid, container, false);
|
||||
|
||||
findViews(rootView);
|
||||
findViews(rootView);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState)
|
||||
{
|
||||
int columns = getResources().getInteger(R.integer.game_grid_columns);
|
||||
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), columns);
|
||||
mAdapter = new GameAdapter();
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState)
|
||||
{
|
||||
int columns = getResources().getInteger(R.integer.game_grid_columns);
|
||||
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getActivity(), columns);
|
||||
mAdapter = new GameAdapter();
|
||||
|
||||
mRecyclerView.setLayoutManager(layoutManager);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
mRecyclerView.setLayoutManager(layoutManager);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
mRecyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||
mRecyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||
|
||||
showGames();
|
||||
}
|
||||
showGames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshScreenshotAtPosition(int position)
|
||||
{
|
||||
mAdapter.notifyItemChanged(position);
|
||||
}
|
||||
@Override
|
||||
public void refreshScreenshotAtPosition(int position)
|
||||
{
|
||||
mAdapter.notifyItemChanged(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(String gameId)
|
||||
{
|
||||
// No-op for now
|
||||
}
|
||||
@Override
|
||||
public void onItemClick(String gameId)
|
||||
{
|
||||
// No-op for now
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showGames()
|
||||
{
|
||||
if (mAdapter != null)
|
||||
{
|
||||
Platform platform = (Platform) getArguments().getSerializable(ARG_PLATFORM);
|
||||
mAdapter.swapDataSet(GameFileCacheService.getGameFilesForPlatform(platform));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void showGames()
|
||||
{
|
||||
if (mAdapter != null)
|
||||
{
|
||||
Platform platform = (Platform) getArguments().getSerializable(ARG_PLATFORM);
|
||||
mAdapter.swapDataSet(GameFileCacheService.getGameFilesForPlatform(platform));
|
||||
}
|
||||
}
|
||||
|
||||
private void findViews(View root)
|
||||
{
|
||||
mRecyclerView = (RecyclerView) root.findViewById(R.id.grid_games);
|
||||
}
|
||||
private void findViews(View root)
|
||||
{
|
||||
mRecyclerView = (RecyclerView) root.findViewById(R.id.grid_games);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,28 @@
|
|||
package org.dolphinemu.dolphinemu.ui.platform;
|
||||
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Abstraction for a screen representing a single platform's games.
|
||||
*/
|
||||
public interface PlatformGamesView
|
||||
{
|
||||
/**
|
||||
* Tell the view that a certain game's screenshot has been updated,
|
||||
* and should be redrawn on-screen.
|
||||
*
|
||||
* @param position The index of the game that should be redrawn.
|
||||
*/
|
||||
void refreshScreenshotAtPosition(int position);
|
||||
/**
|
||||
* Tell the view that a certain game's screenshot has been updated,
|
||||
* and should be redrawn on-screen.
|
||||
*
|
||||
* @param position The index of the game that should be redrawn.
|
||||
*/
|
||||
void refreshScreenshotAtPosition(int position);
|
||||
|
||||
/**
|
||||
* Pass a click event to the view's Presenter. Typically called from the
|
||||
* view's list adapter.
|
||||
*
|
||||
* @param gameId The ID of the game that was clicked.
|
||||
*/
|
||||
void onItemClick(String gameId);
|
||||
/**
|
||||
* Pass a click event to the view's Presenter. Typically called from the
|
||||
* view's list adapter.
|
||||
*
|
||||
* @param gameId The ID of the game that was clicked.
|
||||
*/
|
||||
void onItemClick(String gameId);
|
||||
|
||||
/**
|
||||
* To be called when the game file cache is updated.
|
||||
*/
|
||||
void showGames();
|
||||
/**
|
||||
* To be called when the game file cache is updated.
|
||||
*/
|
||||
void showGames();
|
||||
}
|
||||
|
|
|
@ -18,108 +18,111 @@ import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
|
|||
|
||||
public class Analytics
|
||||
{
|
||||
private static DirectoryStateReceiver directoryStateReceiver;
|
||||
private static DirectoryStateReceiver directoryStateReceiver;
|
||||
|
||||
private static final String analyticsAsked = Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_PERMISSION_ASKED;
|
||||
private static final String analyticsEnabled = Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_ENABLED;
|
||||
private static final String analyticsAsked =
|
||||
Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_PERMISSION_ASKED;
|
||||
private static final String analyticsEnabled =
|
||||
Settings.SECTION_ANALYTICS + "_" + SettingsFile.KEY_ANALYTICS_ENABLED;
|
||||
|
||||
private static final String DEVICE_MANUFACTURER = "DEVICE_MANUFACTURER";
|
||||
private static final String DEVICE_OS = "DEVICE_OS";
|
||||
private static final String DEVICE_MODEL = "DEVICE_MODEL";
|
||||
private static final String DEVICE_TYPE = "DEVICE_TYPE";
|
||||
private static final String DEVICE_MANUFACTURER = "DEVICE_MANUFACTURER";
|
||||
private static final String DEVICE_OS = "DEVICE_OS";
|
||||
private static final String DEVICE_MODEL = "DEVICE_MODEL";
|
||||
private static final String DEVICE_TYPE = "DEVICE_TYPE";
|
||||
|
||||
private static String deviceType;
|
||||
private static String deviceType;
|
||||
|
||||
public static void checkAnalyticsInit(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!preferences.getBoolean(analyticsAsked, false))
|
||||
{
|
||||
if (!DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
// Wait for directories to get initialized
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
public static void checkAnalyticsInit(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (!preferences.getBoolean(analyticsAsked, false))
|
||||
{
|
||||
if (!DirectoryInitializationService.areDolphinDirectoriesReady())
|
||||
{
|
||||
// Wait for directories to get initialized
|
||||
IntentFilter statusIntentFilter = new IntentFilter(
|
||||
DirectoryInitializationService.BROADCAST_ACTION);
|
||||
|
||||
directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
showMessage(context, preferences);
|
||||
}
|
||||
});
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
showMessage(context, preferences);
|
||||
}
|
||||
}
|
||||
// Get device type now since we have a context
|
||||
deviceType = TvUtil.isLeanback(context) ? "android-tv" : "android-mobile";
|
||||
}
|
||||
directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState ->
|
||||
{
|
||||
if (directoryInitializationState ==
|
||||
DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
|
||||
{
|
||||
LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver);
|
||||
directoryStateReceiver = null;
|
||||
showMessage(context, preferences);
|
||||
}
|
||||
});
|
||||
// Registers the DirectoryStateReceiver and its intent filters
|
||||
LocalBroadcastManager.getInstance(context).registerReceiver(
|
||||
directoryStateReceiver,
|
||||
statusIntentFilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
showMessage(context, preferences);
|
||||
}
|
||||
}
|
||||
// Get device type now since we have a context
|
||||
deviceType = TvUtil.isLeanback(context) ? "android-tv" : "android-mobile";
|
||||
}
|
||||
|
||||
private static void showMessage(Context context, SharedPreferences preferences)
|
||||
{
|
||||
// We asked, set to true regardless of answer
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(analyticsAsked, true);
|
||||
sPrefsEditor.apply();
|
||||
private static void showMessage(Context context, SharedPreferences preferences)
|
||||
{
|
||||
// We asked, set to true regardless of answer
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(analyticsAsked, true);
|
||||
sPrefsEditor.apply();
|
||||
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(context.getString(R.string.analytics))
|
||||
.setMessage(context.getString(R.string.analytics_desc))
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) ->
|
||||
{
|
||||
sPrefsEditor.putBoolean(analyticsEnabled, true);
|
||||
sPrefsEditor.apply();
|
||||
SettingsFile.firstAnalyticsAdd(true);
|
||||
})
|
||||
.setNegativeButton(R.string.no, (dialogInterface, i) ->
|
||||
{
|
||||
sPrefsEditor.putBoolean(analyticsEnabled, false);
|
||||
sPrefsEditor.apply();
|
||||
SettingsFile.firstAnalyticsAdd(false);
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
new AlertDialog.Builder(context)
|
||||
.setTitle(context.getString(R.string.analytics))
|
||||
.setMessage(context.getString(R.string.analytics_desc))
|
||||
.setPositiveButton(R.string.yes, (dialogInterface, i) ->
|
||||
{
|
||||
sPrefsEditor.putBoolean(analyticsEnabled, true);
|
||||
sPrefsEditor.apply();
|
||||
SettingsFile.firstAnalyticsAdd(true);
|
||||
})
|
||||
.setNegativeButton(R.string.no, (dialogInterface, i) ->
|
||||
{
|
||||
sPrefsEditor.putBoolean(analyticsEnabled, false);
|
||||
sPrefsEditor.apply();
|
||||
SettingsFile.firstAnalyticsAdd(false);
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
public static void sendReport(String endpoint, byte[] data)
|
||||
{
|
||||
StringRequest request = new StringRequest(Request.Method.POST, endpoint,
|
||||
null, error -> Log.debug("Send Report Failure code: "
|
||||
+ error.networkResponse.statusCode))
|
||||
{
|
||||
@Override
|
||||
public byte[] getBody()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
};
|
||||
public static void sendReport(String endpoint, byte[] data)
|
||||
{
|
||||
StringRequest request = new StringRequest(Request.Method.POST, endpoint,
|
||||
null, error -> Log.debug("Send Report Failure code: "
|
||||
+ error.networkResponse.statusCode))
|
||||
{
|
||||
@Override
|
||||
public byte[] getBody()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
VolleyUtil.getQueue().add(request);
|
||||
}
|
||||
VolleyUtil.getQueue().add(request);
|
||||
}
|
||||
|
||||
public static String getValue(String key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case DEVICE_MODEL:
|
||||
return Build.MODEL;
|
||||
case DEVICE_MANUFACTURER:
|
||||
return Build.MANUFACTURER;
|
||||
case DEVICE_OS:
|
||||
return String.valueOf(Build.VERSION.SDK_INT);
|
||||
case DEVICE_TYPE:
|
||||
return deviceType;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public static String getValue(String key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case DEVICE_MODEL:
|
||||
return Build.MODEL;
|
||||
case DEVICE_MANUFACTURER:
|
||||
return Build.MANUFACTURER;
|
||||
case DEVICE_OS:
|
||||
return String.valueOf(Build.VERSION.SDK_INT);
|
||||
case DEVICE_TYPE:
|
||||
return deviceType;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,25 +5,25 @@ import android.view.ViewPropertyAnimator;
|
|||
|
||||
public final class Animations
|
||||
{
|
||||
private Animations()
|
||||
{
|
||||
}
|
||||
private Animations()
|
||||
{
|
||||
}
|
||||
|
||||
public static ViewPropertyAnimator fadeViewIn(View view)
|
||||
{
|
||||
view.setVisibility(View.VISIBLE);
|
||||
public static ViewPropertyAnimator fadeViewIn(View view)
|
||||
{
|
||||
view.setVisibility(View.VISIBLE);
|
||||
|
||||
return view.animate()
|
||||
.withLayer()
|
||||
.setDuration(100)
|
||||
.alpha(1.0f);
|
||||
}
|
||||
return view.animate()
|
||||
.withLayer()
|
||||
.setDuration(100)
|
||||
.alpha(1.0f);
|
||||
}
|
||||
|
||||
public static ViewPropertyAnimator fadeViewOut(View view)
|
||||
{
|
||||
return view.animate()
|
||||
.withLayer()
|
||||
.setDuration(300)
|
||||
.alpha(0.0f);
|
||||
}
|
||||
public static ViewPropertyAnimator fadeViewOut(View view)
|
||||
{
|
||||
return view.animate()
|
||||
.withLayer()
|
||||
.setDuration(300)
|
||||
.alpha(0.0f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,150 +10,150 @@ import java.util.List;
|
|||
*/
|
||||
public class AppLinkHelper
|
||||
{
|
||||
public static final String PLAY = "play";
|
||||
public static final String BROWSE = "browse";
|
||||
private static final String SCHEMA_URI_PREFIX = "dolphinemu://app/";
|
||||
private static final String URI_PLAY = SCHEMA_URI_PREFIX + PLAY;
|
||||
private static final String URI_VIEW = SCHEMA_URI_PREFIX + BROWSE;
|
||||
private static final int URI_INDEX_OPTION = 0;
|
||||
private static final int URI_INDEX_CHANNEL = 1;
|
||||
private static final int URI_INDEX_GAME = 2;
|
||||
public static final String PLAY = "play";
|
||||
public static final String BROWSE = "browse";
|
||||
private static final String SCHEMA_URI_PREFIX = "dolphinemu://app/";
|
||||
private static final String URI_PLAY = SCHEMA_URI_PREFIX + PLAY;
|
||||
private static final String URI_VIEW = SCHEMA_URI_PREFIX + BROWSE;
|
||||
private static final int URI_INDEX_OPTION = 0;
|
||||
private static final int URI_INDEX_CHANNEL = 1;
|
||||
private static final int URI_INDEX_GAME = 2;
|
||||
|
||||
public static Uri buildGameUri(long channelId, String gameId)
|
||||
{
|
||||
return Uri.parse(URI_PLAY)
|
||||
.buildUpon()
|
||||
.appendPath(String.valueOf(channelId))
|
||||
.appendPath(String.valueOf(gameId))
|
||||
.build();
|
||||
}
|
||||
public static Uri buildGameUri(long channelId, String gameId)
|
||||
{
|
||||
return Uri.parse(URI_PLAY)
|
||||
.buildUpon()
|
||||
.appendPath(String.valueOf(channelId))
|
||||
.appendPath(String.valueOf(gameId))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static Uri buildBrowseUri(String subscriptionName)
|
||||
{
|
||||
return Uri.parse(URI_VIEW).buildUpon().appendPath(subscriptionName).build();
|
||||
}
|
||||
public static Uri buildBrowseUri(String subscriptionName)
|
||||
{
|
||||
return Uri.parse(URI_VIEW).buildUpon().appendPath(subscriptionName).build();
|
||||
}
|
||||
|
||||
public static AppLinkAction extractAction(Uri uri)
|
||||
{
|
||||
if (isGameUri(uri))
|
||||
return new PlayAction(extractChannelId(uri), extractGameId(uri));
|
||||
else if (isBrowseUri(uri))
|
||||
return new BrowseAction(extractSubscriptionName(uri));
|
||||
public static AppLinkAction extractAction(Uri uri)
|
||||
{
|
||||
if (isGameUri(uri))
|
||||
return new PlayAction(extractChannelId(uri), extractGameId(uri));
|
||||
else if (isBrowseUri(uri))
|
||||
return new BrowseAction(extractSubscriptionName(uri));
|
||||
|
||||
throw new IllegalArgumentException("No action found for uri " + uri);
|
||||
}
|
||||
throw new IllegalArgumentException("No action found for uri " + uri);
|
||||
}
|
||||
|
||||
private static boolean isGameUri(Uri uri)
|
||||
{
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String option = uri.getPathSegments().get(URI_INDEX_OPTION);
|
||||
return PLAY.equals(option);
|
||||
}
|
||||
private static boolean isGameUri(Uri uri)
|
||||
{
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
String option = uri.getPathSegments().get(URI_INDEX_OPTION);
|
||||
return PLAY.equals(option);
|
||||
}
|
||||
|
||||
private static boolean isBrowseUri(Uri uri)
|
||||
{
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
return false;
|
||||
private static boolean isBrowseUri(Uri uri)
|
||||
{
|
||||
if (uri.getPathSegments().isEmpty())
|
||||
return false;
|
||||
|
||||
String option = uri.getPathSegments().get(URI_INDEX_OPTION);
|
||||
return BROWSE.equals(option);
|
||||
}
|
||||
String option = uri.getPathSegments().get(URI_INDEX_OPTION);
|
||||
return BROWSE.equals(option);
|
||||
}
|
||||
|
||||
private static String extractSubscriptionName(Uri uri)
|
||||
{
|
||||
return extract(uri, URI_INDEX_CHANNEL);
|
||||
}
|
||||
private static String extractSubscriptionName(Uri uri)
|
||||
{
|
||||
return extract(uri, URI_INDEX_CHANNEL);
|
||||
}
|
||||
|
||||
private static long extractChannelId(Uri uri)
|
||||
{
|
||||
return extractLong(uri, URI_INDEX_CHANNEL);
|
||||
}
|
||||
private static long extractChannelId(Uri uri)
|
||||
{
|
||||
return extractLong(uri, URI_INDEX_CHANNEL);
|
||||
}
|
||||
|
||||
private static String extractGameId(Uri uri)
|
||||
{
|
||||
return extract(uri, URI_INDEX_GAME);
|
||||
}
|
||||
private static String extractGameId(Uri uri)
|
||||
{
|
||||
return extract(uri, URI_INDEX_GAME);
|
||||
}
|
||||
|
||||
private static long extractLong(Uri uri, int index)
|
||||
{
|
||||
return Long.valueOf(extract(uri, index));
|
||||
}
|
||||
private static long extractLong(Uri uri, int index)
|
||||
{
|
||||
return Long.valueOf(extract(uri, index));
|
||||
}
|
||||
|
||||
private static String extract(Uri uri, int index)
|
||||
{
|
||||
List<String> pathSegments = uri.getPathSegments();
|
||||
if (pathSegments.isEmpty() || pathSegments.size() < index)
|
||||
return null;
|
||||
return pathSegments.get(index);
|
||||
}
|
||||
private static String extract(Uri uri, int index)
|
||||
{
|
||||
List<String> pathSegments = uri.getPathSegments();
|
||||
if (pathSegments.isEmpty() || pathSegments.size() < index)
|
||||
return null;
|
||||
return pathSegments.get(index);
|
||||
}
|
||||
|
||||
@StringDef({BROWSE, PLAY})
|
||||
public @interface ActionFlags
|
||||
{
|
||||
}
|
||||
@StringDef({BROWSE, PLAY})
|
||||
public @interface ActionFlags
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Action for deep linking.
|
||||
*/
|
||||
public interface AppLinkAction
|
||||
{
|
||||
/**
|
||||
* Returns an string representation of the action.
|
||||
*/
|
||||
@ActionFlags
|
||||
String getAction();
|
||||
}
|
||||
/**
|
||||
* Action for deep linking.
|
||||
*/
|
||||
public interface AppLinkAction
|
||||
{
|
||||
/**
|
||||
* Returns an string representation of the action.
|
||||
*/
|
||||
@ActionFlags
|
||||
String getAction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action when clicking the channel icon
|
||||
*/
|
||||
public static class BrowseAction implements AppLinkAction
|
||||
{
|
||||
private final String mSubscriptionName;
|
||||
/**
|
||||
* Action when clicking the channel icon
|
||||
*/
|
||||
public static class BrowseAction implements AppLinkAction
|
||||
{
|
||||
private final String mSubscriptionName;
|
||||
|
||||
private BrowseAction(String subscriptionName)
|
||||
{
|
||||
this.mSubscriptionName = subscriptionName;
|
||||
}
|
||||
private BrowseAction(String subscriptionName)
|
||||
{
|
||||
this.mSubscriptionName = subscriptionName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction()
|
||||
{
|
||||
return BROWSE;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String getAction()
|
||||
{
|
||||
return BROWSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action when clicking a program(game)
|
||||
*/
|
||||
public static class PlayAction implements AppLinkAction
|
||||
{
|
||||
private final long channelId;
|
||||
private final String gameId;
|
||||
/**
|
||||
* Action when clicking a program(game)
|
||||
*/
|
||||
public static class PlayAction implements AppLinkAction
|
||||
{
|
||||
private final long channelId;
|
||||
private final String gameId;
|
||||
|
||||
private PlayAction(long channelId, String gameId)
|
||||
{
|
||||
this.channelId = channelId;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
private PlayAction(long channelId, String gameId)
|
||||
{
|
||||
this.channelId = channelId;
|
||||
this.gameId = gameId;
|
||||
}
|
||||
|
||||
public long getChannelId()
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
public long getChannelId()
|
||||
{
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public String getGameId()
|
||||
{
|
||||
return gameId;
|
||||
}
|
||||
public String getGameId()
|
||||
{
|
||||
return gameId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction()
|
||||
{
|
||||
return PLAY;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public String getAction()
|
||||
{
|
||||
return PLAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,22 +6,22 @@ import java.util.Map;
|
|||
public class BiMap<K, V>
|
||||
{
|
||||
|
||||
private Map<K, V> forward = new HashMap<K, V>();
|
||||
private Map<V, K> backward = new HashMap<V, K>();
|
||||
private Map<K, V> forward = new HashMap<K, V>();
|
||||
private Map<V, K> backward = new HashMap<V, K>();
|
||||
|
||||
public synchronized void add(K key, V value)
|
||||
{
|
||||
forward.put(key, value);
|
||||
backward.put(value, key);
|
||||
}
|
||||
public synchronized void add(K key, V value)
|
||||
{
|
||||
forward.put(key, value);
|
||||
backward.put(value, key);
|
||||
}
|
||||
|
||||
public synchronized V getForward(K key)
|
||||
{
|
||||
return forward.get(key);
|
||||
}
|
||||
public synchronized V getForward(K key)
|
||||
{
|
||||
return forward.get(key);
|
||||
}
|
||||
|
||||
public synchronized K getBackward(V key)
|
||||
{
|
||||
return backward.get(key);
|
||||
}
|
||||
public synchronized K getBackward(V key)
|
||||
{
|
||||
return backward.get(key);
|
||||
}
|
||||
}
|
|
@ -4,54 +4,61 @@ import android.view.InputDevice;
|
|||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/** Some controllers have incorrect mappings. This class has special-case fixes for them. */
|
||||
/**
|
||||
* Some controllers have incorrect mappings. This class has special-case fixes for them.
|
||||
*/
|
||||
public class ControllerMappingHelper
|
||||
{
|
||||
/** Some controllers report extra button presses that can be ignored. */
|
||||
public static boolean shouldKeyBeIgnored(InputDevice inputDevice, int keyCode)
|
||||
{
|
||||
if (isDualShock4(inputDevice)) {
|
||||
// The two analog triggers generate analog motion events as well as a keycode.
|
||||
// We always prefer to use the analog values, so throw away the button press
|
||||
// Even though the triggers are L/R2, without mappings they generate L/R1 events.
|
||||
return keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_R1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Some controllers report extra button presses that can be ignored.
|
||||
*/
|
||||
public static boolean shouldKeyBeIgnored(InputDevice inputDevice, int keyCode)
|
||||
{
|
||||
if (isDualShock4(inputDevice))
|
||||
{
|
||||
// The two analog triggers generate analog motion events as well as a keycode.
|
||||
// We always prefer to use the analog values, so throw away the button press
|
||||
// Even though the triggers are L/R2, without mappings they generate L/R1 events.
|
||||
return keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_R1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Scale an axis to be zero-centered with a proper range. */
|
||||
public static float scaleAxis(InputDevice inputDevice, int axis, float value)
|
||||
{
|
||||
if (isDualShock4(inputDevice))
|
||||
{
|
||||
// Android doesn't have correct mappings for this controller's triggers. It reports them
|
||||
// as RX & RY, centered at -1.0, and with a range of [-1.0, 1.0]
|
||||
// Scale them to properly zero-centered with a range of [0.0, 1.0].
|
||||
if (axis == MotionEvent.AXIS_RX || axis == MotionEvent.AXIS_RY)
|
||||
{
|
||||
return (value + 1) / 2.0f;
|
||||
}
|
||||
}
|
||||
else if (isXboxOneWireless(inputDevice))
|
||||
{
|
||||
// Same as the DualShock 4, the mappings are missing.
|
||||
if (axis == MotionEvent.AXIS_Z || axis == MotionEvent.AXIS_RZ)
|
||||
{
|
||||
return (value + 1) / 2.0f;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Scale an axis to be zero-centered with a proper range.
|
||||
*/
|
||||
public static float scaleAxis(InputDevice inputDevice, int axis, float value)
|
||||
{
|
||||
if (isDualShock4(inputDevice))
|
||||
{
|
||||
// Android doesn't have correct mappings for this controller's triggers. It reports them
|
||||
// as RX & RY, centered at -1.0, and with a range of [-1.0, 1.0]
|
||||
// Scale them to properly zero-centered with a range of [0.0, 1.0].
|
||||
if (axis == MotionEvent.AXIS_RX || axis == MotionEvent.AXIS_RY)
|
||||
{
|
||||
return (value + 1) / 2.0f;
|
||||
}
|
||||
}
|
||||
else if (isXboxOneWireless(inputDevice))
|
||||
{
|
||||
// Same as the DualShock 4, the mappings are missing.
|
||||
if (axis == MotionEvent.AXIS_Z || axis == MotionEvent.AXIS_RZ)
|
||||
{
|
||||
return (value + 1) / 2.0f;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static boolean isDualShock4(InputDevice inputDevice)
|
||||
{
|
||||
// Sony DualShock 4 controller
|
||||
return inputDevice.getVendorId() == 0x54c && inputDevice.getProductId() == 0x9cc;
|
||||
}
|
||||
private static boolean isDualShock4(InputDevice inputDevice)
|
||||
{
|
||||
// Sony DualShock 4 controller
|
||||
return inputDevice.getVendorId() == 0x54c && inputDevice.getProductId() == 0x9cc;
|
||||
}
|
||||
|
||||
private static boolean isXboxOneWireless(InputDevice inputDevice)
|
||||
{
|
||||
// Microsoft Xbox One controller
|
||||
return inputDevice.getVendorId() == 0x45e && inputDevice.getProductId() == 0x2e0;
|
||||
}
|
||||
private static boolean isXboxOneWireless(InputDevice inputDevice)
|
||||
{
|
||||
// Microsoft Xbox One controller
|
||||
return inputDevice.getVendorId() == 0x45e && inputDevice.getProductId() == 0x2e0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,79 +3,78 @@ package org.dolphinemu.dolphinemu.utils;
|
|||
import android.graphics.Bitmap;
|
||||
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
public final class CoverHelper
|
||||
{
|
||||
private static String baseUrl = "https://art.gametdb.com/wii/cover/%s/%s.png";
|
||||
private static String baseUrl = "https://art.gametdb.com/wii/cover/%s/%s.png";
|
||||
|
||||
public static String buildGameTDBUrl(GameFile game, String region)
|
||||
{
|
||||
String gameId = game.getGameId();
|
||||
if(game.getPlatform() == 2) // WiiWare
|
||||
gameId = gameId.substring(0,4);
|
||||
return String.format(baseUrl, region, gameId);
|
||||
}
|
||||
public static String buildGameTDBUrl(GameFile game, String region)
|
||||
{
|
||||
String gameId = game.getGameId();
|
||||
if (game.getPlatform() == 2) // WiiWare
|
||||
gameId = gameId.substring(0, 4);
|
||||
return String.format(baseUrl, region, gameId);
|
||||
}
|
||||
|
||||
public static String getRegion(GameFile game)
|
||||
{
|
||||
String region;
|
||||
switch(game.getRegion())
|
||||
{
|
||||
case 0: // NTSC_J
|
||||
region = "JA";
|
||||
break;
|
||||
case 1: // NTSC_U
|
||||
region = "US";
|
||||
break;
|
||||
case 4: // NTSC_K
|
||||
region = "KO";
|
||||
break;
|
||||
case 2: // PAL
|
||||
switch (game.getCountry())
|
||||
{
|
||||
case 2: // German
|
||||
region = "DE";
|
||||
break;
|
||||
case 3: // French
|
||||
region = "FR";
|
||||
break;
|
||||
case 4: // Spanish
|
||||
region = "ES";
|
||||
break;
|
||||
case 5: // Italian
|
||||
region = "IT";
|
||||
break;
|
||||
case 6: // Dutch
|
||||
region = "NL";
|
||||
break;
|
||||
case 1: // English
|
||||
default:
|
||||
region = "EN";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: // Unknown
|
||||
default:
|
||||
region = "EN";
|
||||
break;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
public static String getRegion(GameFile game)
|
||||
{
|
||||
String region;
|
||||
switch (game.getRegion())
|
||||
{
|
||||
case 0: // NTSC_J
|
||||
region = "JA";
|
||||
break;
|
||||
case 1: // NTSC_U
|
||||
region = "US";
|
||||
break;
|
||||
case 4: // NTSC_K
|
||||
region = "KO";
|
||||
break;
|
||||
case 2: // PAL
|
||||
switch (game.getCountry())
|
||||
{
|
||||
case 2: // German
|
||||
region = "DE";
|
||||
break;
|
||||
case 3: // French
|
||||
region = "FR";
|
||||
break;
|
||||
case 4: // Spanish
|
||||
region = "ES";
|
||||
break;
|
||||
case 5: // Italian
|
||||
region = "IT";
|
||||
break;
|
||||
case 6: // Dutch
|
||||
region = "NL";
|
||||
break;
|
||||
case 1: // English
|
||||
default:
|
||||
region = "EN";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: // Unknown
|
||||
default:
|
||||
region = "EN";
|
||||
break;
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
public static void saveCover(Bitmap cover, String path)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileOutputStream out = new FileOutputStream(path);
|
||||
cover.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
out.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
public static void saveCover(Bitmap cover, String path)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileOutputStream out = new FileOutputStream(path);
|
||||
cover.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
out.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,16 +9,20 @@ import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.Directo
|
|||
|
||||
import rx.functions.Action1;
|
||||
|
||||
public class DirectoryStateReceiver extends BroadcastReceiver {
|
||||
Action1<DirectoryInitializationState> callback;
|
||||
public DirectoryStateReceiver(Action1<DirectoryInitializationState> callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
public class DirectoryStateReceiver extends BroadcastReceiver
|
||||
{
|
||||
Action1<DirectoryInitializationState> callback;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
DirectoryInitializationState state = (DirectoryInitializationState) intent.getSerializableExtra(DirectoryInitializationService.EXTRA_STATE);
|
||||
callback.call(state);
|
||||
}
|
||||
public DirectoryStateReceiver(Action1<DirectoryInitializationState> callback)
|
||||
{
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
DirectoryInitializationState state = (DirectoryInitializationState) intent
|
||||
.getSerializableExtra(DirectoryInitializationService.EXTRA_STATE);
|
||||
callback.call(state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,367 +24,366 @@ import javax.microedition.khronos.opengles.GL10;
|
|||
*/
|
||||
public final class EGLHelper
|
||||
{
|
||||
private final EGL10 mEGL;
|
||||
private final EGLDisplay mDisplay;
|
||||
private EGLConfig[] mEGLConfigs;
|
||||
private EGLContext mEGLContext;
|
||||
private EGLSurface mEGLSurface;
|
||||
private GL10 mGL;
|
||||
private final EGL10 mEGL;
|
||||
private final EGLDisplay mDisplay;
|
||||
private EGLConfig[] mEGLConfigs;
|
||||
private EGLContext mEGLContext;
|
||||
private EGLSurface mEGLSurface;
|
||||
private GL10 mGL;
|
||||
|
||||
// GL support flags
|
||||
private boolean supportGL;
|
||||
private boolean supportGLES2;
|
||||
private boolean supportGLES3;
|
||||
// GL support flags
|
||||
private boolean supportGL;
|
||||
private boolean supportGLES2;
|
||||
private boolean supportGLES3;
|
||||
|
||||
// Renderable type bitmasks
|
||||
public static final int EGL_OPENGL_ES_BIT = 0x0001;
|
||||
public static final int EGL_OPENGL_ES2_BIT = 0x0004;
|
||||
public static final int EGL_OPENGL_BIT = 0x0008;
|
||||
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
|
||||
// Renderable type bitmasks
|
||||
public static final int EGL_OPENGL_ES_BIT = 0x0001;
|
||||
public static final int EGL_OPENGL_ES2_BIT = 0x0004;
|
||||
public static final int EGL_OPENGL_BIT = 0x0008;
|
||||
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
|
||||
|
||||
// API types
|
||||
public static final int EGL_OPENGL_ES_API = 0x30A0;
|
||||
public static final int EGL_OPENGL_API = 0x30A2;
|
||||
// API types
|
||||
public static final int EGL_OPENGL_ES_API = 0x30A0;
|
||||
public static final int EGL_OPENGL_API = 0x30A2;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* <p>
|
||||
* Initializes the underlying {@link EGLSurface} with a width and height of 1.
|
||||
* This is useful if all you need to use this class for is to query information
|
||||
* from specific API contexts.
|
||||
*
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int renderableType)
|
||||
{
|
||||
this(1, 1, renderableType);
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
* <p>
|
||||
* Initializes the underlying {@link EGLSurface} with a width and height of 1.
|
||||
* This is useful if all you need to use this class for is to query information
|
||||
* from specific API contexts.
|
||||
*
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int renderableType)
|
||||
{
|
||||
this(1, 1, renderableType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param width Width of the underlying {@link EGLSurface}.
|
||||
* @param height Height of the underlying {@link EGLSurface}.
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int width, int height, int renderableType)
|
||||
{
|
||||
// Initialize handle to an EGL display.
|
||||
mEGL = (EGL10) EGLContext.getEGL();
|
||||
mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param width Width of the underlying {@link EGLSurface}.
|
||||
* @param height Height of the underlying {@link EGLSurface}.
|
||||
* @param renderableType Bitmask indicating which types of client API contexts
|
||||
* the framebuffer config must support.
|
||||
*/
|
||||
public EGLHelper(int width, int height, int renderableType)
|
||||
{
|
||||
// Initialize handle to an EGL display.
|
||||
mEGL = (EGL10) EGLContext.getEGL();
|
||||
mDisplay = mEGL.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||
|
||||
// If a display is present, initialize EGL.
|
||||
if (mDisplay != EGL10.EGL_NO_DISPLAY)
|
||||
{
|
||||
int[] version = new int[2];
|
||||
if (mEGL.eglInitialize(mDisplay, version))
|
||||
{
|
||||
// Detect supported GL APIs, initialize configs, etc.
|
||||
detect();
|
||||
// If a display is present, initialize EGL.
|
||||
if (mDisplay != EGL10.EGL_NO_DISPLAY)
|
||||
{
|
||||
int[] version = new int[2];
|
||||
if (mEGL.eglInitialize(mDisplay, version))
|
||||
{
|
||||
// Detect supported GL APIs, initialize configs, etc.
|
||||
detect();
|
||||
|
||||
// Create context and surface
|
||||
create(width, height, renderableType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[EGLHelper] Error initializing EGL.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[EGLHelper] Error initializing EGL display.");
|
||||
}
|
||||
}
|
||||
// Create context and surface
|
||||
create(width, height, renderableType);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[EGLHelper] Error initializing EGL.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error("[EGLHelper] Error initializing EGL display.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources associated with this helper.
|
||||
* <p>
|
||||
* This should be called whenever this helper is no longer needed.
|
||||
*/
|
||||
public void closeHelper()
|
||||
{
|
||||
mEGL.eglTerminate(mDisplay);
|
||||
}
|
||||
/**
|
||||
* Releases all resources associated with this helper.
|
||||
* <p>
|
||||
* This should be called whenever this helper is no longer needed.
|
||||
*/
|
||||
public void closeHelper()
|
||||
{
|
||||
mEGL.eglTerminate(mDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information through EGL.<br/>
|
||||
* <p>
|
||||
* Index 0: Vendor <br/>
|
||||
* Index 1: Version <br/>
|
||||
* Index 2: Renderer <br/>
|
||||
* Index 3: Extensions <br/>
|
||||
*
|
||||
* @return information retrieved through EGL.
|
||||
*/
|
||||
public String[] getEGLInfo()
|
||||
{
|
||||
return new String[] {
|
||||
mGL.glGetString(GL10.GL_VENDOR),
|
||||
mGL.glGetString(GL10.GL_VERSION),
|
||||
mGL.glGetString(GL10.GL_RENDERER),
|
||||
mGL.glGetString(GL10.GL_EXTENSIONS),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Gets information through EGL.<br/>
|
||||
* <p>
|
||||
* Index 0: Vendor <br/>
|
||||
* Index 1: Version <br/>
|
||||
* Index 2: Renderer <br/>
|
||||
* Index 3: Extensions <br/>
|
||||
*
|
||||
* @return information retrieved through EGL.
|
||||
*/
|
||||
public String[] getEGLInfo()
|
||||
{
|
||||
return new String[]{
|
||||
mGL.glGetString(GL10.GL_VENDOR),
|
||||
mGL.glGetString(GL10.GL_VERSION),
|
||||
mGL.glGetString(GL10.GL_RENDERER),
|
||||
mGL.glGetString(GL10.GL_EXTENSIONS),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this device supports OpenGL.
|
||||
*
|
||||
* @return true if this device supports OpenGL; false otherwise.
|
||||
*/
|
||||
public boolean supportsOpenGL()
|
||||
{
|
||||
return supportGL;
|
||||
}
|
||||
/**
|
||||
* Whether or not this device supports OpenGL.
|
||||
*
|
||||
* @return true if this device supports OpenGL; false otherwise.
|
||||
*/
|
||||
public boolean supportsOpenGL()
|
||||
{
|
||||
return supportGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this device supports OpenGL ES 2.
|
||||
* <br/>
|
||||
* Note that if this returns true, then OpenGL ES 1 is also supported.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 2; false otherwise.
|
||||
*/
|
||||
public boolean supportsGLES2()
|
||||
{
|
||||
return supportGLES2;
|
||||
}
|
||||
/**
|
||||
* Whether or not this device supports OpenGL ES 2.
|
||||
* <br/>
|
||||
* Note that if this returns true, then OpenGL ES 1 is also supported.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 2; false otherwise.
|
||||
*/
|
||||
public boolean supportsGLES2()
|
||||
{
|
||||
return supportGLES2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this device supports OpenGL ES 3.
|
||||
* <br/>
|
||||
* Note that if this returns true, then OpenGL ES 1 and 2 are also supported.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 3; false otherwise.
|
||||
*/
|
||||
public boolean supportsGLES3()
|
||||
{
|
||||
return supportGLES3;
|
||||
}
|
||||
/**
|
||||
* Whether or not this device supports OpenGL ES 3.
|
||||
* <br/>
|
||||
* Note that if this returns true, then OpenGL ES 1 and 2 are also supported.
|
||||
*
|
||||
* @return true if this device supports OpenGL ES 3; false otherwise.
|
||||
*/
|
||||
public boolean supportsGLES3()
|
||||
{
|
||||
return supportGLES3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGL10} instance.
|
||||
*
|
||||
* @return the underlying {@link EGL10} instance.
|
||||
*/
|
||||
public EGL10 getEGL()
|
||||
{
|
||||
return mEGL;
|
||||
}
|
||||
/**
|
||||
* Gets the underlying {@link EGL10} instance.
|
||||
*
|
||||
* @return the underlying {@link EGL10} instance.
|
||||
*/
|
||||
public EGL10 getEGL()
|
||||
{
|
||||
return mEGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link GL10} instance.
|
||||
*
|
||||
* @return the underlying {@link GL10} instance.
|
||||
*/
|
||||
public GL10 getGL()
|
||||
{
|
||||
return mGL;
|
||||
}
|
||||
/**
|
||||
* Gets the underlying {@link GL10} instance.
|
||||
*
|
||||
* @return the underlying {@link GL10} instance.
|
||||
*/
|
||||
public GL10 getGL()
|
||||
{
|
||||
return mGL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLDisplay}.
|
||||
*
|
||||
* @return the underlying {@link EGLDisplay}
|
||||
*/
|
||||
public EGLDisplay getDisplay()
|
||||
{
|
||||
return mDisplay;
|
||||
}
|
||||
/**
|
||||
* Gets the underlying {@link EGLDisplay}.
|
||||
*
|
||||
* @return the underlying {@link EGLDisplay}
|
||||
*/
|
||||
public EGLDisplay getDisplay()
|
||||
{
|
||||
return mDisplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all supported framebuffer configurations for this device.
|
||||
*
|
||||
* @return all supported framebuffer configurations for this device.
|
||||
*/
|
||||
public EGLConfig[] getConfigs()
|
||||
{
|
||||
return mEGLConfigs;
|
||||
}
|
||||
/**
|
||||
* Gets all supported framebuffer configurations for this device.
|
||||
*
|
||||
* @return all supported framebuffer configurations for this device.
|
||||
*/
|
||||
public EGLConfig[] getConfigs()
|
||||
{
|
||||
return mEGLConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLContext}.
|
||||
*
|
||||
* @return the underlying {@link EGLContext}.
|
||||
*/
|
||||
public EGLContext getContext()
|
||||
{
|
||||
return mEGLContext;
|
||||
}
|
||||
/**
|
||||
* Gets the underlying {@link EGLContext}.
|
||||
*
|
||||
* @return the underlying {@link EGLContext}.
|
||||
*/
|
||||
public EGLContext getContext()
|
||||
{
|
||||
return mEGLContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying {@link EGLSurface}.
|
||||
*
|
||||
* @return the underlying {@link EGLSurface}.
|
||||
*/
|
||||
public EGLSurface getSurface()
|
||||
{
|
||||
return mEGLSurface;
|
||||
}
|
||||
/**
|
||||
* Gets the underlying {@link EGLSurface}.
|
||||
*
|
||||
* @return the underlying {@link EGLSurface}.
|
||||
*/
|
||||
public EGLSurface getSurface()
|
||||
{
|
||||
return mEGLSurface;
|
||||
}
|
||||
|
||||
// Detects the specific kind of GL modes that are supported
|
||||
private boolean detect()
|
||||
{
|
||||
// Get total number of configs available.
|
||||
int[] numConfigs = new int[1];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs))
|
||||
{
|
||||
Log.error("[EGLHelper] Error retrieving number of EGL configs available.");
|
||||
return false;
|
||||
}
|
||||
// Detects the specific kind of GL modes that are supported
|
||||
private boolean detect()
|
||||
{
|
||||
// Get total number of configs available.
|
||||
int[] numConfigs = new int[1];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, null, 0, numConfigs))
|
||||
{
|
||||
Log.error("[EGLHelper] Error retrieving number of EGL configs available.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now get all the configurations
|
||||
mEGLConfigs = new EGLConfig[numConfigs[0]];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs))
|
||||
{
|
||||
Log.error("[EGLHelper] Error retrieving all EGL configs.");
|
||||
return false;
|
||||
}
|
||||
// Now get all the configurations
|
||||
mEGLConfigs = new EGLConfig[numConfigs[0]];
|
||||
if (!mEGL.eglGetConfigs(mDisplay, mEGLConfigs, mEGLConfigs.length, numConfigs))
|
||||
{
|
||||
Log.error("[EGLHelper] Error retrieving all EGL configs.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (EGLConfig mEGLConfig : mEGLConfigs)
|
||||
{
|
||||
int[] attribVal = new int[1];
|
||||
boolean ret = mEGL.eglGetConfigAttrib(mDisplay, mEGLConfig, EGL10.EGL_RENDERABLE_TYPE, attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if ((attribVal[0] & EGL_OPENGL_BIT) != 0)
|
||||
supportGL = true;
|
||||
for (EGLConfig mEGLConfig : mEGLConfigs)
|
||||
{
|
||||
int[] attribVal = new int[1];
|
||||
boolean ret =
|
||||
mEGL.eglGetConfigAttrib(mDisplay, mEGLConfig, EGL10.EGL_RENDERABLE_TYPE, attribVal);
|
||||
if (ret)
|
||||
{
|
||||
if ((attribVal[0] & EGL_OPENGL_BIT) != 0)
|
||||
supportGL = true;
|
||||
|
||||
if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0)
|
||||
supportGLES2 = true;
|
||||
if ((attribVal[0] & EGL_OPENGL_ES2_BIT) != 0)
|
||||
supportGLES2 = true;
|
||||
|
||||
if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0)
|
||||
supportGLES3 = true;
|
||||
}
|
||||
}
|
||||
if ((attribVal[0] & EGL_OPENGL_ES3_BIT_KHR) != 0)
|
||||
supportGLES3 = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates the context and surface.
|
||||
private void create(int width, int height, int renderableType)
|
||||
{
|
||||
int[] attribs = {
|
||||
EGL10.EGL_WIDTH, width,
|
||||
EGL10.EGL_HEIGHT, height,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
// Creates the context and surface.
|
||||
private void create(int width, int height, int renderableType)
|
||||
{
|
||||
int[] attribs = {
|
||||
EGL10.EGL_WIDTH, width,
|
||||
EGL10.EGL_HEIGHT, height,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// Initially we just assume GLES2 will be the default context.
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] ctx_attribs = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
// Initially we just assume GLES2 will be the default context.
|
||||
int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
|
||||
int[] ctx_attribs = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL10.EGL_NONE
|
||||
};
|
||||
|
||||
// Determine the type of context that will be created
|
||||
// and change the attribute arrays accordingly.
|
||||
switch (renderableType)
|
||||
{
|
||||
case EGL_OPENGL_ES_BIT:
|
||||
ctx_attribs[1] = 1;
|
||||
break;
|
||||
// Determine the type of context that will be created
|
||||
// and change the attribute arrays accordingly.
|
||||
switch (renderableType)
|
||||
{
|
||||
case EGL_OPENGL_ES_BIT:
|
||||
ctx_attribs[1] = 1;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_BIT:
|
||||
ctx_attribs[0] = EGL10.EGL_NONE;
|
||||
break;
|
||||
case EGL_OPENGL_BIT:
|
||||
ctx_attribs[0] = EGL10.EGL_NONE;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES3_BIT_KHR:
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
case EGL_OPENGL_ES3_BIT_KHR:
|
||||
ctx_attribs[1] = 3;
|
||||
break;
|
||||
|
||||
case EGL_OPENGL_ES2_BIT:
|
||||
default: // Fall-back to GLES 2.
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
}
|
||||
if (renderableType == EGL_OPENGL_BIT)
|
||||
NativeLibrary.eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
NativeLibrary.eglBindAPI(EGL_OPENGL_ES_API);
|
||||
case EGL_OPENGL_ES2_BIT:
|
||||
default: // Fall-back to GLES 2.
|
||||
ctx_attribs[1] = 2;
|
||||
break;
|
||||
}
|
||||
if (renderableType == EGL_OPENGL_BIT)
|
||||
NativeLibrary.eglBindAPI(EGL_OPENGL_API);
|
||||
else
|
||||
NativeLibrary.eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
mEGLContext = mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs);
|
||||
mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs);
|
||||
mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
||||
mGL = (GL10) mEGLContext.getGL();
|
||||
}
|
||||
mEGLContext =
|
||||
mEGL.eglCreateContext(mDisplay, mEGLConfigs[0], EGL10.EGL_NO_CONTEXT, ctx_attribs);
|
||||
mEGLSurface = mEGL.eglCreatePbufferSurface(mDisplay, mEGLConfigs[0], attribs);
|
||||
mEGL.eglMakeCurrent(mDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
||||
mGL = (GL10) mEGLContext.getGL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetString(int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic constant within {@link GL10}.
|
||||
*
|
||||
* @return the string information represented by {@code glEnum}.
|
||||
*/
|
||||
public String glGetString(int glEnum)
|
||||
{
|
||||
return mGL.glGetString(glEnum);
|
||||
}
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetString(int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic constant within {@link GL10}.
|
||||
* @return the string information represented by {@code glEnum}.
|
||||
*/
|
||||
public String glGetString(int glEnum)
|
||||
{
|
||||
return mGL.glGetString(glEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GLES30#glGetStringi(int, int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* <li>GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic GL constant
|
||||
* @param index The index of the string to return.
|
||||
*
|
||||
* @return the string information represented by {@code glEnum} and {@code index}.
|
||||
*/
|
||||
public String glGetStringi(int glEnum, int index)
|
||||
{
|
||||
return GLES30.glGetStringi(glEnum, index);
|
||||
}
|
||||
/**
|
||||
* Simplified call to {@link GLES30#glGetStringi(int, int)}
|
||||
* <p>
|
||||
* Accepts the following constants:
|
||||
* <ul>
|
||||
* <li>GL_VENDOR - Company responsible for the GL implementation.</li>
|
||||
* <li>GL_VERSION - Version or release number.</li>
|
||||
* <li>GL_RENDERER - Name of the renderer</li>
|
||||
* <li>GL_SHADING_LANGUAGE_VERSION - Version or release number of the shading language </li>
|
||||
* <li>GL_EXTENSIONS - Extension string supported by the implementation at {@code index}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param glEnum A symbolic GL constant
|
||||
* @param index The index of the string to return.
|
||||
* @return the string information represented by {@code glEnum} and {@code index}.
|
||||
*/
|
||||
public String glGetStringi(int glEnum, int index)
|
||||
{
|
||||
return GLES30.glGetStringi(glEnum, index);
|
||||
}
|
||||
|
||||
public boolean SupportsExtension(String extension)
|
||||
{
|
||||
int[] num_ext = new int[1];
|
||||
GLES30.glGetIntegerv(GLES30.GL_NUM_EXTENSIONS, num_ext, 0);
|
||||
public boolean SupportsExtension(String extension)
|
||||
{
|
||||
int[] num_ext = new int[1];
|
||||
GLES30.glGetIntegerv(GLES30.GL_NUM_EXTENSIONS, num_ext, 0);
|
||||
|
||||
for (int i = 0; i < num_ext[0]; ++i)
|
||||
{
|
||||
String ext = GLES30.glGetStringi(GLES30.GL_EXTENSIONS, i);
|
||||
if (ext.equals(extension))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < num_ext[0]; ++i)
|
||||
{
|
||||
String ext = GLES30.glGetStringi(GLES30.GL_EXTENSIONS, i);
|
||||
if (ext.equals(extension))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetVersion()
|
||||
{
|
||||
int[] major = new int[1];
|
||||
int[] minor = new int[1];
|
||||
GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, major, 0);
|
||||
GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, minor, 0);
|
||||
return major[0] * 100 + minor[0] * 10;
|
||||
}
|
||||
public int GetVersion()
|
||||
{
|
||||
int[] major = new int[1];
|
||||
int[] minor = new int[1];
|
||||
GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, major, 0);
|
||||
GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, minor, 0);
|
||||
return major[0] * 100 + minor[0] * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetIntegerv(int, int[], int)
|
||||
*
|
||||
* @param glEnum A symbolic GL constant.
|
||||
*
|
||||
* @return the integer information represented by {@code glEnum}.
|
||||
*/
|
||||
public int glGetInteger(int glEnum)
|
||||
{
|
||||
int[] val = new int[1];
|
||||
mGL.glGetIntegerv(glEnum, val, 0);
|
||||
return val[0];
|
||||
}
|
||||
/**
|
||||
* Simplified call to {@link GL10#glGetIntegerv(int, int[], int)
|
||||
*
|
||||
* @param glEnum A symbolic GL constant.
|
||||
* @return the integer information represented by {@code glEnum}.
|
||||
*/
|
||||
public int glGetInteger(int glEnum)
|
||||
{
|
||||
int[] val = new int[1];
|
||||
mGL.glGetIntegerv(glEnum, val, 0);
|
||||
return val[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,41 +17,43 @@ import java.util.List;
|
|||
|
||||
public final class FileBrowserHelper
|
||||
{
|
||||
public static void openDirectoryPicker(FragmentActivity activity)
|
||||
public static void openDirectoryPicker(FragmentActivity activity)
|
||||
{
|
||||
Intent i = new Intent(activity, CustomFilePickerActivity.class);
|
||||
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
|
||||
i.putExtra(FilePickerActivity.EXTRA_START_PATH,
|
||||
Environment.getExternalStorageDirectory().getPath());
|
||||
|
||||
activity.startActivityForResult(i, MainPresenter.REQUEST_ADD_DIRECTORY);
|
||||
}
|
||||
|
||||
public static void openFilePicker(FragmentActivity activity, int requestCode)
|
||||
{
|
||||
Intent i = new Intent(activity, CustomFilePickerActivity.class);
|
||||
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE);
|
||||
i.putExtra(FilePickerActivity.EXTRA_START_PATH,
|
||||
Environment.getExternalStorageDirectory().getPath());
|
||||
|
||||
activity.startActivityForResult(i, requestCode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getSelectedDirectory(Intent result)
|
||||
{
|
||||
// Use the provided utility method to parse the result
|
||||
List<Uri> files = Utils.getSelectedFilesFromResult(result);
|
||||
if (!files.isEmpty())
|
||||
{
|
||||
Intent i = new Intent(activity, CustomFilePickerActivity.class);
|
||||
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
|
||||
i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath());
|
||||
|
||||
activity.startActivityForResult(i, MainPresenter.REQUEST_ADD_DIRECTORY);
|
||||
File file = Utils.getFileForUri(files.get(0));
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
public static void openFilePicker(FragmentActivity activity, int requestCode)
|
||||
{
|
||||
Intent i = new Intent(activity, CustomFilePickerActivity.class);
|
||||
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false);
|
||||
i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE);
|
||||
i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath());
|
||||
|
||||
activity.startActivityForResult(i, requestCode);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getSelectedDirectory(Intent result)
|
||||
{
|
||||
// Use the provided utility method to parse the result
|
||||
List<Uri> files = Utils.getSelectedFilesFromResult(result);
|
||||
if (!files.isEmpty())
|
||||
{
|
||||
File file = Utils.getFileForUri(files.get(0));
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,134 +19,143 @@ import org.dolphinemu.dolphinemu.services.USBPermService;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Java_GCAdapter {
|
||||
public static UsbManager manager;
|
||||
static byte[] controller_payload = new byte[37];
|
||||
public class Java_GCAdapter
|
||||
{
|
||||
public static UsbManager manager;
|
||||
static byte[] controller_payload = new byte[37];
|
||||
|
||||
static UsbDeviceConnection usb_con;
|
||||
static UsbInterface usb_intf;
|
||||
static UsbEndpoint usb_in;
|
||||
static UsbEndpoint usb_out;
|
||||
static UsbDeviceConnection usb_con;
|
||||
static UsbInterface usb_intf;
|
||||
static UsbEndpoint usb_in;
|
||||
static UsbEndpoint usb_out;
|
||||
|
||||
private static void RequestPermission()
|
||||
{
|
||||
Context context = NativeLibrary.sEmulationActivity.get();
|
||||
if (context != null)
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (!manager.hasPermission(dev))
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
PendingIntent pend_intent;
|
||||
intent.setClass(context, USBPermService.class);
|
||||
pend_intent = PendingIntent.getService(context, 0, intent, 0);
|
||||
manager.requestPermission(dev, pend_intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot request GameCube Adapter permission as EmulationActivity is null.");
|
||||
}
|
||||
private static void RequestPermission()
|
||||
{
|
||||
Context context = NativeLibrary.sEmulationActivity.get();
|
||||
if (context != null)
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (!manager.hasPermission(dev))
|
||||
{
|
||||
Intent intent = new Intent();
|
||||
PendingIntent pend_intent;
|
||||
intent.setClass(context, USBPermService.class);
|
||||
pend_intent = PendingIntent.getService(context, 0, intent, 0);
|
||||
manager.requestPermission(dev, pend_intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot request GameCube Adapter permission as EmulationActivity is null.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void Shutdown()
|
||||
{
|
||||
usb_con.close();
|
||||
}
|
||||
public static int GetFD() { return usb_con.getFileDescriptor(); }
|
||||
public static void Shutdown()
|
||||
{
|
||||
usb_con.close();
|
||||
}
|
||||
|
||||
public static boolean QueryAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
return true;
|
||||
else
|
||||
RequestPermission();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static int GetFD()
|
||||
{
|
||||
return usb_con.getFileDescriptor();
|
||||
}
|
||||
|
||||
public static void InitAdapter()
|
||||
{
|
||||
byte[] init = { 0x13 };
|
||||
usb_con.bulkTransfer(usb_in, init, init.length, 0);
|
||||
}
|
||||
public static boolean QueryAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
return true;
|
||||
else
|
||||
RequestPermission();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int Input() {
|
||||
return usb_con.bulkTransfer(usb_in, controller_payload, controller_payload.length, 16);
|
||||
}
|
||||
public static void InitAdapter()
|
||||
{
|
||||
byte[] init = {0x13};
|
||||
usb_con.bulkTransfer(usb_in, init, init.length, 0);
|
||||
}
|
||||
|
||||
public static int Output(byte[] rumble) {
|
||||
return usb_con.bulkTransfer(usb_out, rumble, 5, 16);
|
||||
}
|
||||
public static int Input()
|
||||
{
|
||||
return usb_con.bulkTransfer(usb_in, controller_payload, controller_payload.length, 16);
|
||||
}
|
||||
|
||||
public static boolean OpenAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
{
|
||||
usb_con = manager.openDevice(dev);
|
||||
public static int Output(byte[] rumble)
|
||||
{
|
||||
return usb_con.bulkTransfer(usb_out, rumble, 5, 16);
|
||||
}
|
||||
|
||||
Log.info("GCAdapter: Number of configurations: " + dev.getConfigurationCount());
|
||||
Log.info("GCAdapter: Number of interfaces: " + dev.getInterfaceCount());
|
||||
public static boolean OpenAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == 0x0337 && dev.getVendorId() == 0x057e)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
{
|
||||
usb_con = manager.openDevice(dev);
|
||||
|
||||
if (dev.getConfigurationCount() > 0 && dev.getInterfaceCount() > 0)
|
||||
{
|
||||
UsbConfiguration conf = dev.getConfiguration(0);
|
||||
usb_intf = conf.getInterface(0);
|
||||
usb_con.claimInterface(usb_intf, true);
|
||||
Log.info("GCAdapter: Number of configurations: " + dev.getConfigurationCount());
|
||||
Log.info("GCAdapter: Number of interfaces: " + dev.getInterfaceCount());
|
||||
|
||||
Log.info("GCAdapter: Number of endpoints: " + usb_intf.getEndpointCount());
|
||||
if (dev.getConfigurationCount() > 0 && dev.getInterfaceCount() > 0)
|
||||
{
|
||||
UsbConfiguration conf = dev.getConfiguration(0);
|
||||
usb_intf = conf.getInterface(0);
|
||||
usb_con.claimInterface(usb_intf, true);
|
||||
|
||||
if (usb_intf.getEndpointCount() == 2)
|
||||
{
|
||||
for (int i = 0; i < usb_intf.getEndpointCount(); ++i)
|
||||
if (usb_intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
|
||||
usb_in = usb_intf.getEndpoint(i);
|
||||
else
|
||||
usb_out = usb_intf.getEndpoint(i);
|
||||
Log.info("GCAdapter: Number of endpoints: " + usb_intf.getEndpointCount());
|
||||
|
||||
InitAdapter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_con.releaseInterface(usb_intf);
|
||||
}
|
||||
}
|
||||
if (usb_intf.getEndpointCount() == 2)
|
||||
{
|
||||
for (int i = 0; i < usb_intf.getEndpointCount(); ++i)
|
||||
if (usb_intf.getEndpoint(i).getDirection() == UsbConstants.USB_DIR_IN)
|
||||
usb_in = usb_intf.getEndpoint(i);
|
||||
else
|
||||
usb_out = usb_intf.getEndpoint(i);
|
||||
|
||||
final Activity emulationActivity = NativeLibrary.sEmulationActivity.get();
|
||||
if (emulationActivity != null)
|
||||
{
|
||||
emulationActivity.runOnUiThread(() -> Toast.makeText(emulationActivity, "GameCube Adapter couldn't be opened. Please re-plug the device.", Toast.LENGTH_LONG).show());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot show toast for GameCube Adapter failure.");
|
||||
}
|
||||
usb_con.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
InitAdapter();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
usb_con.releaseInterface(usb_intf);
|
||||
}
|
||||
}
|
||||
|
||||
final Activity emulationActivity = NativeLibrary.sEmulationActivity.get();
|
||||
if (emulationActivity != null)
|
||||
{
|
||||
emulationActivity.runOnUiThread(() -> Toast.makeText(emulationActivity,
|
||||
"GameCube Adapter couldn't be opened. Please re-plug the device.",
|
||||
Toast.LENGTH_LONG).show());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot show toast for GameCube Adapter failure.");
|
||||
}
|
||||
usb_con.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,145 +19,148 @@ import java.util.Map;
|
|||
|
||||
public class Java_WiimoteAdapter
|
||||
{
|
||||
final static int MAX_PAYLOAD = 23;
|
||||
final static int MAX_WIIMOTES = 4;
|
||||
final static int TIMEOUT = 200;
|
||||
final static short NINTENDO_VENDOR_ID = 0x057e;
|
||||
final static short NINTENDO_WIIMOTE_PRODUCT_ID = 0x0306;
|
||||
public static UsbManager manager;
|
||||
final static int MAX_PAYLOAD = 23;
|
||||
final static int MAX_WIIMOTES = 4;
|
||||
final static int TIMEOUT = 200;
|
||||
final static short NINTENDO_VENDOR_ID = 0x057e;
|
||||
final static short NINTENDO_WIIMOTE_PRODUCT_ID = 0x0306;
|
||||
public static UsbManager manager;
|
||||
|
||||
static UsbDeviceConnection usb_con;
|
||||
static UsbInterface[] usb_intf = new UsbInterface[MAX_WIIMOTES];
|
||||
static UsbEndpoint[] usb_in = new UsbEndpoint[MAX_WIIMOTES];
|
||||
static UsbDeviceConnection usb_con;
|
||||
static UsbInterface[] usb_intf = new UsbInterface[MAX_WIIMOTES];
|
||||
static UsbEndpoint[] usb_in = new UsbEndpoint[MAX_WIIMOTES];
|
||||
|
||||
public static byte[][] wiimote_payload = new byte[MAX_WIIMOTES][MAX_PAYLOAD];
|
||||
public static byte[][] wiimote_payload = new byte[MAX_WIIMOTES][MAX_PAYLOAD];
|
||||
|
||||
private static void RequestPermission()
|
||||
{
|
||||
Context context = NativeLibrary.sEmulationActivity.get();
|
||||
if (context != null)
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (!manager.hasPermission(dev))
|
||||
{
|
||||
Log.warning("Requesting permission for Wii Remote adapter");
|
||||
Intent intent = new Intent();
|
||||
PendingIntent pend_intent;
|
||||
intent.setClass(context, USBPermService.class);
|
||||
pend_intent = PendingIntent.getService(context, 0, intent, 0);
|
||||
manager.requestPermission(dev, pend_intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot request Wiimote adapter permission as EmulationActivity is null.");
|
||||
}
|
||||
}
|
||||
private static void RequestPermission()
|
||||
{
|
||||
Context context = NativeLibrary.sEmulationActivity.get();
|
||||
if (context != null)
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID &&
|
||||
dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (!manager.hasPermission(dev))
|
||||
{
|
||||
Log.warning("Requesting permission for Wii Remote adapter");
|
||||
Intent intent = new Intent();
|
||||
PendingIntent pend_intent;
|
||||
intent.setClass(context, USBPermService.class);
|
||||
pend_intent = PendingIntent.getService(context, 0, intent, 0);
|
||||
manager.requestPermission(dev, pend_intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warning("Cannot request Wiimote adapter permission as EmulationActivity is null.");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean QueryAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
return true;
|
||||
else
|
||||
RequestPermission();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static boolean QueryAdapter()
|
||||
{
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID &&
|
||||
dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
return true;
|
||||
else
|
||||
RequestPermission();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int Input(int index)
|
||||
{
|
||||
return usb_con.bulkTransfer(usb_in[index], wiimote_payload[index], MAX_PAYLOAD, TIMEOUT);
|
||||
}
|
||||
public static int Input(int index)
|
||||
{
|
||||
return usb_con.bulkTransfer(usb_in[index], wiimote_payload[index], MAX_PAYLOAD, TIMEOUT);
|
||||
}
|
||||
|
||||
public static int Output(int index, byte[] buf, int size)
|
||||
{
|
||||
byte report_number = buf[0];
|
||||
public static int Output(int index, byte[] buf, int size)
|
||||
{
|
||||
byte report_number = buf[0];
|
||||
|
||||
// Remove the report number from the buffer
|
||||
buf = Arrays.copyOfRange(buf, 1, buf.length);
|
||||
size--;
|
||||
// Remove the report number from the buffer
|
||||
buf = Arrays.copyOfRange(buf, 1, buf.length);
|
||||
size--;
|
||||
|
||||
final int LIBUSB_REQUEST_TYPE_CLASS = (1 << 5);
|
||||
final int LIBUSB_RECIPIENT_INTERFACE = 0x1;
|
||||
final int LIBUSB_ENDPOINT_OUT = 0;
|
||||
final int LIBUSB_REQUEST_TYPE_CLASS = (1 << 5);
|
||||
final int LIBUSB_RECIPIENT_INTERFACE = 0x1;
|
||||
final int LIBUSB_ENDPOINT_OUT = 0;
|
||||
|
||||
final int HID_SET_REPORT = 0x9;
|
||||
final int HID_OUTPUT = (2 << 8);
|
||||
final int HID_SET_REPORT = 0x9;
|
||||
final int HID_OUTPUT = (2 << 8);
|
||||
|
||||
int write = usb_con.controlTransfer(
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||
HID_SET_REPORT,
|
||||
HID_OUTPUT | report_number,
|
||||
index,
|
||||
buf, size,
|
||||
1000);
|
||||
int write = usb_con.controlTransfer(
|
||||
LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
|
||||
HID_SET_REPORT,
|
||||
HID_OUTPUT | report_number,
|
||||
index,
|
||||
buf, size,
|
||||
1000);
|
||||
|
||||
if (write < 0)
|
||||
return 0;
|
||||
if (write < 0)
|
||||
return 0;
|
||||
|
||||
return write + 1;
|
||||
}
|
||||
return write + 1;
|
||||
}
|
||||
|
||||
public static boolean OpenAdapter()
|
||||
{
|
||||
// If the adapter is already open. Don't attempt to do it again
|
||||
if (usb_con != null && usb_con.getFileDescriptor() != -1)
|
||||
return true;
|
||||
public static boolean OpenAdapter()
|
||||
{
|
||||
// If the adapter is already open. Don't attempt to do it again
|
||||
if (usb_con != null && usb_con.getFileDescriptor() != -1)
|
||||
return true;
|
||||
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID && dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
{
|
||||
usb_con = manager.openDevice(dev);
|
||||
UsbConfiguration conf = dev.getConfiguration(0);
|
||||
HashMap<String, UsbDevice> devices = manager.getDeviceList();
|
||||
for (Map.Entry<String, UsbDevice> pair : devices.entrySet())
|
||||
{
|
||||
UsbDevice dev = pair.getValue();
|
||||
if (dev.getProductId() == NINTENDO_WIIMOTE_PRODUCT_ID &&
|
||||
dev.getVendorId() == NINTENDO_VENDOR_ID)
|
||||
{
|
||||
if (manager.hasPermission(dev))
|
||||
{
|
||||
usb_con = manager.openDevice(dev);
|
||||
UsbConfiguration conf = dev.getConfiguration(0);
|
||||
|
||||
Log.info("Number of configurations: " + dev.getConfigurationCount());
|
||||
Log.info("Number of Interfaces: " + dev.getInterfaceCount());
|
||||
Log.info("Number of Interfaces from conf: " + conf.getInterfaceCount());
|
||||
Log.info("Number of configurations: " + dev.getConfigurationCount());
|
||||
Log.info("Number of Interfaces: " + dev.getInterfaceCount());
|
||||
Log.info("Number of Interfaces from conf: " + conf.getInterfaceCount());
|
||||
|
||||
// Sometimes the interface count is returned as zero.
|
||||
// Means the device needs to be unplugged and plugged back in again
|
||||
if (dev.getInterfaceCount() > 0)
|
||||
{
|
||||
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
{
|
||||
// One interface per Wii Remote
|
||||
usb_intf[i] = dev.getInterface(i);
|
||||
usb_con.claimInterface(usb_intf[i], true);
|
||||
// Sometimes the interface count is returned as zero.
|
||||
// Means the device needs to be unplugged and plugged back in again
|
||||
if (dev.getInterfaceCount() > 0)
|
||||
{
|
||||
for (int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
{
|
||||
// One interface per Wii Remote
|
||||
usb_intf[i] = dev.getInterface(i);
|
||||
usb_con.claimInterface(usb_intf[i], true);
|
||||
|
||||
// One endpoint per Wii Remote. Input only
|
||||
// Output reports go through the control channel.
|
||||
usb_in[i] = usb_intf[i].getEndpoint(0);
|
||||
Log.info("Interface " + i + " endpoint count:" + usb_intf[i].getEndpointCount());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: Message that the device was found, but it needs to be unplugged and plugged back in?
|
||||
usb_con.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// One endpoint per Wii Remote. Input only
|
||||
// Output reports go through the control channel.
|
||||
usb_in[i] = usb_intf[i].getEndpoint(0);
|
||||
Log.info("Interface " + i + " endpoint count:" + usb_intf[i].getEndpointCount());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// XXX: Message that the device was found, but it needs to be unplugged and plugged back in?
|
||||
usb_con.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,45 +9,45 @@ import org.dolphinemu.dolphinemu.BuildConfig;
|
|||
*/
|
||||
public final class Log
|
||||
{
|
||||
private static final String TAG = "Dolphin";
|
||||
private static final String TAG = "Dolphin";
|
||||
|
||||
private Log()
|
||||
{
|
||||
}
|
||||
private Log()
|
||||
{
|
||||
}
|
||||
|
||||
public static void verbose(String message)
|
||||
{
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
android.util.Log.v(TAG, message);
|
||||
}
|
||||
}
|
||||
public static void verbose(String message)
|
||||
{
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
android.util.Log.v(TAG, message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void debug(String message)
|
||||
{
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
android.util.Log.d(TAG, message);
|
||||
}
|
||||
}
|
||||
public static void debug(String message)
|
||||
{
|
||||
if (BuildConfig.DEBUG)
|
||||
{
|
||||
android.util.Log.d(TAG, message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void info(String message)
|
||||
{
|
||||
android.util.Log.i(TAG, message);
|
||||
}
|
||||
public static void info(String message)
|
||||
{
|
||||
android.util.Log.i(TAG, message);
|
||||
}
|
||||
|
||||
public static void warning(String message)
|
||||
{
|
||||
android.util.Log.w(TAG, message);
|
||||
}
|
||||
public static void warning(String message)
|
||||
{
|
||||
android.util.Log.w(TAG, message);
|
||||
}
|
||||
|
||||
public static void error(String message)
|
||||
{
|
||||
android.util.Log.e(TAG, message);
|
||||
}
|
||||
public static void error(String message)
|
||||
{
|
||||
android.util.Log.e(TAG, message);
|
||||
}
|
||||
|
||||
public static void wtf(String message)
|
||||
{
|
||||
android.util.Log.wtf(TAG, message);
|
||||
}
|
||||
public static void wtf(String message)
|
||||
{
|
||||
android.util.Log.wtf(TAG, message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,49 +14,59 @@ import org.dolphinemu.dolphinemu.R;
|
|||
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
|
||||
public class PermissionsHandler {
|
||||
public static final int REQUEST_CODE_WRITE_PERMISSION = 500;
|
||||
public class PermissionsHandler
|
||||
{
|
||||
public static final int REQUEST_CODE_WRITE_PERMISSION = 500;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public static boolean checkWritePermission(final FragmentActivity activity) {
|
||||
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
||||
return true;
|
||||
}
|
||||
@TargetApi(Build.VERSION_CODES.M)
|
||||
public static boolean checkWritePermission(final FragmentActivity activity)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE);
|
||||
|
||||
if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
|
||||
if (activity.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE)) {
|
||||
showMessageOKCancel(activity, activity.getString(R.string.write_permission_needed),
|
||||
(dialog, which) -> activity.requestPermissions(new String[] {WRITE_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_WRITE_PERMISSION));
|
||||
return false;
|
||||
}
|
||||
if (hasWritePermission != PackageManager.PERMISSION_GRANTED)
|
||||
{
|
||||
if (activity.shouldShowRequestPermissionRationale(WRITE_EXTERNAL_STORAGE))
|
||||
{
|
||||
showMessageOKCancel(activity, activity.getString(R.string.write_permission_needed),
|
||||
(dialog, which) -> activity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_WRITE_PERMISSION));
|
||||
return false;
|
||||
}
|
||||
|
||||
activity.requestPermissions(new String[] {WRITE_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_WRITE_PERMISSION);
|
||||
return false;
|
||||
}
|
||||
activity.requestPermissions(new String[]{WRITE_EXTERNAL_STORAGE},
|
||||
REQUEST_CODE_WRITE_PERMISSION);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean hasWriteAccess(Context context) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE);
|
||||
return hasWritePermission == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
public static boolean hasWriteAccess(Context context)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
{
|
||||
int hasWritePermission = ContextCompat.checkSelfPermission(context, WRITE_EXTERNAL_STORAGE);
|
||||
return hasWritePermission == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void showMessageOKCancel(final FragmentActivity activity, String message, DialogInterface.OnClickListener okListener) {
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.setNegativeButton(android.R.string.cancel, (dialogInterface, i) ->
|
||||
Toast.makeText(activity, R.string.write_permission_needed, Toast.LENGTH_SHORT).show())
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
private static void showMessageOKCancel(final FragmentActivity activity, String message,
|
||||
DialogInterface.OnClickListener okListener)
|
||||
{
|
||||
new AlertDialog.Builder(activity)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok, okListener)
|
||||
.setNegativeButton(android.R.string.cancel, (dialogInterface, i) ->
|
||||
Toast.makeText(activity, R.string.write_permission_needed, Toast.LENGTH_SHORT)
|
||||
.show())
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,98 +12,105 @@ import org.dolphinemu.dolphinemu.model.GameFile;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
public class PicassoUtils {
|
||||
public static void loadGameBanner(ImageView imageView, GameFile gameFile)
|
||||
{
|
||||
File cover = new File(gameFile.getCustomCoverPath());
|
||||
if (cover.exists())
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(cover)
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView);
|
||||
}
|
||||
else if ((cover = new File(gameFile.getCoverPath())).exists())
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(cover)
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView);
|
||||
}
|
||||
/**
|
||||
* GameTDB has a pretty close to complete collection for US/EN covers. First pass at getting
|
||||
* the cover will be by the disk's region, second will be the US cover, and third EN.
|
||||
*/
|
||||
else
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, CoverHelper.getRegion(gameFile)))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(((BitmapDrawable) imageView.getDrawable()).getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
@Override
|
||||
public void onError() // Second pass using US region
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, "US"))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(((BitmapDrawable) imageView.getDrawable()).getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
@Override
|
||||
public void onError() // Third and last pass using EN region
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, "EN"))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(((BitmapDrawable) imageView.getDrawable()).getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
@Override
|
||||
public void onError()
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
public class PicassoUtils
|
||||
{
|
||||
public static void loadGameBanner(ImageView imageView, GameFile gameFile)
|
||||
{
|
||||
File cover = new File(gameFile.getCustomCoverPath());
|
||||
if (cover.exists())
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(cover)
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView);
|
||||
}
|
||||
else if ((cover = new File(gameFile.getCoverPath())).exists())
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(cover)
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView);
|
||||
}
|
||||
/**
|
||||
* GameTDB has a pretty close to complete collection for US/EN covers. First pass at getting
|
||||
* the cover will be by the disk's region, second will be the US cover, and third EN.
|
||||
*/
|
||||
else
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, CoverHelper.getRegion(gameFile)))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(((BitmapDrawable) imageView.getDrawable()).getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError() // Second pass using US region
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, "US"))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(
|
||||
((BitmapDrawable) imageView.getDrawable()).getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError() // Third and last pass using EN region
|
||||
{
|
||||
Picasso.with(imageView.getContext())
|
||||
.load(CoverHelper.buildGameTDBUrl(gameFile, "EN"))
|
||||
.fit()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.config(Bitmap.Config.ARGB_8888)
|
||||
.error(R.drawable.no_banner)
|
||||
.into(imageView, new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onSuccess()
|
||||
{
|
||||
CoverHelper.saveCover(
|
||||
((BitmapDrawable) imageView.getDrawable())
|
||||
.getBitmap(),
|
||||
gameFile.getCoverPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError()
|
||||
{
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,61 +14,61 @@ import java.util.Date;
|
|||
|
||||
public final class StartupHandler
|
||||
{
|
||||
public static final String NEW_SESSION = "NEW_SESSION";
|
||||
public static final String LAST_CLOSED = "LAST_CLOSED";
|
||||
public static final Long SESSION_TIMEOUT = 21600000L; // 6 hours in milliseconds
|
||||
public static final String NEW_SESSION = "NEW_SESSION";
|
||||
public static final String LAST_CLOSED = "LAST_CLOSED";
|
||||
public static final Long SESSION_TIMEOUT = 21600000L; // 6 hours in milliseconds
|
||||
|
||||
public static void HandleInit(FragmentActivity parent)
|
||||
{
|
||||
// Ask the user to grant write permission if it's not already granted
|
||||
PermissionsHandler.checkWritePermission(parent);
|
||||
public static void HandleInit(FragmentActivity parent)
|
||||
{
|
||||
// Ask the user to grant write permission if it's not already granted
|
||||
PermissionsHandler.checkWritePermission(parent);
|
||||
|
||||
// Ask the user if he wants to enable analytics if we haven't yet.
|
||||
Analytics.checkAnalyticsInit(parent);
|
||||
// Ask the user if he wants to enable analytics if we haven't yet.
|
||||
Analytics.checkAnalyticsInit(parent);
|
||||
|
||||
String start_file = "";
|
||||
Bundle extras = parent.getIntent().getExtras();
|
||||
if (extras != null)
|
||||
{
|
||||
start_file = extras.getString("AutoStartFile");
|
||||
}
|
||||
String start_file = "";
|
||||
Bundle extras = parent.getIntent().getExtras();
|
||||
if (extras != null)
|
||||
{
|
||||
start_file = extras.getString("AutoStartFile");
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(start_file))
|
||||
{
|
||||
// Start the emulation activity, send the ISO passed in and finish the main activity
|
||||
Intent emulation_intent = new Intent(parent, EmulationActivity.class);
|
||||
emulation_intent.putExtra("SelectedGame", start_file);
|
||||
parent.startActivity(emulation_intent);
|
||||
parent.finish();
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(start_file))
|
||||
{
|
||||
// Start the emulation activity, send the ISO passed in and finish the main activity
|
||||
Intent emulation_intent = new Intent(parent, EmulationActivity.class);
|
||||
emulation_intent.putExtra("SelectedGame", start_file);
|
||||
parent.startActivity(emulation_intent);
|
||||
parent.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* There isn't a good way to determine a new session. setSessionTime is called if the main
|
||||
* activity goes into the background.
|
||||
*/
|
||||
public static void setSessionTime(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putLong(LAST_CLOSED, new Date(System.currentTimeMillis()).getTime());
|
||||
sPrefsEditor.apply();
|
||||
}
|
||||
/**
|
||||
* There isn't a good way to determine a new session. setSessionTime is called if the main
|
||||
* activity goes into the background.
|
||||
*/
|
||||
public static void setSessionTime(Context context)
|
||||
{
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putLong(LAST_CLOSED, new Date(System.currentTimeMillis()).getTime());
|
||||
sPrefsEditor.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if we treat this activity start as a new session.
|
||||
*/
|
||||
public static void checkSessionReset(Context context)
|
||||
{
|
||||
Long currentTime = new Date(System.currentTimeMillis()).getTime();
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Long lastOpen = preferences.getLong(LAST_CLOSED, 0);
|
||||
if (currentTime > (lastOpen + SESSION_TIMEOUT))
|
||||
{
|
||||
// Passed at emulation start to trigger first open event.
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(NEW_SESSION, true);
|
||||
sPrefsEditor.apply();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called to determine if we treat this activity start as a new session.
|
||||
*/
|
||||
public static void checkSessionReset(Context context)
|
||||
{
|
||||
Long currentTime = new Date(System.currentTimeMillis()).getTime();
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
Long lastOpen = preferences.getLong(LAST_CLOSED, 0);
|
||||
if (currentTime > (lastOpen + SESSION_TIMEOUT))
|
||||
{
|
||||
// Passed at emulation start to trigger first open event.
|
||||
SharedPreferences.Editor sPrefsEditor = preferences.edit();
|
||||
sPrefsEditor.putBoolean(NEW_SESSION, true);
|
||||
sPrefsEditor.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.graphics.drawable.VectorDrawable;
|
|||
import android.media.tv.TvContract;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.PersistableBundle;
|
||||
import android.support.annotation.AnyRes;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -25,7 +24,6 @@ import android.support.media.tv.Channel;
|
|||
import android.support.media.tv.TvContractCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.model.GameFile;
|
||||
import org.dolphinemu.dolphinemu.model.HomeScreenChannel;
|
||||
import org.dolphinemu.dolphinemu.services.SyncChannelJobService;
|
||||
|
@ -33,7 +31,6 @@ import org.dolphinemu.dolphinemu.services.SyncProgramsJobService;
|
|||
import org.dolphinemu.dolphinemu.ui.platform.Platform;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -45,232 +42,234 @@ import static android.support.v4.content.FileProvider.getUriForFile;
|
|||
*/
|
||||
public class TvUtil
|
||||
{
|
||||
private static final String TAG = "TvUtil";
|
||||
private static final long CHANNEL_JOB_ID_OFFSET = 1000;
|
||||
private static final String TAG = "TvUtil";
|
||||
private static final long CHANNEL_JOB_ID_OFFSET = 1000;
|
||||
|
||||
private static final String[] CHANNELS_PROJECTION = {
|
||||
TvContractCompat.Channels._ID,
|
||||
TvContract.Channels.COLUMN_DISPLAY_NAME,
|
||||
TvContractCompat.Channels.COLUMN_BROWSABLE
|
||||
};
|
||||
private static final String LEANBACK_PACKAGE = "com.google.android.tvlauncher";
|
||||
private static final String[] CHANNELS_PROJECTION = {
|
||||
TvContractCompat.Channels._ID,
|
||||
TvContract.Channels.COLUMN_DISPLAY_NAME,
|
||||
TvContractCompat.Channels.COLUMN_BROWSABLE
|
||||
};
|
||||
private static final String LEANBACK_PACKAGE = "com.google.android.tvlauncher";
|
||||
|
||||
public static int getNumberOfChannels(Context context)
|
||||
{
|
||||
Cursor cursor =
|
||||
context.getContentResolver()
|
||||
.query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
CHANNELS_PROJECTION,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
return cursor != null ? cursor.getCount() : 0;
|
||||
}
|
||||
public static int getNumberOfChannels(Context context)
|
||||
{
|
||||
Cursor cursor =
|
||||
context.getContentResolver()
|
||||
.query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
CHANNELS_PROJECTION,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
return cursor != null ? cursor.getCount() : 0;
|
||||
}
|
||||
|
||||
public static List<Channel> getAllChannels(Context context)
|
||||
{
|
||||
List<Channel> channels = new ArrayList<>();
|
||||
Cursor cursor =
|
||||
context.getContentResolver()
|
||||
.query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
CHANNELS_PROJECTION,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
channels.add(Channel.fromCursor(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
public static List<Channel> getAllChannels(Context context)
|
||||
{
|
||||
List<Channel> channels = new ArrayList<>();
|
||||
Cursor cursor =
|
||||
context.getContentResolver()
|
||||
.query(
|
||||
TvContractCompat.Channels.CONTENT_URI,
|
||||
CHANNELS_PROJECTION,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
if (cursor != null && cursor.moveToFirst())
|
||||
{
|
||||
do
|
||||
{
|
||||
channels.add(Channel.fromCursor(cursor));
|
||||
}
|
||||
while (cursor.moveToNext());
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
public static Channel getChannelById(Context context, long channelId)
|
||||
{
|
||||
for (Channel channel : getAllChannels(context))
|
||||
{
|
||||
if (channel.getId() == channelId)
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static Channel getChannelById(Context context, long channelId)
|
||||
{
|
||||
for (Channel channel : getAllChannels(context))
|
||||
{
|
||||
if (channel.getId() == channelId)
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all Leanback homescreen channels
|
||||
*/
|
||||
public static void updateAllChannels(Context context)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < 26)
|
||||
return;
|
||||
for (Channel channel : getAllChannels(context))
|
||||
{
|
||||
context.getContentResolver()
|
||||
.update(
|
||||
TvContractCompat.buildChannelUri(channel.getId()),
|
||||
channel.toContentValues(),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Updates all Leanback homescreen channels
|
||||
*/
|
||||
public static void updateAllChannels(Context context)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < 26)
|
||||
return;
|
||||
for (Channel channel : getAllChannels(context))
|
||||
{
|
||||
context.getContentResolver()
|
||||
.update(
|
||||
TvContractCompat.buildChannelUri(channel.getId()),
|
||||
channel.toContentValues(),
|
||||
null,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
public static Uri getUriToResource(Context context, @AnyRes int resId)
|
||||
throws Resources.NotFoundException
|
||||
{
|
||||
Resources res = context.getResources();
|
||||
Uri resUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
|
||||
"://" + res.getResourcePackageName(resId)
|
||||
+ '/' + res.getResourceTypeName(resId)
|
||||
+ '/' + res.getResourceEntryName(resId));
|
||||
return resUri;
|
||||
}
|
||||
public static Uri getUriToResource(Context context, @AnyRes int resId)
|
||||
throws Resources.NotFoundException
|
||||
{
|
||||
Resources res = context.getResources();
|
||||
Uri resUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
|
||||
"://" + res.getResourcePackageName(resId)
|
||||
+ '/' + res.getResourceTypeName(resId)
|
||||
+ '/' + res.getResourceEntryName(resId));
|
||||
return resUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a resource into a {@link Bitmap}. If the resource is a vector drawable, it will be
|
||||
* drawn into a new Bitmap. Otherwise the {@link BitmapFactory} will decode the resource.
|
||||
*/
|
||||
@NonNull
|
||||
public static Bitmap convertToBitmap(Context context, int resourceId)
|
||||
{
|
||||
Drawable drawable = context.getDrawable(resourceId);
|
||||
if (drawable instanceof VectorDrawable)
|
||||
{
|
||||
Bitmap bitmap =
|
||||
Bitmap.createBitmap(
|
||||
drawable.getIntrinsicWidth(),
|
||||
drawable.getIntrinsicHeight(),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
return BitmapFactory.decodeResource(context.getResources(), resourceId);
|
||||
}
|
||||
/**
|
||||
* Converts a resource into a {@link Bitmap}. If the resource is a vector drawable, it will be
|
||||
* drawn into a new Bitmap. Otherwise the {@link BitmapFactory} will decode the resource.
|
||||
*/
|
||||
@NonNull
|
||||
public static Bitmap convertToBitmap(Context context, int resourceId)
|
||||
{
|
||||
Drawable drawable = context.getDrawable(resourceId);
|
||||
if (drawable instanceof VectorDrawable)
|
||||
{
|
||||
Bitmap bitmap =
|
||||
Bitmap.createBitmap(
|
||||
drawable.getIntrinsicWidth(),
|
||||
drawable.getIntrinsicHeight(),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
|
||||
drawable.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
return BitmapFactory.decodeResource(context.getResources(), resourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leanback lanucher requires a uri for poster art so we create a contentUri and
|
||||
* pass that to LEANBACK_PACKAGE
|
||||
*/
|
||||
public static Uri buildBanner(GameFile game, Context context)
|
||||
{
|
||||
Uri contentUri = null;
|
||||
/**
|
||||
* Leanback lanucher requires a uri for poster art so we create a contentUri and
|
||||
* pass that to LEANBACK_PACKAGE
|
||||
*/
|
||||
public static Uri buildBanner(GameFile game, Context context)
|
||||
{
|
||||
Uri contentUri = null;
|
||||
|
||||
try
|
||||
{
|
||||
File cover = new File(game.getCustomCoverPath());
|
||||
if(cover.exists())
|
||||
{
|
||||
contentUri = getUriForFile(context, getFileProvider(context), cover);
|
||||
}
|
||||
else if ((cover = new File(game.getCoverPath())).exists())
|
||||
{
|
||||
contentUri = getUriForFile(context, getFileProvider(context), cover);
|
||||
}
|
||||
context.grantUriPermission(LEANBACK_PACKAGE, contentUri,
|
||||
FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(TAG, "Failed to create banner");
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
try
|
||||
{
|
||||
File cover = new File(game.getCustomCoverPath());
|
||||
if (cover.exists())
|
||||
{
|
||||
contentUri = getUriForFile(context, getFileProvider(context), cover);
|
||||
}
|
||||
else if ((cover = new File(game.getCoverPath())).exists())
|
||||
{
|
||||
contentUri = getUriForFile(context, getFileProvider(context), cover);
|
||||
}
|
||||
context.grantUriPermission(LEANBACK_PACKAGE, contentUri,
|
||||
FLAG_GRANT_READ_URI_PERMISSION);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.e(TAG, "Failed to create banner");
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
|
||||
return contentUri;
|
||||
}
|
||||
return contentUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed since debug builds append '.debug' to the end of the package
|
||||
*/
|
||||
private static String getFileProvider(Context context)
|
||||
{
|
||||
return context.getPackageName() + ".filesprovider";
|
||||
}
|
||||
/**
|
||||
* Needed since debug builds append '.debug' to the end of the package
|
||||
*/
|
||||
private static String getFileProvider(Context context)
|
||||
{
|
||||
return context.getPackageName() + ".filesprovider";
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules syncing channels via a {@link JobScheduler}.
|
||||
*
|
||||
* @param context for accessing the {@link JobScheduler}.
|
||||
*/
|
||||
public static void scheduleSyncingChannel(Context context)
|
||||
{
|
||||
ComponentName componentName = new ComponentName(context, SyncChannelJobService.class);
|
||||
JobInfo.Builder builder = new JobInfo.Builder(1, componentName);
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
||||
/**
|
||||
* Schedules syncing channels via a {@link JobScheduler}.
|
||||
*
|
||||
* @param context for accessing the {@link JobScheduler}.
|
||||
*/
|
||||
public static void scheduleSyncingChannel(Context context)
|
||||
{
|
||||
ComponentName componentName = new ComponentName(context, SyncChannelJobService.class);
|
||||
JobInfo.Builder builder = new JobInfo.Builder(1, componentName);
|
||||
builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
||||
|
||||
JobScheduler scheduler =
|
||||
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
JobScheduler scheduler =
|
||||
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
|
||||
Log.d(TAG, "Scheduled channel creation.");
|
||||
scheduler.schedule(builder.build());
|
||||
}
|
||||
Log.d(TAG, "Scheduled channel creation.");
|
||||
scheduler.schedule(builder.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedulers syncing programs for a channel. The scheduler will listen to a {@link Uri} for a
|
||||
* particular channel.
|
||||
*
|
||||
* @param context for accessing the {@link JobScheduler}.
|
||||
* @param channelId for the channel to listen for changes.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public static void scheduleSyncingProgramsForChannel(Context context, long channelId)
|
||||
{
|
||||
Log.d(TAG, "ProgramsRefresh job");
|
||||
ComponentName componentName = new ComponentName(context, SyncProgramsJobService.class);
|
||||
JobInfo.Builder builder =
|
||||
new JobInfo.Builder(getJobIdForChannelId(channelId), componentName);
|
||||
JobInfo.TriggerContentUri triggerContentUri =
|
||||
new JobInfo.TriggerContentUri(
|
||||
TvContractCompat.buildChannelUri(channelId),
|
||||
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS);
|
||||
builder.addTriggerContentUri(triggerContentUri);
|
||||
builder.setTriggerContentMaxDelay(0L);
|
||||
builder.setTriggerContentUpdateDelay(0L);
|
||||
/**
|
||||
* Schedulers syncing programs for a channel. The scheduler will listen to a {@link Uri} for a
|
||||
* particular channel.
|
||||
*
|
||||
* @param context for accessing the {@link JobScheduler}.
|
||||
* @param channelId for the channel to listen for changes.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public static void scheduleSyncingProgramsForChannel(Context context, long channelId)
|
||||
{
|
||||
Log.d(TAG, "ProgramsRefresh job");
|
||||
ComponentName componentName = new ComponentName(context, SyncProgramsJobService.class);
|
||||
JobInfo.Builder builder =
|
||||
new JobInfo.Builder(getJobIdForChannelId(channelId), componentName);
|
||||
JobInfo.TriggerContentUri triggerContentUri =
|
||||
new JobInfo.TriggerContentUri(
|
||||
TvContractCompat.buildChannelUri(channelId),
|
||||
JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS);
|
||||
builder.addTriggerContentUri(triggerContentUri);
|
||||
builder.setTriggerContentMaxDelay(0L);
|
||||
builder.setTriggerContentUpdateDelay(0L);
|
||||
|
||||
PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putLong(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
|
||||
builder.setExtras(bundle);
|
||||
PersistableBundle bundle = new PersistableBundle();
|
||||
bundle.putLong(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
|
||||
builder.setExtras(bundle);
|
||||
|
||||
JobScheduler scheduler =
|
||||
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
scheduler.cancel(getJobIdForChannelId(channelId));
|
||||
scheduler.schedule(builder.build());
|
||||
}
|
||||
JobScheduler scheduler =
|
||||
(JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
|
||||
scheduler.cancel(getJobIdForChannelId(channelId));
|
||||
scheduler.schedule(builder.build());
|
||||
}
|
||||
|
||||
private static int getJobIdForChannelId(long channelId)
|
||||
{
|
||||
return (int) (CHANNEL_JOB_ID_OFFSET + channelId);
|
||||
}
|
||||
private static int getJobIdForChannelId(long channelId)
|
||||
{
|
||||
return (int) (CHANNEL_JOB_ID_OFFSET + channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates all subscriptions for homescreen channels.
|
||||
*/
|
||||
public static List<HomeScreenChannel> createUniversalSubscriptions()
|
||||
{
|
||||
//Leaving the subs local variable in case more channels are created other than platforms.
|
||||
List<HomeScreenChannel> subs = new ArrayList<>(createPlatformSubscriptions());
|
||||
return subs;
|
||||
}
|
||||
/**
|
||||
* Generates all subscriptions for homescreen channels.
|
||||
*/
|
||||
public static List<HomeScreenChannel> createUniversalSubscriptions()
|
||||
{
|
||||
//Leaving the subs local variable in case more channels are created other than platforms.
|
||||
List<HomeScreenChannel> subs = new ArrayList<>(createPlatformSubscriptions());
|
||||
return subs;
|
||||
}
|
||||
|
||||
private static List<HomeScreenChannel> createPlatformSubscriptions()
|
||||
{
|
||||
List<HomeScreenChannel> subs = new ArrayList<>();
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
subs.add(new HomeScreenChannel(
|
||||
platform.getHeaderName(),
|
||||
platform.getHeaderName(),
|
||||
AppLinkHelper.buildBrowseUri(platform.getHeaderName()).toString()));
|
||||
}
|
||||
return subs;
|
||||
}
|
||||
public static Boolean isLeanback(Context context)
|
||||
{
|
||||
return(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
|
||||
}
|
||||
private static List<HomeScreenChannel> createPlatformSubscriptions()
|
||||
{
|
||||
List<HomeScreenChannel> subs = new ArrayList<>();
|
||||
for (Platform platform : Platform.values())
|
||||
{
|
||||
subs.add(new HomeScreenChannel(
|
||||
platform.getHeaderName(),
|
||||
platform.getHeaderName(),
|
||||
AppLinkHelper.buildBrowseUri(platform.getHeaderName()).toString()));
|
||||
}
|
||||
return subs;
|
||||
}
|
||||
|
||||
public static Boolean isLeanback(Context context)
|
||||
{
|
||||
return (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,16 @@ import com.android.volley.toolbox.Volley;
|
|||
|
||||
public class VolleyUtil
|
||||
{
|
||||
private static RequestQueue queue;
|
||||
private static RequestQueue queue;
|
||||
|
||||
public static void init(Context context)
|
||||
{
|
||||
if (queue == null)
|
||||
queue = Volley.newRequestQueue(context);
|
||||
}
|
||||
public static void init(Context context)
|
||||
{
|
||||
if (queue == null)
|
||||
queue = Volley.newRequestQueue(context);
|
||||
}
|
||||
|
||||
public static RequestQueue getQueue()
|
||||
{
|
||||
return queue;
|
||||
}
|
||||
public static RequestQueue getQueue()
|
||||
{
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,18 +13,18 @@ import org.dolphinemu.dolphinemu.R;
|
|||
*/
|
||||
public class FileViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
public View itemView;
|
||||
public View itemView;
|
||||
|
||||
public TextView textFileName;
|
||||
public ImageView imageType;
|
||||
public TextView textFileName;
|
||||
public ImageView imageType;
|
||||
|
||||
public FileViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
public FileViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
this.itemView = itemView;
|
||||
this.itemView = itemView;
|
||||
|
||||
textFileName = (TextView) itemView.findViewById(R.id.text_file_name);
|
||||
imageType = (ImageView) itemView.findViewById(R.id.image_type);
|
||||
}
|
||||
textFileName = (TextView) itemView.findViewById(R.id.text_file_name);
|
||||
imageType = (ImageView) itemView.findViewById(R.id.image_type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,20 +14,20 @@ import org.dolphinemu.dolphinemu.model.GameFile;
|
|||
*/
|
||||
public class GameViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
public ImageView imageScreenshot;
|
||||
public TextView textGameTitle;
|
||||
public TextView textCompany;
|
||||
public ImageView imageScreenshot;
|
||||
public TextView textGameTitle;
|
||||
public TextView textCompany;
|
||||
|
||||
public GameFile gameFile;
|
||||
public GameFile gameFile;
|
||||
|
||||
public GameViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
public GameViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
itemView.setTag(this);
|
||||
itemView.setTag(this);
|
||||
|
||||
imageScreenshot = itemView.findViewById(R.id.image_game_screen);
|
||||
textGameTitle = itemView.findViewById(R.id.text_game_title);
|
||||
textCompany = itemView.findViewById(R.id.text_company);
|
||||
}
|
||||
imageScreenshot = itemView.findViewById(R.id.image_game_screen);
|
||||
textGameTitle = itemView.findViewById(R.id.text_game_title);
|
||||
textCompany = itemView.findViewById(R.id.text_company);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,19 +13,19 @@ import org.dolphinemu.dolphinemu.model.GameFile;
|
|||
*/
|
||||
public final class TvGameViewHolder extends Presenter.ViewHolder
|
||||
{
|
||||
public ImageCardView cardParent;
|
||||
public ImageCardView cardParent;
|
||||
|
||||
public ImageView imageScreenshot;
|
||||
public ImageView imageScreenshot;
|
||||
|
||||
public GameFile gameFile;
|
||||
public GameFile gameFile;
|
||||
|
||||
public TvGameViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
public TvGameViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
itemView.setTag(this);
|
||||
itemView.setTag(this);
|
||||
|
||||
cardParent = (ImageCardView) itemView;
|
||||
imageScreenshot = cardParent.getMainImageView();
|
||||
}
|
||||
cardParent = (ImageCardView) itemView;
|
||||
imageScreenshot = cardParent.getMainImageView();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@ import android.view.View;
|
|||
|
||||
public final class TvSettingsViewHolder extends Presenter.ViewHolder
|
||||
{
|
||||
public ImageCardView cardParent;
|
||||
public ImageCardView cardParent;
|
||||
|
||||
// Determines what action to take when this item is clicked.
|
||||
public int itemId;
|
||||
// Determines what action to take when this item is clicked.
|
||||
public int itemId;
|
||||
|
||||
public TvSettingsViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
public TvSettingsViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
itemView.setTag(this);
|
||||
itemView.setTag(this);
|
||||
|
||||
cardParent = (ImageCardView) itemView;
|
||||
}
|
||||
cardParent = (ImageCardView) itemView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
<!-- This animation is used ONLY when a submenu is replaced. -->
|
||||
<objectAnimator
|
||||
android:propertyName="translationX"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="-1280dp"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
android:propertyName="translationX"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="-1280dp"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
|
||||
<objectAnimator
|
||||
android:propertyName="alpha"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="0"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
android:propertyName="alpha"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="0"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
|
||||
</set>
|
|
@ -3,19 +3,19 @@
|
|||
|
||||
<!-- This animation is used ONLY when a submenu is replaced. -->
|
||||
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:propertyName="translationX"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1280dp"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
android:propertyName="translationX"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="0"
|
||||
android:valueTo="1280dp"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
|
||||
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:propertyName="alpha"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="0"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
android:propertyName="alpha"
|
||||
android:valueType="floatType"
|
||||
android:valueFrom="1"
|
||||
android:valueTo="0"
|
||||
android:interpolator="@android:interpolator/decelerate_quad"
|
||||
android:duration="200"/>
|
||||
|
||||
</set>
|
|
@ -2,7 +2,7 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_selected="true"
|
||||
android:drawable="@color/dolphin_accent_gamecube" />
|
||||
android:drawable="@color/dolphin_accent_gamecube"/>
|
||||
<item
|
||||
android:drawable="@color/tv_card_unselected" />
|
||||
android:drawable="@color/tv_card_unselected"/>
|
||||
</selector>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_selected="true"
|
||||
android:drawable="@color/dolphin_accent_wii" />
|
||||
android:drawable="@color/dolphin_accent_wii"/>
|
||||
<item
|
||||
android:drawable="@color/tv_card_unselected" />
|
||||
android:drawable="@color/tv_card_unselected"/>
|
||||
</selector>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_selected="true"
|
||||
android:drawable="@color/dolphin_accent_wiiware" />
|
||||
android:drawable="@color/dolphin_accent_wiiware"/>
|
||||
<item
|
||||
android:drawable="@color/tv_card_unselected" />
|
||||
android:drawable="@color/tv_card_unselected"/>
|
||||
</selector>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/surface_emulation"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:id="@+id/surface_emulation"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
/>
|
|
@ -1,11 +1,11 @@
|
|||
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/grid_state_slots"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="2"
|
||||
android:layout_gravity="center"
|
||||
android:background="#af000000">
|
||||
android:id="@+id/grid_state_slots"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="2"
|
||||
android:layout_gravity="center"
|
||||
android:background="#af000000">
|
||||
|
||||
<Button
|
||||
android:id="@+id/loadsave_state_button_1"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue