diff --git a/generate_svg.py b/generate_svg.py index b9aef84c..c1abab7b 100755 --- a/generate_svg.py +++ b/generate_svg.py @@ -1,17 +1,16 @@ #!/usr/bin/env python3 -from scc.tools import _ +import os +from enum import IntEnum -from scc.actions import Action, DPadAction, XYAction, MouseAction -from scc.modifiers import ModeModifier, DoubleclickModifier -from scc.special_actions import MenuAction -from scc.parser import TalkingActionParser +from scc.actions import Action, DPadAction, MouseAction, XYAction from scc.constants import SCButtons +from scc.gui.svg_widget import SVGEditor +from scc.modifiers import DoubleclickModifier, ModeModifier +from scc.parser import TalkingActionParser from scc.profile import Profile -from scc.tools import nameof +from scc.special_actions import MenuAction +from scc.tools import _, nameof from scc.uinput import Rels -from scc.gui.svg_widget import SVGEditor -from scc.lib import IntEnum -import os class Align(IntEnum): @@ -30,33 +29,33 @@ def find_image(name): class Line(object): - + def __init__(self, icon, text): self.icons = [ icon ] self.text = text - - + + def get_size(self, gen): # TODO: This return gen.char_width * len(self.text), gen.line_height - - + + def add_icon(self, icon): self.icons.append(icon) return self - - + + def to_string(self): return "%-10s: %s" % (",".join([ x for x in self.icons if x ]), self.text) class LineCollection(object): """ Allows calling add_icon on multiple lines at once """ - + def __init__(self, *lines): self.lines = lines - - + + def add_icon(self, icon): for line in self.lines: line.add_icon(icon) @@ -68,7 +67,7 @@ class Box(object): SPACING = 2 MIN_WIDTH = 100 MIN_HEIGHT = 50 - + def __init__(self, anchor_x, anchor_y, align, name, min_width = MIN_WIDTH, min_height = MIN_HEIGHT): self.name = name @@ -79,15 +78,15 @@ def __init__(self, anchor_x, anchor_y, align, name, self.x, self.y = 0, 0 self.min_width = min_width self.min_height = min_height - - + + def to_string(self): return "--- %s ---\n%s\n" % ( self.name, "\n".join([ x.to_string() for x in self.lines ]) ) - - + + def add(self, icon, context, action): if not action: return LineCollection() if isinstance(action, ModeModifier): @@ -107,7 +106,7 @@ def add(self, icon, context, action): lines.append( self.add("HOLD", context, action.holdaction) .add_icon(icon) ) return LineCollection(*lines) - + action = action.strip() if isinstance(action, MenuAction): if self.name == "bcs" and action.menu_id == "Default.menu": @@ -127,7 +126,7 @@ def add(self, icon, context, action): # Special case, pad bound to wheel line = Line(icon, _("Mouse Wheel")) self.lines.append(line) - return line + return line return LineCollection( self.add("AXISX", Action.AC_BUTTON, action.x), self.add("AXISY", Action.AC_BUTTON, action.y) @@ -135,8 +134,8 @@ def add(self, icon, context, action): line = Line(icon, action.describe(context)) self.lines.append(line) return line - - + + def calculate(self, gen): self.width, self.height = self.min_width, 2 * self.PADDING self.icount = 0 @@ -146,7 +145,7 @@ def calculate(self, gen): self.icount = max(self.icount, len(line.icons)) self.width += 2 * self.PADDING + self.icount * (gen.line_height + self.SPACING) self.height = max(self.height, self.min_height) - + anchor_x, anchor_y = self.anchor if (self.align & Align.TOP) != 0: self.y = anchor_y @@ -154,15 +153,15 @@ def calculate(self, gen): self.y = gen.full_height - self.height - anchor_y else: self.y = (gen.full_height - self.height) / 2 - + if (self.align & Align.LEFT) != 0: self.x = anchor_x elif (self.align & Align.RIGHT) != 0: self.x = gen.full_width - self.width - anchor_x else: self.x = (gen.full_width - self.width) / 2 - - + + def place(self, gen, root): e = SVGEditor.add_element(root, "rect", style = "opacity:1;fill-opacity:0.0;stroke-width:2.0;", @@ -172,7 +171,7 @@ def place(self, gen, root): width = self.width, height = self.height, x = self.x, y = self.y, ) - + y = self.y + self.PADDING for line in self.lines: h = gen.line_height @@ -191,8 +190,8 @@ def place(self, gen, root): ) SVGEditor.set_text(txt, line.text) y += self.SPACING - - + + def place_marker(self, gen, root): x1, y1 = self.x, self.y x2, y2 = x1 + self.width, y1 + self.height @@ -213,7 +212,7 @@ def place_marker(self, gen, root): edges = [ [ x2, y1 ], [ x2, y2 ] ] elif self.align & Align.RIGHT != 0: edges = [ [ x1, y1 ], [ x2, y2 ] ] - + targets = SVGEditor.get_element(root, "markers_%s" % (self.name,)) if targets is None: return @@ -226,7 +225,7 @@ def place_marker(self, gen, root): except IndexError: break edges = [ i for i in edges if len(i) == 4] - + for x1, y1, x2, y2 in edges: e = SVGEditor.add_element(root, "line", style = "opacity:1;stroke:#06a400;stroke-width:0.5;", @@ -238,7 +237,7 @@ def place_marker(self, gen, root): class Generator(object): PADDING = 10 - + def __init__(self): svg = SVGEditor(file("images/binding-display.svg").read()) background = SVGEditor.get_element(svg, "background") @@ -247,18 +246,18 @@ def __init__(self): self.char_width = int(float(self.label_template.attrib.get("width") or 8)) self.full_width = int(float(background.attrib.get("width") or 800)) self.full_height = int(float(background.attrib.get("height") or 800)) - + profile = Profile(TalkingActionParser()).load("test.sccprofile") boxes = [] - - + + box_bcs = Box(0, self.PADDING, Align.TOP, "bcs") box_bcs.add("BACK", Action.AC_BUTTON, profile.buttons.get(SCButtons.BACK)) box_bcs.add("C", Action.AC_BUTTON, profile.buttons.get(SCButtons.C)) box_bcs.add("START", Action.AC_BUTTON, profile.buttons.get(SCButtons.START)) boxes.append(box_bcs) - - + + box_left = Box(self.PADDING, self.PADDING, Align.LEFT | Align.TOP, "left", min_height = self.full_height * 0.5, min_width = self.full_width * 0.2) @@ -267,8 +266,8 @@ def __init__(self): box_left.add("LGRIP", Action.AC_BUTTON, profile.buttons.get(SCButtons.LGRIP)) box_left.add("LPAD", Action.AC_PAD, profile.pads.get(profile.LEFT)) boxes.append(box_left) - - + + box_right = Box(self.PADDING, self.PADDING, Align.RIGHT | Align.TOP, "right", min_height = self.full_height * 0.5, min_width = self.full_width * 0.2) @@ -277,47 +276,47 @@ def __init__(self): box_right.add("RGRIP", Action.AC_BUTTON, profile.buttons.get(SCButtons.RGRIP)) box_right.add("RPAD", Action.AC_PAD, profile.pads.get(profile.RIGHT)) boxes.append(box_right) - - + + box_abxy = Box(4 * self.PADDING, self.PADDING, Align.RIGHT | Align.BOTTOM, "abxy") box_abxy.add("A", Action.AC_BUTTON, profile.buttons.get(SCButtons.A)) box_abxy.add("B", Action.AC_BUTTON, profile.buttons.get(SCButtons.B)) box_abxy.add("X", Action.AC_BUTTON, profile.buttons.get(SCButtons.X)) box_abxy.add("Y", Action.AC_BUTTON, profile.buttons.get(SCButtons.Y)) boxes.append(box_abxy) - - + + box_stick = Box(4 * self.PADDING, self.PADDING, Align.LEFT | Align.BOTTOM, "stick") box_stick.add("STICK", Action.AC_STICK, profile.stick) boxes.append(box_stick) - - + + w = int(float(background.attrib.get("width") or 800)) h = int(float(background.attrib.get("height") or 800)) - + root = SVGEditor.get_element(svg, "root") for b in boxes: b.calculate(self) - + # Set ABXY and Stick size & position box_abxy.height = box_stick.height = self.full_height * 0.25 box_abxy.width = box_stick.width = self.full_width * 0.3 box_abxy.y = self.full_height - self.PADDING - box_abxy.height box_stick.y = self.full_height - self.PADDING - box_stick.height box_abxy.x = self.full_width - self.PADDING - box_abxy.width - + self.equal_width(box_left, box_right) self.equal_height(box_left, box_right) - + for b in boxes: b.place_marker(self, root) for b in boxes: b.place(self, root) - + file("out.svg", "w").write(svg.to_string()) - - - + + + def equal_width(self, *boxes): """ Sets width of all passed boxes to width of widest box """ width = 0 @@ -326,8 +325,8 @@ def equal_width(self, *boxes): b.width = width if b.align & Align.RIGHT: b.x = self.full_width - b.width - self.PADDING - - + + def equal_height(self, *boxes): """ Sets height of all passed boxes to height of tallest box """ height = 0 diff --git a/scc/constants.py b/scc/constants.py index 9312fe54..aa780e06 100644 --- a/scc/constants.py +++ b/scc/constants.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from scc.lib import IntEnum +from enum import IntEnum """ If SC-Controller is updated while daemon is running, DAEMON_VERSION send by diff --git a/scc/drivers/ds5drv.py b/scc/drivers/ds5drv.py index 20ea033a..60865ca8 100644 --- a/scc/drivers/ds5drv.py +++ b/scc/drivers/ds5drv.py @@ -10,6 +10,7 @@ import sys import time import zlib +from enum import IntEnum from scc.constants import ( OUTPUT_360_STICK_MAX, @@ -45,7 +46,6 @@ hiddrv_test, ) from scc.drivers.usb import register_hotplug_device -from scc.lib import IntEnum from scc.lib.hidraw import HIDRaw from scc.sccdaemon import SCCDaemon from scc.tools import init_logging, set_logging_level diff --git a/scc/drivers/hiddrv.py b/scc/drivers/hiddrv.py index 9aa2abe4..fec75af2 100644 --- a/scc/drivers/hiddrv.py +++ b/scc/drivers/hiddrv.py @@ -7,6 +7,7 @@ import logging import os import sys +from enum import IntEnum from scc.constants import STICK_PAD_MAX, STICK_PAD_MIN, ControllerFlags, SCButtons from scc.controller import Controller @@ -16,7 +17,6 @@ register_hotplug_device, unregister_hotplug_device, ) -from scc.lib import IntEnum from scc.lib.hidparse import ( AXES, GenericDesktopPage, diff --git a/scc/drivers/sc_dongle.py b/scc/drivers/sc_dongle.py index d921d908..41e0717a 100644 --- a/scc/drivers/sc_dongle.py +++ b/scc/drivers/sc_dongle.py @@ -1,21 +1,21 @@ -#!/usr/bin/env python3 -""" -SC Controller - Steam Controller Wireless Receiver (aka Dongle) Driver +"""SC Controller - Steam Controller Wireless Receiver (aka Dongle) Driver. Called and used when Dongle is detected on USB bus. Handles one or multiple controllers connected to dongle. """ +from __future__ import annotations -from scc.lib import IntEnum -from scc.drivers.usb import USBDevice, register_hotplug_device -from scc.constants import SCButtons, STICKTILT, STICK_PAD_MIN, STICK_PAD_MAX -from scc.controller import Controller -from scc.config import Config -from collections import namedtuple -from math import pi as PI, sin, cos -from typing import Union -import struct import logging +import struct +from collections import namedtuple +from enum import IntEnum +from math import cos, sin +from math import pi as PI + +from scc.config import Config +from scc.constants import STICK_PAD_MAX, STICK_PAD_MIN, STICKTILT, SCButtons +from scc.controller import Controller +from scc.drivers.usb import USBDevice, register_hotplug_device VENDOR_ID = 0x28de PRODUCT_ID = 0x1142 @@ -301,7 +301,7 @@ def disconnected(self): # Has to be overriden in sc_by_cable FORMAT2 = b'>BBBB59x' - def configure(self, idle_timeout: Union[int, None] = None, enable_gyros: Union[bool, None] = None, led_level: Union[int, None] = None): + def configure(self, idle_timeout: int | None = None, enable_gyros: bool | None = None, led_level: int | None = None): """ Sets and, if possible, sends configuration to controller. Only value that is provided is changed. @@ -394,8 +394,7 @@ def feedback(self, data): def _feedback(self, position, amplitude=128, period=0, count=1): - """ - Add haptic feedback to be send on next usb tick + """Add haptic feedback to be send on next usb tick. @param int position haptic to use 1 for left 0 for right @param int amplitude signal amplitude from 0 to 65535 @@ -407,7 +406,7 @@ def _feedback(self, position, amplitude=128, period=0, count=1): SCPacketType.FEEDBACK, 0x07, position, amplitude, period, count)) -def init(daemon, config: dict) -> Union[Dongle, bool]: +def init(daemon, config: dict) -> Dongle | bool: """ Registers hotplug callback for controller dongle """ def cb(device, handle): return Dongle(device, handle, daemon) diff --git a/scc/drivers/steamdeck.py b/scc/drivers/steamdeck.py index df0b4475..a17bb411 100644 --- a/scc/drivers/steamdeck.py +++ b/scc/drivers/steamdeck.py @@ -11,11 +11,11 @@ import ctypes import logging import struct +from enum import IntEnum from scc.constants import STICK_PAD_MAX, STICK_PAD_MIN, ControllerFlags, SCButtons from scc.drivers.sc_dongle import SCController, SCPacketType from scc.drivers.usb import USBDevice, register_hotplug_device -from scc.lib import IntEnum VENDOR_ID = 0x28de PRODUCT_ID = 0x1205 diff --git a/scc/lib/hidparse.py b/scc/lib/hidparse.py index 973c6cf1..e77faacc 100644 --- a/scc/lib/hidparse.py +++ b/scc/lib/hidparse.py @@ -1,5 +1,4 @@ -""" -hidparse - just enough code to parse HID report from hidraw descriptor. +"""hidparse - just enough code to parse HID report from hidraw descriptor. Based on - Pythonic binding for linux's hidraw ioctls @@ -9,17 +8,35 @@ Licensed under GPL 2.0 """ -from scc.lib.hidparse_data import GlobalItem, MainItem, LocalItem, UsagePage -from scc.lib.hidparse_data import SensorPage, SensorSelector, LightSensor -from scc.lib.hidparse_data import GenericDesktopPage, page_to_enum -from scc.lib.hidparse_data import MotionSensor, OrientationSensor -from scc.lib.hidparse_data import ModifierI2a, HidSensorProperty -from scc.lib.hidparse_data import ItemType, ItemLength, ItemBase -from scc.lib.hidparse_data import SensorEvent, SensorDataField -from scc.lib.hidparse_data import Collection, Unit, UnitType +import ctypes +import fcntl +import struct +from enum import IntEnum + from scc.lib import ioctl_opt -from scc.lib import IntEnum -import ctypes, fcntl, collections, struct +from scc.lib.hidparse_data import ( + Collection, + GenericDesktopPage, + GlobalItem, + HidSensorProperty, + ItemBase, + ItemLength, + ItemType, + LightSensor, + LocalItem, + MainItem, + ModifierI2a, + MotionSensor, + OrientationSensor, + SensorDataField, + SensorEvent, + SensorPage, + SensorSelector, + Unit, + UnitType, + UsagePage, + page_to_enum, +) # hid.h _HID_MAX_DESCRIPTOR_SIZE = 4096 @@ -58,16 +75,16 @@ class BusType(IntEnum): class ReservedItem(object): _CACHE = {} - + def __init__(self, value): self.value = value - - + + def __repr__(self): return "" % (self.value,) - + __str__ = __repr__ - + def __new__(cls, value): if value not in cls._CACHE: cls._CACHE[value] = object.__new__(cls) @@ -158,7 +175,7 @@ def parse_item(it, page): isize = it[1] itag = it[3] * 256 + it[2] raise ValueError("Not implemented: long item!!") - + if itype == 0x00: # main items item = enum_or_reserved(MainItem, itag) if item == MainItem.Collection: @@ -277,7 +294,7 @@ def _split_hid_items(data): def parse_report_descriptor(data, flat_list=False): """ Parses HID report descriptor to list of elements. - + If flat_list is set to True, only one list is returned. Otherwise, each collection is stored in its own nested list. """ @@ -302,14 +319,14 @@ def parse_report_descriptor(data, flat_list=False): col.append(item) else: col.append(item) - + return rv def get_report_descriptor(devfile, flat_list=False): """ Returns parsed HID report descriptor as list of elements. - + If flat_list is set to True, only one list is returned. Otherwise, each collection is stored in its own nested list. """ @@ -318,7 +335,7 @@ def get_report_descriptor(devfile, flat_list=False): class Parser(object): - + def __init__(self, code, offset, count, size): self.code = code self.value = 0 @@ -342,8 +359,8 @@ def __init__(self, code, offset, count, size): self.byte_len = 1 self.fmt = ">= self.additional_bits @@ -354,14 +371,14 @@ def decode(self, data): class HIDButtonParser(Parser): TYPE = HIDPARSE_TYPE_BUTTONS - + def __repr__(self): return "" % (self.offset, self.len, self.value) class HIDAxisParser(Parser): TYPE = HIDPARSE_TYPE_AXIS - + def __repr__(self): return "" % (self.offset, self.len, self.value) diff --git a/scc/lib/hidparse_data.py b/scc/lib/hidparse_data.py index 4573e19b..f01f98aa 100644 --- a/scc/lib/hidparse_data.py +++ b/scc/lib/hidparse_data.py @@ -1,10 +1,9 @@ -""" -hidparse_data - long enums moved from hidparse.py +"""hidparse_data - long enums moved from hidparse.py. Licensed under GPL 2.0 """ -from scc.lib import IntEnum +from enum import IntEnum class MainItem(IntEnum): diff --git a/scc/osd/binding_display.py b/scc/osd/binding_display.py index dd8d111c..eba0fdf4 100644 --- a/scc/osd/binding_display.py +++ b/scc/osd/binding_display.py @@ -1,32 +1,32 @@ -#!/usr/bin/env python3 -""" -SC-Controller - OSD Launcher +"""SC-Controller - OSD Launcher. Display launcher with phone-like keyboard that user can use to select application (list is generated using xdg) and start it. Reuses styles from OSD Menu and OSD Dialog """ -from scc.tools import _, set_logging_level +import base64 +import logging +import os +import sys +from enum import IntEnum from gi.repository import Gtk -from scc.actions import DPadAction, AxisAction, MouseAction -from scc.actions import Action, MultiAction, XYAction -from scc.modifiers import ModeModifier, DoubleclickModifier -from scc.paths import get_share_path, get_config_path -from scc.menu_data import MenuData, MenuItem -from scc.lib import xwrappers as X, IntEnum -from scc.special_actions import MenuAction -from scc.parser import TalkingActionParser -from scc.constants import SCButtons -from scc.profile import Profile + +from scc.actions import Action, AxisAction, DPadAction, MouseAction, MultiAction, XYAction from scc.config import Config -from scc.tools import nameof -from scc.uinput import Rels -from scc.gui.svg_widget import SVGWidget, SVGEditor +from scc.constants import SCButtons from scc.gui.daemon_manager import DaemonManager +from scc.gui.svg_widget import SVGEditor, SVGWidget +from scc.modifiers import DoubleclickModifier, ModeModifier from scc.osd import OSDWindow -import os, sys, re, base64, logging +from scc.parser import TalkingActionParser +from scc.paths import get_config_path, get_share_path +from scc.profile import Profile +from scc.special_actions import MenuAction +from scc.tools import _, nameof +from scc.uinput import Rels + log = logging.getLogger("osd.binds") @@ -58,9 +58,7 @@ def on_profile_changed(self, daemon, filename): def use_daemon(self, d): - """ - Allows (re)using already existing DaemonManager instance in same process - """ + """Allows (re)using already existing DaemonManager instance in same process.""" self.daemon = d self._cononect_handlers() self.on_daemon_connected(self.daemon) @@ -76,10 +74,7 @@ def _add_arguments(self): def compute_position(self): - """ - Unlike other OSD windows, this one is scaled to 80% of screen size - and centered in on active screen. - """ + """Unlike other OSD windows, this one is scaled to 80% of screen size and centered in on active screen.""" x, y = 10, 10 iw, ih = self.background.image_width, self.background.image_height geometry = self.get_active_screen_geometry() diff --git a/scc/osd/osk_actions.py b/scc/osd/osk_actions.py index c5f694b7..0dfccd38 100644 --- a/scc/osd/osk_actions.py +++ b/scc/osd/osk_actions.py @@ -1,6 +1,4 @@ -#!/usr/bin/env python3 -""" -SC Controller - On Screen Keyboard Actions +"""SC Controller - On Screen Keyboard Actions. Special Actions that are used to bind functions like closing keyboard or moving cursors around. @@ -9,11 +7,11 @@ and its binding editor enables them to use with 'OSK.something' syntax. """ -from scc.lib import Enum -from scc.constants import TRIGGER_HALF, LEFT, RIGHT +import logging + from scc.actions import Action, SpecialAction +from scc.constants import LEFT, RIGHT, TRIGGER_HALF -import time, logging log = logging.getLogger("OSDKeyActs") _ = lambda x : x diff --git a/scc/uinput.py b/scc/uinput.py index 6704a3bb..f29068b1 100644 --- a/scc/uinput.py +++ b/scc/uinput.py @@ -24,12 +24,12 @@ import ctypes import os from ctypes import POINTER, byref, c_bool, c_int16, c_int32, c_uint16 +from enum import IntEnum from math import copysign, fmod, sqrt from libusb1 import timeval from scc.cheader import defines -from scc.lib import IntEnum from scc.tools import find_library UNPUT_MODULE_VERSION = 9 diff --git a/tests/test_strings/test_keys.py b/tests/test_strings/test_keys.py index f118d373..11b1aea5 100644 --- a/tests/test_strings/test_keys.py +++ b/tests/test_strings/test_keys.py @@ -1,8 +1,10 @@ +from enum import IntEnum + from scc.uinput import Keys -from scc.lib import IntEnum + class TestKeys(object): def test_up_str(self): assert isinstance(Keys.KEY_UP, IntEnum) assert Keys.KEY_UP.name == "KEY_UP" - assert str(Keys.KEY_UP) == "Keys.KEY_UP" \ No newline at end of file + assert str(Keys.KEY_UP) == "Keys.KEY_UP"