Add pyproject.toml
This commit is contained in:
parent
3a9f707e9b
commit
abdda5a7c4
3 changed files with 88 additions and 2 deletions
25
README.md
25
README.md
|
|
@ -63,17 +63,31 @@ Flags:
|
|||
## Python bridge (recommended)
|
||||
Works on macOS, Windows, Linux. Uses SDL2 + pyserial.
|
||||
|
||||
### Install dependencies with uv (or pip)
|
||||
### Install dependencies (pyproject-enabled)
|
||||
The repository now includes a `pyproject.toml`, so you can install the bridge and helper scripts as an editable package:
|
||||
|
||||
```sh
|
||||
# from repo root
|
||||
uv venv .venv
|
||||
uv pip install pyserial pysdl2
|
||||
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
||||
uv pip install -e .
|
||||
```
|
||||
|
||||
Prefer stock pip?
|
||||
|
||||
```sh
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
- SDL2 runtime: install via your OS package manager (macOS: `brew install sdl2`; Windows: place `SDL2.dll` on PATH or next to the script; Linux: `sudo apt install libsdl2-2.0-0` or equivalent).
|
||||
|
||||
### Run
|
||||
```sh
|
||||
source .venv/bin/activate # or .venv\Scripts\activate on Windows
|
||||
controller-uart-bridge --interactive
|
||||
# or, equivalently
|
||||
python controller_uart_bridge.py --interactive
|
||||
```
|
||||
Options:
|
||||
|
|
@ -88,6 +102,8 @@ Options:
|
|||
- `--deadzone 0.08` to change stick deadzone (0.0-1.0).
|
||||
- `--zero-sticks` to sample the current stick positions on connect and treat them as neutral (cancel drift).
|
||||
- `--zero-hotkey z` to choose the terminal hotkey that re-zeroes all connected controllers on demand (press `z` by default; pass an empty string to disable).
|
||||
- `--update-controller-db` to download the latest SDL GameController database before launching (defaults to the copy in `controller_db/` if present).
|
||||
- `--controller-db-url URL` to override the source URL when updating the controller database (defaults to the official mdqinc repo).
|
||||
- `--trigger-threshold 0.35` to change analog trigger press threshold (0.0-1.0).
|
||||
- `--swap-abxy` to flip AB/XY globally.
|
||||
- `--swap-abxy-index N` (repeatable) to flip AB/XY for controllers first seen at index N (auto-converts to a stable GUID).
|
||||
|
|
@ -101,6 +117,11 @@ Options:
|
|||
- Hotkeys work only when the bridge is started from a TTY/console that currently has focus. Pass an empty string to either flag to disable that shortcut (useful when running unattended).
|
||||
- If you launch the bridge with `--swap-abxy` (global swap), the per-controller toggle hotkey will show that the layout is enforced globally and will not override it.
|
||||
|
||||
### Updating SDL controller mappings
|
||||
- The bridge ships with a pinned `controller_db/gamecontrollerdb.txt`. Run `controller-uart-bridge --update-controller-db ...` to download the latest database from the official upstream (`mdqinc/SDL_GameControllerDB`).
|
||||
- The download only touches `controller_db/gamecontrollerdb.txt`; add `--controller-db-url https://.../custom.txt` if you maintain your own fork.
|
||||
- If the file is missing, the bridge will automatically attempt a download on startup.
|
||||
|
||||
Hot-plugging: controllers and UARTs can be plugged/unplugged while running; the bridge will auto reconnect when possible.
|
||||
|
||||
### Using the lightweight UART helper (no SDL needed)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import argparse
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
from dataclasses import dataclass, field
|
||||
from ctypes import create_string_buffer
|
||||
from pathlib import Path
|
||||
|
|
@ -50,6 +51,9 @@ RUMBLE_IDLE_TIMEOUT = 0.25 # seconds without packets before forcing rumble off
|
|||
RUMBLE_STUCK_TIMEOUT = 0.60 # continuous same-energy rumble will be stopped after this
|
||||
RUMBLE_MIN_ACTIVE = 0.50 # below this, rumble is treated as off/noise
|
||||
RUMBLE_SCALE = 0.8
|
||||
CONTROLLER_DB_URL_DEFAULT = (
|
||||
"https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt"
|
||||
)
|
||||
|
||||
|
||||
def parse_mapping(value: str) -> Tuple[int, str]:
|
||||
|
|
@ -66,6 +70,28 @@ def parse_mapping(value: str) -> Tuple[int, str]:
|
|||
return idx, port.strip()
|
||||
|
||||
|
||||
def download_controller_db(console: Console, destination: Path, url: str) -> bool:
|
||||
"""Download the latest SDL controller DB to the local controller_db directory."""
|
||||
console.print(f"[cyan]Fetching SDL controller database from {url}...[/cyan]")
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=20) as response:
|
||||
status = getattr(response, "status", 200)
|
||||
if status != 200:
|
||||
raise RuntimeError(f"HTTP {status}")
|
||||
data = response.read()
|
||||
except Exception as exc:
|
||||
console.print(f"[red]Failed to download controller database: {exc}[/red]")
|
||||
return False
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
destination.write_bytes(data)
|
||||
except Exception as exc:
|
||||
console.print(f"[red]Failed to write controller database to {destination}: {exc}[/red]")
|
||||
return False
|
||||
console.print(f"[green]Updated controller database ({len(data)} bytes) at {destination}[/green]")
|
||||
return True
|
||||
|
||||
|
||||
def parse_hotkey(value: str) -> str:
|
||||
"""Validate a single-character hotkey (empty string disables)."""
|
||||
if value is None:
|
||||
|
|
@ -578,6 +604,16 @@ def build_arg_parser() -> argparse.ArgumentParser:
|
|||
metavar="KEY",
|
||||
help="Press this key in the terminal to re-zero sticks at runtime (default: 'z', empty string disables).",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--update-controller-db",
|
||||
action="store_true",
|
||||
help="Download the latest SDL GameController database before loading mappings.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--controller-db-url",
|
||||
default=CONTROLLER_DB_URL_DEFAULT,
|
||||
help="Override the URL used to download the SDL GameController database.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--swap-hotkey",
|
||||
type=parse_hotkey,
|
||||
|
|
@ -704,6 +740,8 @@ class PairingState:
|
|||
def load_button_maps(console: Console, args: argparse.Namespace) -> Tuple[Dict[int, SwitchButton], Dict[int, SwitchButton], set[int]]:
|
||||
"""Load SDL controller mappings and return button map variants."""
|
||||
default_mapping = Path(__file__).parent / "controller_db" / "gamecontrollerdb.txt"
|
||||
if args.update_controller_db or not default_mapping.exists():
|
||||
download_controller_db(console, default_mapping, args.controller_db_url)
|
||||
mappings_to_load: List[str] = []
|
||||
if default_mapping.exists():
|
||||
mappings_to_load.append(str(default_mapping))
|
||||
|
|
|
|||
27
pyproject.toml
Normal file
27
pyproject.toml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
[build-system]
|
||||
requires = ["setuptools>=65"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "switch-pico-bridge"
|
||||
version = "0.1.0"
|
||||
description = "SDL2-to-UART host bridge and helpers for the switch-pico firmware."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
authors = [{ name = "Switch Pico Maintainers" }]
|
||||
dependencies = [
|
||||
"pyserial",
|
||||
"pysdl2",
|
||||
"rich",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
controller-uart-bridge = "controller_uart_bridge:main"
|
||||
host-uart-logger = "host_uart_logger:main"
|
||||
|
||||
[tool.setuptools]
|
||||
py-modules = [
|
||||
"controller_uart_bridge",
|
||||
"host_uart_logger",
|
||||
"switch_pico_uart",
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue