mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-14 18:57:07 -07:00
Add Rumble to Android
This commit is contained in:
parent
2906cfdd69
commit
3b85e147b6
11 changed files with 65 additions and 12 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
|
|
@ -133,6 +133,7 @@ typedef struct android_chiaki_session_t
|
|||
jmethodID java_session_event_connected_meth;
|
||||
jmethodID java_session_event_login_pin_request_meth;
|
||||
jmethodID java_session_event_quit_meth;
|
||||
jmethodID java_session_event_rumble_meth;
|
||||
jfieldID java_controller_state_buttons;
|
||||
jfieldID java_controller_state_l2_state;
|
||||
jfieldID java_controller_state_r2_state;
|
||||
|
@ -192,6 +193,14 @@ static void android_chiaki_event_cb(ChiakiEvent *event, void *user)
|
|||
free(reason_str);
|
||||
break;
|
||||
}
|
||||
case CHIAKI_EVENT_RUMBLE:
|
||||
E->CallVoidMethod(env, session->java_session,
|
||||
session->java_session_event_rumble_meth,
|
||||
(jint)event->rumble.left,
|
||||
(jint)event->rumble.right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
(*global_vm)->DetachCurrentThread(global_vm);
|
||||
|
@ -310,6 +319,7 @@ JNIEXPORT void JNICALL JNI_FCN(sessionCreate)(JNIEnv *env, jobject obj, jobject
|
|||
session->java_session_event_connected_meth = E->GetMethodID(env, session->java_session_class, "eventConnected", "()V");
|
||||
session->java_session_event_login_pin_request_meth = E->GetMethodID(env, session->java_session_class, "eventLoginPinRequest", "(Z)V");
|
||||
session->java_session_event_quit_meth = E->GetMethodID(env, session->java_session_class, "eventQuit", "(ILjava/lang/String;)V");
|
||||
session->java_session_event_rumble_meth = E->GetMethodID(env, session->java_session_class, "eventRumble", "(II)V");
|
||||
|
||||
jclass controller_state_class = E->FindClass(env, BASE_PACKAGE"/ControllerState");
|
||||
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
|
||||
|
|
|
@ -68,11 +68,16 @@ class Preferences(context: Context)
|
|||
get() = sharedPreferences.getBoolean(onScreenControlsEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(onScreenControlsEnabledKey, value).apply() }
|
||||
|
||||
val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_key)
|
||||
val touchpadOnlyEnabledKey get() = resources.getString(R.string.preferences_touchpad_only_enabled_key)
|
||||
var touchpadOnlyEnabled
|
||||
get() = sharedPreferences.getBoolean(touchpadOnlyEnabledKey, false)
|
||||
set(value) { sharedPreferences.edit().putBoolean(touchpadOnlyEnabledKey, value).apply() }
|
||||
|
||||
val rumbleEnabledKey get() = resources.getString(R.string.preferences_rumble_enabled_key)
|
||||
var rumbleEnabled
|
||||
get() = sharedPreferences.getBoolean(rumbleEnabledKey, true)
|
||||
set(value) { sharedPreferences.edit().putBoolean(rumbleEnabledKey, value).apply() }
|
||||
|
||||
val logVerboseKey get() = resources.getString(R.string.preferences_log_verbose_key)
|
||||
var logVerbose
|
||||
get() = sharedPreferences.getBoolean(logVerboseKey, false)
|
||||
|
|
|
@ -289,6 +289,7 @@ sealed class Event
|
|||
object ConnectedEvent: Event()
|
||||
data class LoginPinRequestEvent(val pinIncorrect: Boolean): Event()
|
||||
data class QuitEvent(val reason: QuitReason, val reasonString: String?): Event()
|
||||
data class RumbleEvent(val left: UByte, val right: UByte): Event()
|
||||
|
||||
class CreateError(val errorCode: ErrorCode): Exception("Failed to create a native object: $errorCode")
|
||||
|
||||
|
@ -344,6 +345,11 @@ class Session(connectInfo: ConnectInfo, logFile: String?, logVerbose: Boolean)
|
|||
event(QuitEvent(QuitReason(reasonValue), reasonString))
|
||||
}
|
||||
|
||||
private fun eventRumble(left: Int, right: Int)
|
||||
{
|
||||
event(RumbleEvent(left.toUByte(), right.toUByte()))
|
||||
}
|
||||
|
||||
fun setSurface(surface: Surface)
|
||||
{
|
||||
ChiakiNative.sessionSetSurface(nativePtr, surface)
|
||||
|
|
|
@ -25,6 +25,8 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
|
||||
private val _state = MutableLiveData<StreamState>(StreamStateIdle)
|
||||
val state: LiveData<StreamState> get() = _state
|
||||
private val _rumbleState = MutableLiveData<RumbleEvent>(RumbleEvent(0U, 0U))
|
||||
val rumbleState: LiveData<RumbleEvent> get() = _rumbleState
|
||||
|
||||
var surfaceTexture: SurfaceTexture? = null
|
||||
|
||||
|
@ -86,6 +88,7 @@ class StreamSession(val connectInfo: ConnectInfo, val logManager: LogManager, va
|
|||
event.pinIncorrect
|
||||
)
|
||||
)
|
||||
is RumbleEvent -> _rumbleState.postValue(event)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
|
|||
{
|
||||
preferences.logVerboseKey -> preferences.logVerbose
|
||||
preferences.swapCrossMoonKey -> preferences.swapCrossMoon
|
||||
preferences.rumbleEnabledKey -> preferences.rumbleEnabled
|
||||
else -> defValue
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ class DataStore(val preferences: Preferences): PreferenceDataStore()
|
|||
{
|
||||
preferences.logVerboseKey -> preferences.logVerbose = value
|
||||
preferences.swapCrossMoonKey -> preferences.swapCrossMoon = value
|
||||
preferences.rumbleEnabledKey -> preferences.rumbleEnabled = value
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ import android.content.res.Configuration
|
|||
import android.graphics.Matrix
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.TextureView
|
||||
|
@ -30,6 +32,7 @@ import com.metallic.chiaki.session.*
|
|||
import com.metallic.chiaki.touchcontrols.TouchpadOnlyFragment
|
||||
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
|
||||
import kotlinx.android.synthetic.main.activity_stream.*
|
||||
import kotlin.math.min
|
||||
|
||||
private sealed class DialogContents
|
||||
private object StreamQuitDialog: DialogContents()
|
||||
|
@ -105,6 +108,19 @@ class StreamActivity : AppCompatActivity(), View.OnSystemUiVisibilityChangeListe
|
|||
textureView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
|
||||
adjustTextureViewAspect()
|
||||
}
|
||||
|
||||
if(Preferences(this).rumbleEnabled)
|
||||
{
|
||||
val vibrator = getSystemService(VIBRATOR_SERVICE) as Vibrator
|
||||
viewModel.session.rumbleState.observe(this, Observer {
|
||||
val amplitude = min(255, (it.left.toInt() + it.right.toInt()) / 2)
|
||||
vibrator.cancel()
|
||||
if(amplitude == 0)
|
||||
return@Observer
|
||||
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
|
||||
vibrator.vibrate(VibrationEffect.createOneShot(1000, amplitude))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachFragment(fragment: Fragment)
|
||||
|
|
9
android/app/src/main/res/drawable/ic_rumble.xml
Normal file
9
android/app/src/main/res/drawable/ic_rumble.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?android:attr/textColorPrimary"
|
||||
android:pathData="M0,15h2L2,9L0,9v6zM3,17h2L5,7L3,7v10zM22,9v6h2L24,9h-2zM19,17h2L21,7h-2v10zM16.5,3h-9C6.67,3 6,3.67 6,4.5v15c0,0.83 0.67,1.5 1.5,1.5h9c0.83,0 1.5,-0.67 1.5,-1.5v-15c0,-0.83 -0.67,-1.5 -1.5,-1.5zM16,19L8,19L8,5h8v14z"/>
|
||||
</vector>
|
|
@ -88,6 +88,8 @@
|
|||
<string name="preferences_codec_title_h265">H265 (PS5 only)</string>
|
||||
<string name="preferences_swap_cross_moon_title">Swap Cross/Moon and Box/Pyramid Buttons</string>
|
||||
<string name="preferences_swap_cross_moon_summary">Swap face buttons if default mapping is incorrect (e.g. for 8BitDo controllers)</string>
|
||||
<string name="preferences_rumble_enabled_title">Rumble</string>
|
||||
<string name="preferences_rumble_enabled_summary">Use phone vibration motor for rumble</string>
|
||||
<string name="alert_message_delete_registered_host">Are you sure you want to delete the registered console %s with ID %s?</string>
|
||||
<string name="alert_message_delete_manual_host">Are you sure you want to delete the console entry for %s?</string>
|
||||
<string name="action_keep">Keep</string>
|
||||
|
@ -101,7 +103,8 @@
|
|||
<!-- Don't localize these -->
|
||||
<string name="preferences_discovery_enabled_key">discovery_enabled</string>
|
||||
<string name="preferences_on_screen_controls_enabled_key">on_screen_controls_enabled</string>
|
||||
<string name="preferences_touchpad_only_key">touchpad_only_enabled</string>
|
||||
<string name="preferences_touchpad_only_enabled_key">touchpad_only_enabled</string>
|
||||
<string name="preferences_rumble_enabled_key">rumble_enabled</string>
|
||||
<string name="preferences_log_verbose_key">log_verbose</string>
|
||||
<string name="preferences_import_settings_key">import_settings</string>
|
||||
<string name="preferences_export_settings_key">export_settings</string>
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
app:summary="@string/preferences_swap_cross_moon_summary"
|
||||
app:icon="@drawable/ic_gamepad" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_rumble_enabled_key"
|
||||
app:title="@string/preferences_rumble_enabled_title"
|
||||
app:summary="@string/preferences_rumble_enabled_summary"
|
||||
app:icon="@drawable/ic_rumble" />
|
||||
|
||||
<SwitchPreference
|
||||
app:key="@string/preferences_log_verbose_key"
|
||||
app:title="@string/preferences_log_verbose_title"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue