Files
btd700linux/btd700/__main__.py
T
Justin dd0809e877
Tests / unit (de, 3.10) (push) Has been cancelled
Tests / unit (de, 3.14) (push) Has been cancelled
Tests / unit (en, 3.14) (push) Has been cancelled
Tests / unit (en, 3.10) (push) Has been cancelled
Add English localization and MIT-licensed public release documentation
2026-09-05 21:02:14 +02:00

93 lines
4.9 KiB
Python

from .i18n import tr, set_language
import argparse
import getpass
import json
import sys
def main():
language_parser = argparse.ArgumentParser(add_help=False)
language_parser.add_argument('--language', choices=['en', 'de'])
language_args, _ = language_parser.parse_known_args()
if language_args.language:
set_language(language_args.language)
parser = argparse.ArgumentParser(description=tr('Native Linux-Steuerung für den BTD 700; ohne Firmware-Updates.'))
parser.add_argument('--language', choices=['en', 'de'], help=tr('Sprache der App (Standard: Systemsprache)'))
parser.add_argument('--device', help=tr('Steuergerät aus dem Befehl devices, z. B. /dev/hidraw6'))
parser.add_argument('--background', action='store_true', help=tr('Nur im Infobereich starten'))
parser.add_argument('--demo', action='store_true', help=tr('Vorführmodus ohne USB-Zugriff'))
parser.add_argument('--smoke-seconds', type=int, default=0, help=argparse.SUPPRESS)
subs = parser.add_subparsers(dest='command')
subs.add_parser('devices', help=tr('BTD-700-Steuerschnittstellen auflisten'))
subs.add_parser('status', help=tr('Aktuellen Status als JSON ausgeben (ohne Passwort)'))
mode = subs.add_parser('mode', help=tr('Audiomodus wählen'))
mode.add_argument('value', choices=['standard', 'gaming', 'auracast'])
mode.add_argument('--transport', choices=['auto', 'classic', 'le'])
codec = subs.add_parser('codec', help=tr('Codec im Standard-Modus wählen'))
codec.add_argument('value', choices=['sbc', 'aptx', 'adaptive', 'lossless', 'qmap', 'lc3'])
subs.add_parser('connect', help=tr('Gekoppelte Kopfhörer verbinden'))
subs.add_parser('disconnect', help=tr('Kopfhörer trennen'))
broadcast = subs.add_parser('auracast', help=tr('Auracast-Einstellungen speichern'))
broadcast.add_argument('--name')
broadcast.add_argument('--password', action='store_true', help=tr('Neues Passwort verdeckt abfragen'))
broadcast.add_argument('--public', choices=['on', 'off'])
broadcast.add_argument('--encryption', choices=['on', 'off'])
broadcast.add_argument('--quality', choices=['16k', '24k', 'high'])
reset = subs.add_parser('reset', help=tr('Alle Kopplungen und Einstellungen löschen'))
reset.add_argument('--confirm', action='store_true')
args = parser.parse_args()
if not args.command:
try:
from .app import run
return run(background=args.background, demo=args.demo, device=args.device, smoke_seconds=args.smoke_seconds)
except (ImportError, ValueError) as exc:
print(tr('GTK-Oberfläche nicht verfügbar: {error}\nAbhängigkeiten: siehe README.md. CLI: ./run.sh status').format(error=exc), file=sys.stderr)
return 1
from .transport import DeviceError, Hidraw, discover
from .controller import Controller
from .protocol import ProtocolError
if args.command == 'devices':
from dataclasses import asdict
print(json.dumps([asdict(d) for d in discover()], indent=2))
return 0
transport = None
try:
if args.demo:
from .demo import DemoTransport
transport = DemoTransport()
else:
devices = [d for d in discover() if not args.device or d.path == args.device]
if len(devices) != 1:
raise DeviceError(tr('Kein eindeutiger BTD 700 gefunden. devices ausführen; bei mehreren Dongles --device angeben.'))
transport = Hidraw(devices[0])
controller = Controller(transport)
if args.command == 'mode':
controller.set_mode(['standard', 'gaming', 'auracast'].index(args.value),
{'auto': 3, 'classic': 1, 'le': 2}.get(args.transport))
elif args.command == 'codec':
controller.set_codec(1 << ['sbc', 'aptx', 'adaptive', 'lossless', 'qmap', 'lc3'].index(args.value))
elif args.command in ('connect', 'disconnect'):
controller.set_connection(args.command == 'connect')
elif args.command == 'auracast':
controller.set_broadcast(name=args.name,
password=getpass.getpass(tr('Neues Auracast-Passwort: ')) if args.password else None,
public=None if args.public is None else args.public == 'on',
encrypted=None if args.encryption is None else args.encryption == 'on',
quality={'16k': 0, '24k': 1, 'high': 2}.get(args.quality))
elif args.command == 'reset':
controller.factory_reset(confirmed=args.confirm)
print(tr('Zurücksetzen angefordert. Kopfhörer danach neu koppeln.'))
return 0
print(json.dumps(controller.snapshot().public_dict(), indent=2, ensure_ascii=False))
return 0
except (OSError, DeviceError, ProtocolError, ValueError) as exc:
print(tr('Fehler: {error}').format(error=exc), file=sys.stderr)
return 1
finally:
if transport:
transport.close()
if __name__ == '__main__':
raise SystemExit(main())