mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-20 21:43:12 -07:00
Send DPad Input to Session on Android
This commit is contained in:
parent
b007f93d16
commit
884333ed65
10 changed files with 152 additions and 56 deletions
|
@ -258,12 +258,12 @@ JNIEXPORT void JNICALL Java_com_metallic_chiaki_lib_ChiakiNative_sessionCreate(J
|
||||||
|
|
||||||
jclass controller_state_class = E->FindClass(env, "com/metallic/chiaki/lib/ControllerState");
|
jclass controller_state_class = E->FindClass(env, "com/metallic/chiaki/lib/ControllerState");
|
||||||
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
|
session->java_controller_state_buttons = E->GetFieldID(env, controller_state_class, "buttons", "I");
|
||||||
session->java_controller_state_l2_state = E->GetFieldID(env, controller_state_class, "l2_state", "B");
|
session->java_controller_state_l2_state = E->GetFieldID(env, controller_state_class, "l2State", "B");
|
||||||
session->java_controller_state_r2_state = E->GetFieldID(env, controller_state_class, "r2_state", "B");
|
session->java_controller_state_r2_state = E->GetFieldID(env, controller_state_class, "r2State", "B");
|
||||||
session->java_controller_state_left_x = E->GetFieldID(env, controller_state_class, "left_x", "S");
|
session->java_controller_state_left_x = E->GetFieldID(env, controller_state_class, "leftX", "S");
|
||||||
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "left_y", "S");
|
session->java_controller_state_left_y = E->GetFieldID(env, controller_state_class, "leftY", "S");
|
||||||
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "right_x", "S");
|
session->java_controller_state_right_x = E->GetFieldID(env, controller_state_class, "rightX", "S");
|
||||||
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "right_y", "S");
|
session->java_controller_state_right_y = E->GetFieldID(env, controller_state_class, "rightY", "S");
|
||||||
|
|
||||||
chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session);
|
chiaki_session_set_event_cb(&session->session, android_chiaki_event_cb, session);
|
||||||
chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder);
|
chiaki_session_set_video_sample_cb(&session->session, android_chiaki_video_decoder_video_sample, &session->video_decoder);
|
||||||
|
|
|
@ -32,6 +32,7 @@ data class StreamStateCreateError(val error: SessionCreateError): StreamState()
|
||||||
data class StreamStateQuit(val reason: QuitReason, val reasonString: String?): StreamState()
|
data class StreamStateQuit(val reason: QuitReason, val reasonString: String?): StreamState()
|
||||||
data class StreamStateLoginPinRequest(val pinIncorrect: Boolean): StreamState()
|
data class StreamStateLoginPinRequest(val pinIncorrect: Boolean): StreamState()
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
class StreamSession(val connectInfo: ConnectInfo)
|
class StreamSession(val connectInfo: ConnectInfo)
|
||||||
{
|
{
|
||||||
var session: Session? = null
|
var session: Session? = null
|
||||||
|
@ -40,8 +41,8 @@ class StreamSession(val connectInfo: ConnectInfo)
|
||||||
private val _state = MutableLiveData<StreamState>(StreamStateIdle)
|
private val _state = MutableLiveData<StreamState>(StreamStateIdle)
|
||||||
val state: LiveData<StreamState> get() = _state
|
val state: LiveData<StreamState> get() = _state
|
||||||
|
|
||||||
@ExperimentalUnsignedTypes
|
|
||||||
private val controllerState = ControllerState()
|
private val controllerState = ControllerState()
|
||||||
|
private var touchControllerState = ControllerState()
|
||||||
|
|
||||||
var surfaceTexture: SurfaceTexture? = null
|
var surfaceTexture: SurfaceTexture? = null
|
||||||
|
|
||||||
|
@ -147,8 +148,18 @@ class StreamSession(val connectInfo: ConnectInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session?.setControllerState(controllerState)
|
sendControllerState()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateTouchControllerState(controllerState: ControllerState)
|
||||||
|
{
|
||||||
|
touchControllerState = controllerState
|
||||||
|
sendControllerState()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendControllerState()
|
||||||
|
{
|
||||||
|
session?.setControllerState(controllerState or touchControllerState)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package com.metallic.chiaki.lib
|
package com.metallic.chiaki.lib
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.util.Log
|
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class ConnectVideoProfile(
|
data class ConnectVideoProfile(
|
||||||
|
@ -49,14 +49,17 @@ class ErrorCode(val value: Int)
|
||||||
var isSuccess = value == 0
|
var isSuccess = value == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ControllerState @ExperimentalUnsignedTypes constructor(
|
private fun maxAbs(a: Short, b: Short) = if(abs(a.toInt()) > abs(b.toInt())) a else b
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
data class ControllerState constructor(
|
||||||
var buttons: UInt = 0U,
|
var buttons: UInt = 0U,
|
||||||
var l2_state: UByte = 0U,
|
var l2State: UByte = 0U,
|
||||||
var r2_state: UByte = 0U,
|
var r2State: UByte = 0U,
|
||||||
var left_x: Short = 0,
|
var leftX: Short = 0,
|
||||||
var left_y: Short = 0,
|
var leftY: Short = 0,
|
||||||
var right_x: Short = 0,
|
var rightX: Short = 0,
|
||||||
var right_y: Short = 0
|
var rightY: Short = 0
|
||||||
){
|
){
|
||||||
companion object
|
companion object
|
||||||
{
|
{
|
||||||
|
@ -77,6 +80,16 @@ data class ControllerState @ExperimentalUnsignedTypes constructor(
|
||||||
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
|
val BUTTON_TOUCHPAD = (1 shl 14).toUInt()
|
||||||
val BUTTON_PS = (1 shl 15).toUInt()
|
val BUTTON_PS = (1 shl 15).toUInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
infix fun or(o: ControllerState) = ControllerState(
|
||||||
|
buttons = buttons or o.buttons,
|
||||||
|
l2State = maxOf(l2State, o.l2State),
|
||||||
|
r2State = maxOf(r2State, o.r2State),
|
||||||
|
leftX = maxAbs(leftX, o.leftX),
|
||||||
|
leftY = maxAbs(leftY, o.leftY),
|
||||||
|
rightX = maxAbs(rightX, o.rightX),
|
||||||
|
rightY = maxAbs(rightY, o.rightY)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class QuitReason(val value: Int)
|
class QuitReason(val value: Int)
|
||||||
|
|
|
@ -19,15 +19,17 @@ package com.metallic.chiaki.stream
|
||||||
|
|
||||||
import android.graphics.Matrix
|
import android.graphics.Matrix
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import com.metallic.chiaki.R
|
import com.metallic.chiaki.R
|
||||||
import com.metallic.chiaki.lib.ConnectInfo
|
import com.metallic.chiaki.lib.ConnectInfo
|
||||||
|
import com.metallic.chiaki.touchcontrols.TouchControlsFragment
|
||||||
import kotlinx.android.synthetic.main.activity_stream.*
|
import kotlinx.android.synthetic.main.activity_stream.*
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
class StreamActivity : AppCompatActivity()
|
class StreamActivity : AppCompatActivity()
|
||||||
{
|
{
|
||||||
companion object
|
companion object
|
||||||
|
@ -40,7 +42,6 @@ class StreamActivity : AppCompatActivity()
|
||||||
override fun onCreate(savedInstanceState: Bundle?)
|
override fun onCreate(savedInstanceState: Bundle?)
|
||||||
{
|
{
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_stream)
|
|
||||||
|
|
||||||
viewModel = ViewModelProviders.of(this)[StreamViewModel::class.java]
|
viewModel = ViewModelProviders.of(this)[StreamViewModel::class.java]
|
||||||
if(!viewModel.isInitialized)
|
if(!viewModel.isInitialized)
|
||||||
|
@ -54,6 +55,8 @@ class StreamActivity : AppCompatActivity()
|
||||||
viewModel.init(connectInfo)
|
viewModel.init(connectInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_stream)
|
||||||
|
|
||||||
viewModel.session.attachToTextureView(textureView)
|
viewModel.session.attachToTextureView(textureView)
|
||||||
|
|
||||||
viewModel.session.state.observe(this, Observer {
|
viewModel.session.state.observe(this, Observer {
|
||||||
|
@ -65,6 +68,13 @@ class StreamActivity : AppCompatActivity()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
override fun onAttachFragment(fragment: Fragment)
|
||||||
|
{
|
||||||
|
super.onAttachFragment(fragment)
|
||||||
|
(fragment as? TouchControlsFragment)?.controllerStateCallback = viewModel.session::updateTouchControllerState
|
||||||
|
}
|
||||||
|
|
||||||
override fun onResume()
|
override fun onResume()
|
||||||
{
|
{
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
|
@ -37,6 +37,8 @@ class DPadView @JvmOverloads constructor(
|
||||||
var state: Direction? = null
|
var state: Direction? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
var stateChangeCallback: ((Direction?) -> Unit)? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Radius (as a fraction of the entire DPad Radius)
|
* Radius (as a fraction of the entire DPad Radius)
|
||||||
* to be used as a deadzone in the center on move events
|
* to be used as a deadzone in the center on move events
|
||||||
|
@ -69,7 +71,7 @@ class DPadView @JvmOverloads constructor(
|
||||||
drawable = dpadIdleDrawable
|
drawable = dpadIdleDrawable
|
||||||
|
|
||||||
drawable?.setBounds(0, 0, width, height)
|
drawable?.setBounds(0, 0, width, height)
|
||||||
drawable?.alpha = 127
|
//drawable?.alpha = 127
|
||||||
drawable?.draw(canvas)
|
drawable?.draw(canvas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +108,7 @@ class DPadView @JvmOverloads constructor(
|
||||||
{
|
{
|
||||||
state = newState
|
state = newState
|
||||||
invalidate()
|
invalidate()
|
||||||
// TODO: callback
|
stateChangeCallback?.let { it(state) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Chiaki.
|
||||||
|
*
|
||||||
|
* Chiaki is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Chiaki is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.metallic.chiaki.touchcontrols
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.metallic.chiaki.R
|
||||||
|
import com.metallic.chiaki.lib.ControllerState
|
||||||
|
import kotlinx.android.synthetic.main.fragment_controls.*
|
||||||
|
|
||||||
|
@ExperimentalUnsignedTypes
|
||||||
|
class TouchControlsFragment : Fragment()
|
||||||
|
{
|
||||||
|
var controllerState = ControllerState()
|
||||||
|
private set(value)
|
||||||
|
{
|
||||||
|
val diff = field != value
|
||||||
|
field = value
|
||||||
|
if(diff)
|
||||||
|
controllerStateCallback?.let { it(value) }
|
||||||
|
}
|
||||||
|
|
||||||
|
var controllerStateCallback: ((ControllerState) -> Unit)? = null
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
|
||||||
|
= inflater.inflate(R.layout.fragment_controls, container, false)
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?)
|
||||||
|
{
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
dpadView.stateChangeCallback = this::dpadStateChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dpadStateChanged(direction: DPadView.Direction?)
|
||||||
|
{
|
||||||
|
controllerState = controllerState.copy().apply {
|
||||||
|
buttons = ((buttons
|
||||||
|
and ControllerState.BUTTON_DPAD_LEFT.inv()
|
||||||
|
and ControllerState.BUTTON_DPAD_RIGHT.inv()
|
||||||
|
and ControllerState.BUTTON_DPAD_UP.inv()
|
||||||
|
and ControllerState.BUTTON_DPAD_DOWN.inv())
|
||||||
|
or when(direction)
|
||||||
|
{
|
||||||
|
DPadView.Direction.UP -> ControllerState.BUTTON_DPAD_UP
|
||||||
|
DPadView.Direction.DOWN -> ControllerState.BUTTON_DPAD_DOWN
|
||||||
|
DPadView.Direction.LEFT -> ControllerState.BUTTON_DPAD_LEFT
|
||||||
|
DPadView.Direction.RIGHT -> ControllerState.BUTTON_DPAD_RIGHT
|
||||||
|
null -> 0U
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -51,20 +51,4 @@
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/morningEditText" />
|
app:layout_constraintTop_toBottomOf="@+id/morningEditText" />
|
||||||
|
|
||||||
<com.metallic.chiaki.touchcontrols.DPadView
|
|
||||||
android:layout_width="200dp"
|
|
||||||
android:layout_height="200dp"
|
|
||||||
android:layout_marginTop="32dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<com.metallic.chiaki.touchcontrols.DPadView
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="100dp"
|
|
||||||
android:layout_marginBottom="32dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -17,24 +17,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
|
<fragment
|
||||||
|
android:id="@+id/controlsFragment"
|
||||||
|
android:name="com.metallic.chiaki.touchcontrols.TouchControlsFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<com.metallic.chiaki.touchcontrols.DPadView
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="100dp"
|
|
||||||
android:layout_marginLeft="32dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
|
||||||
|
|
||||||
<com.metallic.chiaki.touchcontrols.DPadView
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="100dp"
|
|
||||||
android:layout_marginRight="32dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
20
android/app/src/main/res/layout/fragment_controls.xml
Normal file
20
android/app/src/main/res/layout/fragment_controls.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<com.metallic.chiaki.touchcontrols.ControlsBackgroundView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<com.metallic.chiaki.touchcontrols.DPadView
|
||||||
|
android:id="@+id/dpadView"
|
||||||
|
android:layout_width="130dp"
|
||||||
|
android:layout_height="130dp"
|
||||||
|
android:layout_marginLeft="32dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,6 +7,6 @@
|
||||||
<color name="stream_text">@android:color/white</color>
|
<color name="stream_text">@android:color/white</color>
|
||||||
<color name="stream_background">@android:color/black</color>
|
<color name="stream_background">@android:color/black</color>
|
||||||
|
|
||||||
<color name="control_primary">@android:color/white</color>
|
<color name="control_primary">#44ffffff</color>
|
||||||
<color name="control_pressed">#8888ff</color>
|
<color name="control_pressed">#88ffffff</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue