summaryrefslogtreecommitdiff
path: root/Source/Android/app/src
diff options
context:
space:
mode:
authorTom Pratt <tom.pratt@outlook.com>2026-07-23 19:47:07 +0200
committerTom Pratt <tom.pratt@outlook.com>2026-08-24 19:36:00 +0200
commit3236c634d9dfb9d382d1f27c2e380c341cb56ab7 (patch)
tree81178c1de2874cc69d3c45e1e4a4066c0236ab1a /Source/Android/app/src
parent123d32248e455ec242866e3a75fea70dcecfd567 (diff)
Add functionality to get and set controller mappings in Android
Diffstat (limited to 'Source/Android/app/src')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt31
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt24
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt16
3 files changed, 70 insertions, 1 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
index 56676c4d3f..d44e70ba09 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/NetplaySession.kt
@@ -23,6 +23,7 @@ import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.runningFold
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
+import org.dolphinemu.dolphinemu.features.netplay.model.ControllerMapping
import org.dolphinemu.dolphinemu.features.netplay.model.GameDigestProgress
import org.dolphinemu.dolphinemu.features.netplay.model.NetplayMessage
import org.dolphinemu.dolphinemu.features.netplay.model.Player
@@ -87,6 +88,12 @@ class NetplaySession(
)
val players = _players.asSharedFlow().distinctUntilChanged()
+ private val _controllerMapping = MutableSharedFlow<ControllerMapping>(
+ replay = 1,
+ onBufferOverflow = BufferOverflow.DROP_OLDEST
+ )
+ val controllerMapping = _controllerMapping.asSharedFlow().distinctUntilChanged()
+
private val _chatMessages = MutableSharedFlow<String>(
extraBufferCapacity = 32,
onBufferOverflow = BufferOverflow.DROP_OLDEST
@@ -185,6 +192,11 @@ class NetplaySession(
fun reconnectTraversal() = nativeReconnectTraversal()
+ fun setControllerMapping(mapping: ControllerMapping) {
+ nativeSetPadMapping(mapping.gamecubePorts.map { it?.pid ?: 0 }.toIntArray())
+ nativeSetWiimoteMapping(mapping.wiiRemotes.map { it?.pid ?: 0 }.toIntArray())
+ }
+
fun consumeBootSessionData(): Long {
return bootSessionDataPointer.also {
bootSessionDataPointer = 0
@@ -278,6 +290,14 @@ class NetplaySession(
private external fun nativeReconnectTraversal()
+ private external fun nativeGetPadMapping(): IntArray
+
+ private external fun nativeGetWiimoteMapping(): IntArray
+
+ private external fun nativeSetPadMapping(mapping: IntArray)
+
+ private external fun nativeSetWiimoteMapping(mapping: IntArray)
+
// NetPlayUI callbacks
@Keep
@@ -304,7 +324,16 @@ class NetplaySession(
@Keep
fun onUpdate(players: Array<Player>) {
- _players.tryEmit(players.toList())
+ val playersList = players.toList()
+ _players.tryEmit(playersList)
+
+ fun findPlayer(playerId: Int) = playersList.find { it.pid == playerId }
+ _controllerMapping.tryEmit(
+ ControllerMapping(
+ gamecubePorts = nativeGetPadMapping().map(::findPlayer).toList(),
+ wiiRemotes = nativeGetWiimoteMapping().map(::findPlayer).toList(),
+ )
+ )
}
@Keep
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt
new file mode 100644
index 0000000000..d7cfae0ab3
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/ControllerMapping.kt
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.features.netplay.model
+
+data class ControllerMapping(
+ val gamecubePorts: List<Player?>,
+ val wiiRemotes: List<Player?>,
+) {
+ fun withGamecubePort(port: Int, player: Player?) =
+ copy(gamecubePorts = gamecubePorts.replace(port, player))
+
+ fun withWiiRemote(port: Int, player: Player?) =
+ copy(wiiRemotes = wiiRemotes.replace(port, player))
+
+ companion object {
+ fun emptyControllerMapping(): ControllerMapping = ControllerMapping(
+ gamecubePorts = emptyList(),
+ wiiRemotes = emptyList(),
+ )
+ }
+}
+
+private fun <T> List<T>.replace(index: Int, value: T) =
+ toMutableList().also { it[index] = value }
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
index 0764448824..1e3aea26a2 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/netplay/model/NetplayViewModel.kt
@@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import org.dolphinemu.dolphinemu.features.netplay.NetplaySession
+import org.dolphinemu.dolphinemu.features.netplay.model.ControllerMapping.Companion.emptyControllerMapping
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting
import org.dolphinemu.dolphinemu.features.settings.model.IntSetting
import org.dolphinemu.dolphinemu.features.settings.model.NativeConfig
@@ -59,6 +60,9 @@ class NetplayViewModel(
val players = netplaySession.players
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
+ val controllerMapping = netplaySession.controllerMapping
+ .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyControllerMapping())
+
val messages = netplaySession.messages
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
@@ -168,6 +172,18 @@ class NetplayViewModel(
netplaySession.changeGame(gameFile)
}
+ fun setGamecubePort(portNumber: Int, player: Player?) {
+ netplaySession.setControllerMapping(
+ controllerMapping.value.withGamecubePort(portNumber, player)
+ )
+ }
+
+ fun setWiiRemote(remoteNumber: Int, player: Player?) {
+ netplaySession.setControllerMapping(
+ controllerMapping.value.withWiiRemote(remoteNumber, player)
+ )
+ }
+
private fun getLocalIp(): JoinAddress {
val localIp = networkHelper.getLocalIpString()
?: return JoinAddress.Unknown { _joinAddresses.value += JoinInfoType.LOCAL to getLocalIp() }