Compare commits

...

2 Commits

Author SHA1 Message Date
Mel
38a1e7de60 add .idea to gitignore 2025-12-11 23:02:30 +01:00
Mel
6c90998bb0 started to add VTS API code 2025-12-11 23:01:34 +01:00
5 changed files with 105 additions and 28 deletions

3
.gitignore vendored
View File

@@ -166,11 +166,10 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ .idea/
# Ruff stuff: # Ruff stuff:
.ruff_cache/ .ruff_cache/
# PyPI configuration file # PyPI configuration file
.pypirc .pypirc

12
.idea/workspace.xml generated
View File

@@ -2,14 +2,10 @@
<project version="4"> <project version="4">
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="f77c63ed-c4d9-4a13-a764-781244bcbffa" name="Changes" comment=""> <list default="true" id="f77c63ed-c4d9-4a13-a764-781244bcbffa" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/vts-gampad-input/vts_connection.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/vts-gampad-input/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/vts-gampad-input/main.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/vts-gamepad-input.iml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/vts-gampad-input/vts-connection.py" beforeDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/vts-gampad-input/main.py" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/vts-gampad-input/vts-connection.py" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />

View File

@@ -1,7 +1,9 @@
#! /usr/bin/env python #! /usr/bin/env python
import asyncio
import inquirer import inquirer
from inputs import GamePad, devices from inputs import GamePad, devices
from vts_connection import VTSConnection
def _get_gamepads() -> list[GamePad]: def _get_gamepads() -> list[GamePad]:
@@ -37,7 +39,7 @@ def select_gamepad() -> GamePad | None:
return gamepads[0] return gamepads[0]
def _in_deadzone(analog_value: int, percentage: float = 5) -> bool: def _in_deadzone(analog_value: int, percentage: float = 10) -> bool:
center: float = 255 / 2 center: float = 255 / 2
dead_range = center * (percentage / 100) dead_range = center * (percentage / 100)
@@ -47,8 +49,24 @@ def _in_deadzone(analog_value: int, percentage: float = 5) -> bool:
return False return False
def _normalize_analog_sticks(analog_value: float) -> float:
"""Normalize analog value to -1 - 1 range to comply with Nyarupad"""
minimum: int = 0
maximum: int = 255
formula = 2 * ((analog_value - minimum) / (maximum - minimum)) - 1
return formula
def _normalize_analog_trigger(analog_value: float) -> float:
minimum: int = 0
maximum: int = 255
formula = (analog_value - minimum) / (maximum - minimum)
return formula
def main() -> None: def main() -> None:
gamepad = select_gamepad() gamepad = select_gamepad()
connection = VTSConnection()
while True: while True:
for event in gamepad.read(): for event in gamepad.read():
@@ -56,10 +74,18 @@ def main() -> None:
# Add some deadzone of about 5% to analog stick # Add some deadzone of about 5% to analog stick
if event.code in ["ABS_X", "ABS_Y", "ABS_RX", "ABS_RY"]: if event.code in ["ABS_X", "ABS_Y", "ABS_RX", "ABS_RY"]:
if not _in_deadzone(analog_value=event.state): if not _in_deadzone(analog_value=event.state):
print(event.ev_type, event.code, event.state) print(
f"{event.ev_type} {event.code} {_normalize_analog_sticks(analog_value=event.state)}"
)
elif event.code in ["ABS_Z", "ABS_RZ"]:
print(
f"{event.ev_type} {event.code} {_normalize_analog_trigger(event.state)}"
)
else: else:
print(event.ev_type, event.code, event.state) print(event.ev_type, event.code, event.state)
asyncio.run(connection.update_parameters(event.code, event.state))
if __name__ == "__main__": if __name__ == "__main__":
try: try:

View File

@@ -1,16 +0,0 @@
import pyvts
import asyncio
plugin_info = {
"plugin_name": "vts-gampad-input",
"developer": "Melody LaFae",
"authentication_token_path": f"{os.environ['XDG_CONFIG_DIRS']}/.vts-gampad-authentication-token",
}
class VTSConnection:
def __init__(self):
pass
async def connect(self):
vts = pyvts.

View File

@@ -0,0 +1,72 @@
#! /usr/bin/env python
import asyncio
import os
import pyvts
plugin_info = {
"plugin_name": "vts-gampad-input",
"developer": "Melody LaFae",
"authentication_token_path": f"{os.environ['HOME']}/.vts-gampad-authentication-token",
}
class VTSConnection:
def __init__(self):
self.vts = pyvts.vts(plugin_info=plugin_info)
self.request = pyvts.VTSRequest(plugin_info=plugin_info)
if asyncio.run(self._connect()):
asyncio.run(self._create_vts_params())
async def _connect(self) -> bool:
try:
await self.vts.connect()
except OSError:
print("Error: Make sure the VTS API is running")
exit(1)
await self.vts.request_authenticate_token()
await self.vts.request_authenticate()
connection_success = await self.vts.request(
self.request.requestCustomParameter(
parameter="NP_ON",
info="VTS Gamepad Input Enabled",
min=0.0,
max=1.0,
default_value=0.0,
)
)
if not connection_success:
raise ConnectionError("Connection failed")
else:
return True
async def _create_vts_params(self):
params: list[dict] = [
self.request.requestCustomParameter(
parameter="NP_LButtonDown",
info="Left side face buttons down",
min=0.0,
max=1.0,
default_value=0.0,
),
self.request.requestCustomParameter(
parameter="NP_LButtonDown",
info="Left side face buttons down",
min=0.0,
max=1.0,
default_value=0.0,
),
]
async def update_parameters(self, button: str, value: float) -> None:
pass
def main():
VTSConnection()
if __name__ == "__main__":
main()