Add threading, allow mapping events one-to-many

This commit is contained in:
Marc Riera Irigoyen 2022-10-20 00:01:30 +02:00
parent 5052407e53
commit 9712d26508
5 changed files with 77 additions and 25 deletions

View file

@ -55,24 +55,25 @@ class SwitchGamepad(PhysicalGamepad):
# time.sleep(5)
# print("Read from ZKNS-001 correct")
# return InputEvent(InputEvent.EventType.PRESS_BUTTON, InputEvent.Button.BUTTON_A)
print(self.device.active_keys())
select([self.device], [], [], 5)
try:
event = self.device.read_one()
input_events = []
if event is not None:
if event.type == evdev.ecodes.EV_KEY:
match event.code:
case 304: # Y
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_A)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_A))
case 305: # B
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_B)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_B))
case 306: # A
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_C)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_C))
case 307: # X
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_D)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_D))
case 312: # MINUS
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_SELECT)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_SELECT))
case 313: # PLUS
return InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_START)
input_events.append(InputEvent(InputEvent.EventType(event.value), InputEvent.Button.BUTTON_START))
return input_events
except OSError:
return (InputEvent(InputEvent.EventType.ERROR, None))
return [InputEvent(InputEvent.EventType.ERROR, None)]

View file

@ -1,6 +1,7 @@
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QMainWindow, QTableWidgetItem, QHeaderView
import threading
from gui.main_ui import Ui_MainWindow
import gamepads.physical as gamepad_physical
import gamepads.emulated as gamepad_emulated
@ -13,6 +14,8 @@ class MainWindow(QMainWindow):
self._gamepad_handler = gamepad_handler
self._gui = Ui_MainWindow()
self._gui.setupUi(self)
self._emuthread = None
self._emuthread_stop = threading.Event()
self.gamepad_model = GamepadModel(self._gamepad_handler.find_gamepads())
self._gui.tableView_physicalControllerList.setModel(self.gamepad_model)
@ -24,11 +27,18 @@ class MainWindow(QMainWindow):
self._gui.pushButton_physicalControllerRefresh.clicked.connect(self.controller_list_refresh)
self._gui.pushButton_emulatedControllerStart.clicked.connect(self.controller_emulator_start)
self._gui.pushButton_emulatedControllerStop.clicked.connect(self.controller_emulator_stop)
self._gui.pushButton_emulatedControllerStop.setVisible(False)
def closeEvent(self, event):
self._emuthread_stop.set()
def controller_list_refresh(self):
self.gamepad_model.beginResetModel()
self.gamepad_model.gamepads = self._gamepad_handler.find_gamepads()
self.gamepad_model.endResetModel()
self.controller_list_selection_changed()
def controller_list_selection_changed(self):
enabled = False
@ -37,10 +47,41 @@ class MainWindow(QMainWindow):
enabled = True
self._gui.pushButton_emulatedControllerStart.setEnabled(enabled)
def lock_interface(self,):
self._gui.pushButton_emulatedControllerStart.setVisible(False)
self._gui.pushButton_emulatedControllerStop.setVisible(True)
self._gui.tableView_physicalControllerList.setEnabled(False)
self._gui.pushButton_physicalControllerRefresh.setEnabled(False)
self._gui.pushButton_physicalControllerConfig.setEnabled(False)
self._gui.comboBox_emulatedControllerModel.setEnabled(False)
def unlock_interface(self,):
self._gui.pushButton_emulatedControllerStart.setVisible(True)
self._gui.pushButton_emulatedControllerStop.setVisible(False)
self._gui.tableView_physicalControllerList.setEnabled(True)
self._gui.pushButton_physicalControllerRefresh.setEnabled(True)
self._gui.pushButton_physicalControllerConfig.setEnabled(True)
self._gui.comboBox_emulatedControllerModel.setEnabled(True)
def controller_emulator_start(self):
self._gui.pushButton_emulatedControllerStart.setEnabled(False)
self.lock_interface()
self._gui.statusbar.showMessage("Gamepad emulator running...")
rows = self._gui.tableView_physicalControllerList.selectionModel().selectedRows()
if rows:
gamepad = self.gamepad_model.gamepads[rows[0].row()]
emulated_gamepad = gamepad_emulated.PC2HandleGamepad()
self._gamepad_handler.start_gamepad_emulator(gamepad, emulated_gamepad)
self._emuthread = threading.Thread(target=self._gamepad_handler.run_gamepad_emulator, args=(gamepad, emulated_gamepad, self._emuthread_stop))
self._emuthread.start()
def controller_emulator_stop(self):
self._gui.statusbar.showMessage("Stopping gamepad emulator...")
self._emuthread_stop.set()
self._emuthread.join(timeout=0.05)
if self._emuthread.is_alive():
QTimer.singleShot(50, self.controller_emulator_stop)
return
self._emuthread_stop.clear()
self.unlock_interface()
self.controller_list_refresh()
self._gui.statusbar.showMessage("Gamepad emulator stopped successfully!", 5000)

View file

@ -70,8 +70,8 @@ class Ui_MainWindow(object):
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.comboBox_emulatedControllerModel.sizePolicy().hasHeightForWidth())
self.comboBox_emulatedControllerModel.setSizePolicy(sizePolicy)
self.comboBox_emulatedControllerModel.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContents)
self.comboBox_emulatedControllerModel.setObjectName("comboBox_emulatedControllerModel")
self.comboBox_emulatedControllerModel.addItem("")
self.horizontalLayout.addWidget(self.comboBox_emulatedControllerModel)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
@ -79,6 +79,9 @@ class Ui_MainWindow(object):
self.pushButton_emulatedControllerStart.setEnabled(False)
self.pushButton_emulatedControllerStart.setObjectName("pushButton_emulatedControllerStart")
self.horizontalLayout.addWidget(self.pushButton_emulatedControllerStart)
self.pushButton_emulatedControllerStop = QtWidgets.QPushButton(self.groupBox_emulatedController)
self.pushButton_emulatedControllerStop.setObjectName("pushButton_emulatedControllerStop")
self.horizontalLayout.addWidget(self.pushButton_emulatedControllerStop)
self.verticalLayout_main.addWidget(self.groupBox_emulatedController)
self.gridLayout.addLayout(self.verticalLayout_main, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
@ -97,5 +100,5 @@ class Ui_MainWindow(object):
self.pushButton_physicalControllerConfig.setText(_translate("MainWindow", "Configuration"))
self.groupBox_emulatedController.setTitle(_translate("MainWindow", "Emulated controller"))
self.label_emulatedControllerModel.setText(_translate("MainWindow", "Model"))
self.comboBox_emulatedControllerModel.setItemText(0, _translate("MainWindow", "Two-handle controller for PC (DGOC-44U)"))
self.pushButton_emulatedControllerStart.setText(_translate("MainWindow", "Start"))
self.pushButton_emulatedControllerStop.setText(_translate("MainWindow", "Stop"))

View file

@ -130,11 +130,9 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Two-handle controller for PC (DGOC-44U)</string>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</item>
</widget>
</item>
<item>
@ -160,6 +158,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_emulatedControllerStop">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View file

@ -1,4 +1,5 @@
from evdev import InputDevice, list_devices, ecodes as e, UInput, AbsInfo
import threading
import events.input as input_events
import gamepads.physical as gamepad_physical
import gamepads.emulated as gamepad_emulated
@ -15,10 +16,11 @@ class GamepadHandler:
gamepads.append(gamepad_physical.create_gamepad(0x0f0d, 0x00c1, "Test gamepad"))
return gamepads
def start_gamepad_emulator(gamepad, emulated_gamepad):
while True:
event = gamepad.read_input()
if event is not None:
def run_gamepad_emulator(gamepad, emulated_gamepad, stop_event):
while not stop_event.is_set():
events = gamepad.read_input()
if events is not None:
for event in events:
if event.type == input_events.InputEvent.EventType.ERROR:
break
emulated_gamepad.write_input(event)