From ec74519d4526462b3b7bd2a941a2575899850098 Mon Sep 17 00:00:00 2001 From: ayozetr <53948812+ayozetr@users.noreply.github.com> Date: Sat, 13 Jun 2026 23:33:21 +0100 Subject: [PATCH] Add power switch to enable/disable the selected wheel Add a per-device power switch that authorizes/deauthorizes the selected wheel at the USB level (sysfs 'authorized'), hiding it from every game and application without unplugging it. A deauthorized wheel leaves the input subsystem and disappears from the device list, so the switch keeps representing it (off, with a status label showing how to re-enable it) until the user flips the switch back on. The disabled wheel is remembered (persisted in config) and re-enabled by writing to its stored USB path. - device: track usb_path and add is_authorized/can_set_authorized/set_authorized - device_manager: resolve usb_path via find_parent and add authorize_path to re-enable a wheel that already left the input subsystem - gui: power switch wired to the selected device, with a status label and remembered disabled wheel; update_power_controls keeps the switch coherent on every device-list refresh - udev: new 99-oversteer-wheel-power.rules granting write access to the 'authorized' attribute for supported wheels only - po: translate the new strings (Power, Re-enable, tooltip, permission message) into all 9 languages --- .gitignore | 2 + data/udev/99-oversteer-wheel-power.rules | 71 ++++++++++++++++++++++++ oversteer/device.py | 30 ++++++++++ oversteer/device_manager.py | 18 ++++++ oversteer/gtk_handlers.py | 6 ++ oversteer/gtk_ui.py | 17 ++++++ oversteer/gui.py | 57 +++++++++++++++++++ oversteer/main.ui | 54 ++++++++++++++++++ po/ca.po | 19 +++++++ po/de.po | 19 +++++++ po/es.po | 22 ++++++++ po/fi.po | 19 +++++++ po/gl.po | 19 +++++++ po/hu.po | 19 +++++++ po/pl.po | 19 +++++++ po/ru.po | 19 +++++++ po/tr.po | 19 +++++++ 17 files changed, 429 insertions(+) create mode 100644 data/udev/99-oversteer-wheel-power.rules diff --git a/.gitignore b/.gitignore index 9cd9129..0f4c7ec 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ __pycache__ /extra *~ +/.dev-locale +/run.py diff --git a/data/udev/99-oversteer-wheel-power.rules b/data/udev/99-oversteer-wheel-power.rules new file mode 100644 index 0000000..a2ebf15 --- /dev/null +++ b/data/udev/99-oversteer-wheel-power.rules @@ -0,0 +1,71 @@ +# Allow regular users to enable/disable supported wheels from Oversteer. +# +# Oversteer's power switch writes to the USB device's "authorized" attribute +# (1 = visible to the system, 0 = hidden from every game/application). That +# attribute lives at the usb_device node and is owned by root, so this rule +# grants write access to it for the supported wheels only, avoiding any other +# USB device (mice, keyboards, etc.). +# +# The usb_device node and its "authorized" attribute exist as long as the wheel +# is plugged in, even while deauthorized, so this single rule covers both +# disabling and re-enabling. + +ACTION=="remove", GOTO="oversteer_power_end" +SUBSYSTEM!="usb", GOTO="oversteer_power_end" +ENV{DEVTYPE}!="usb_device", GOTO="oversteer_power_end" + +# Logitech wheels +ATTR{idVendor}=="046d", ATTR{idProduct}=="c294", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c29a", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c298", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c299", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c29b", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c24f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c262", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c266", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c26e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c268", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c272", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c295", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="ca03", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c29c", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c291", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c293", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="046d", ATTR{idProduct}=="c20e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +# Thrustmaster wheels +ATTR{idVendor}=="044f", ATTR{idProduct}=="b677", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b696", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b66e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b66f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b66d", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b65e", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b668", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b66a", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b67f", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b664", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b692", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b669", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="044f", ATTR{idProduct}=="b689", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +# Other Thrustmaster (different vendor IDs) +ATTR{idVendor}=="24c6", ATTR{idProduct}=="5b00", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="06f8", ATTR{idProduct}=="0004", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +# Fanatec wheels +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0020", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0e03", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0005", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0001", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0004", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0006", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="0eb7", ATTR{idProduct}=="0007", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +# Cammus +ATTR{idVendor}=="3416", ATTR{idProduct}=="0301", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +# Generic FFBoard / Flashfire +ATTR{idVendor}=="1209", ATTR{idProduct}=="ffb0", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" +ATTR{idVendor}=="2f24", ATTR{idProduct}=="010d", RUN+="/bin/sh -c 'chmod 666 %S%p/authorized'" + +LABEL="oversteer_power_end" diff --git a/oversteer/device.py b/oversteer/device.py index 039990f..ae17b6b 100644 --- a/oversteer/device.py +++ b/oversteer/device.py @@ -27,6 +27,7 @@ def __init__(self, device_manager, data): self.product_id = None self.usb_id = None self.dev_path = None + self.usb_path = None self.dev_name = None self.name = None self.ready = True @@ -82,6 +83,35 @@ def check_file_permissions(self, filename): def get_max_range(self): return self.max_range + def authorized_file(self): + if self.usb_path is None: + return None + return os.path.join(self.usb_path, 'authorized') + + def is_authorized(self): + path = self.authorized_file() + if path is None or not os.access(path, os.F_OK | os.R_OK): + return None + with open(path, "r") as file: + data = file.read() + return int(data.strip()) == 1 + + def can_set_authorized(self): + path = self.authorized_file() + if path is None: + return False + return os.access(path, os.W_OK) + + def set_authorized(self, authorized): + path = self.authorized_file() + if path is None: + return False + value = "1" if authorized else "0" + logging.debug("Setting authorized: %s (%s)", value, path) + with open(path, "w") as file: + file.write(value) + return True + def list_modes(self): path = self.checked_device_file("alternate_modes") if not path: diff --git a/oversteer/device_manager.py b/oversteer/device_manager.py index f30a4f8..cd16b93 100644 --- a/oversteer/device_manager.py +++ b/oversteer/device_manager.py @@ -117,6 +117,9 @@ def update_device_list(self, udevice): logging.debug("%s: ID_VENDOR_ID: %s ID_MODEL_ID: %s", device_node, udevice.get('ID_VENDOR_ID'), udevice.get('ID_MODEL_ID')) + usb_device = udevice.find_parent('usb', 'usb_device') + usb_path = usb_device.sys_path if usb_device is not None else None + device.set({ 'id': id, 'vendor_id': udevice.get('ID_VENDOR_ID'), @@ -124,6 +127,7 @@ def update_device_list(self, udevice): 'usb_id': usb_id, 'dev_name': device_node, 'dev_path': os.path.realpath(os.path.join(udevice.sys_path, 'device', 'device')), + 'usb_path': usb_path, 'name': bytes(udevice.get('ID_VENDOR_ENC') + ' ' + udevice.get('ID_MODEL_ENC'), 'utf-8').decode('unicode_escape'), 'max_range': self.supported_wheels[usb_id], @@ -144,6 +148,20 @@ def get_device(self, did): return self.devices[did] return next((item for item in self.devices.values() if item.dev_name == did), None) + def authorize_path(self, usb_path, authorized): + # Re-enable a wheel that is no longer in the device list (it left the + # input subsystem when it was deauthorized). The usb_device node and its + # 'authorized' attribute still exist while the wheel stays plugged in. + if usb_path is None: + return False + path = os.path.join(usb_path, 'authorized') + if not os.access(path, os.F_OK | os.W_OK): + return False + with open(path, "w") as file: + file.write("1" if authorized else "0") + self.changed = True + return True + def is_changed(self): changed = self.changed self.changed = False diff --git a/oversteer/gtk_handlers.py b/oversteer/gtk_handlers.py index e7bb146..954a49c 100644 --- a/oversteer/gtk_handlers.py +++ b/oversteer/gtk_handlers.py @@ -52,6 +52,12 @@ def on_update_clicked(self, button): self.controller.populate_window() self.ui.update() + def on_wheel_power_state_set(self, widget, state): + if self.ui._suppress_power_signal: + return False + self.controller.set_wheel_power(state) + return False + def on_change_emulation_mode_clicked(self, widget): mode = self.ui.emulation_mode_combobox.get_active_id() self.model.set_mode(mode) diff --git a/oversteer/gtk_ui.py b/oversteer/gtk_ui.py index 8cd63b5..adc75c8 100644 --- a/oversteer/gtk_ui.py +++ b/oversteer/gtk_ui.py @@ -16,6 +16,7 @@ def __init__(self, controller, argv): self.ffbmeter_timer = False self.current_test_canvas = None self.current_test_toolbar = None + self._suppress_power_signal = False Gdk.init(argv) style_provider = Gtk.CssProvider() @@ -168,6 +169,20 @@ def set_check_permissions(self, state): def set_device_id(self, device_id): self.device_combobox.set_active_id(device_id) + def set_wheel_power(self, state, sensitive = True): + # Update the switch without triggering a write back to the device. + self._suppress_power_signal = True + self.wheel_power.set_sensitive(sensitive and state is not None) + self.wheel_power.set_active(bool(state)) + self._suppress_power_signal = False + + def set_wheel_power_status(self, text): + if text: + self.wheel_power_status.set_label(text) + self.wheel_power_status.show() + else: + self.wheel_power_status.hide() + def set_devices(self, devices): model = self.device_combobox.get_model() if model is None: @@ -578,6 +593,8 @@ def _set_builder_objects(self): self.check_permissions = self.builder.get_object('check_permissions') self.device_combobox = self.builder.get_object('device') + self.wheel_power = self.builder.get_object('wheel_power') + self.wheel_power_status = self.builder.get_object('wheel_power_status') self.profile_combobox = self.builder.get_object('profile') self.new_profile_name_entry = self.builder.get_object('new_profile_name') self.save_profile_button = self.builder.get_object('save_profile') diff --git a/oversteer/gui.py b/oversteer/gui.py index 77e604a..2a75f42 100644 --- a/oversteer/gui.py +++ b/oversteer/gui.py @@ -56,6 +56,7 @@ def __init__(self, application, model, argv): self.model = model self.device_manager = self.app.device_manager self.device = None + self.disabled_wheel = None self.grab_input = False self.test = None self.linear_chart = None @@ -155,6 +156,7 @@ def populate_devices(self): if device.is_ready(): device_list.append((device.get_id(), device.name)) self.ui.set_devices(device_list) + self.update_power_controls() def populate_profiles(self): profiles = [] @@ -166,6 +168,52 @@ def populate_profiles(self): def populate_window(self): self.populate_devices() self.populate_profiles() + self.update_power_controls() + + def update_power_controls(self): + # A disabled wheel leaves the device list, so the switch keeps + # representing it (off, with a status message) until it's re-enabled. + if self.disabled_wheel is not None: + self.ui.set_wheel_power(False, True) + self.ui.set_wheel_power_status(_("Re-enable {}").format(self.disabled_wheel['name'])) + elif self.device is not None and self.device.is_authorized() is not None: + self.ui.set_wheel_power(self.device.is_authorized(), self.device.can_set_authorized()) + self.ui.set_wheel_power_status(None) + else: + self.ui.set_wheel_power(False, False) + self.ui.set_wheel_power_status(None) + + def set_wheel_power(self, state): + try: + if state: + if self.disabled_wheel is not None: + # Re-enable the remembered wheel; it's no longer in the list. + if not self.device_manager.authorize_path(self.disabled_wheel['usb_path'], True): + raise PermissionError + self.disabled_wheel = None + self.save_preferences() + elif self.device is not None: + self.device.set_authorized(True) + else: + if self.device is None: + return + self.device.set_authorized(False) + # Remember the wheel so it can be re-enabled with the switch + # after it disappears from the device list. + self.disabled_wheel = { + 'usb_path': self.device.usb_path, + 'name': self.device.name, + } + self.save_preferences() + except (KeyboardInterrupt, SystemExit): + raise + except OSError: + if self.app.udev_path: + self.install_udev_files() + else: + self.ui.info_dialog(_("You don't have the required permissions to " + + "enable or disable the wheel.")) + self.update_power_controls() def change_device(self, device_id): self.device = self.device_manager.get_device(device_id) @@ -188,6 +236,8 @@ def change_device(self, device_id): self.model = Model(self.device, self.ui) self.models[self.device.get_id()] = self.model + self.update_power_controls() + self.ui.set_max_range(self.device.get_max_range()) self.ui.set_modes(self.model.get_mode_list()) @@ -265,6 +315,11 @@ def load_preferences(self): Locale.setlocale(Locale.LC_ALL, (self.locale, 'UTF-8')) if 'check_permissions' in config['DEFAULT']: self.check_permissions = config['DEFAULT']['check_permissions'] == '1' + if config['DEFAULT'].get('disabled_wheel_path', '') != '': + self.disabled_wheel = { + 'usb_path': config['DEFAULT']['disabled_wheel_path'], + 'name': config['DEFAULT'].get('disabled_wheel_name', _('wheel')), + } if 'button_config' in config['DEFAULT'] and config['DEFAULT']['button_config'] != '': if 'button_toggle' not in config['DEFAULT']: self.button_config = list(map(int, config['DEFAULT']['button_config'].split(','))) @@ -298,6 +353,8 @@ def save_preferences(self): 'check_permissions': '1' if self.check_permissions else '0', 'button_toggle': ','.join(map(str, self.button_config[0])), 'button_config': ','.join(map(str, self.button_config[1:])), + 'disabled_wheel_path': self.disabled_wheel['usb_path'] if self.disabled_wheel else '', + 'disabled_wheel_name': self.disabled_wheel['name'] if self.disabled_wheel else '', } config_file = os.path.join(self.config_path, 'config.ini') with open(config_file, 'w') as file: diff --git a/oversteer/main.ui b/oversteer/main.ui index b5ad218..d59b1a3 100644 --- a/oversteer/main.ui +++ b/oversteer/main.ui @@ -356,6 +356,60 @@ 1 + + + True + False + 8 + Enable or disable the wheel for the whole system. When disabled, no game or application can see it. + + + True + False + Power + + + False + True + 0 + + + + + True + True + center + True + + + + False + True + 1 + + + + + False + True + center + + + + False + True + 2 + + + + + False + True + 2 + + False diff --git a/po/ca.po b/po/ca.po index cb1e70a..372188b 100644 --- a/po/ca.po +++ b/po/ca.po @@ -912,6 +912,25 @@ msgstr "Configurador de volants" msgid "game;racing;cars;wheels" msgstr "jocs;carreres;coches;volants" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Encesa" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Activa o desactiva el volant per a tot el sistema. Quan està desactivat, cap joc o aplicació no el pot veure." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Reactiva {}" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "No tens els permissos requerits per a activar o desactivar el volant." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/de.po b/po/de.po index 4e91f7a..15e2973 100644 --- a/po/de.po +++ b/po/de.po @@ -908,5 +908,24 @@ msgstr "Lenkradmanager" msgid "game;racing;cars;wheels" msgstr "Spiele;Rennen;Autos;Lenkrad" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Ein/Aus" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Aktiviert oder deaktiviert das Lenkrad systemweit. Wenn deaktiviert, kann es kein Spiel und keine Anwendung sehen." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "{} wieder aktivieren" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Keine Berechtigung, das Lenkrad zu aktivieren oder zu deaktivieren." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/es.po b/po/es.po index be2fac5..0044955 100644 --- a/po/es.po +++ b/po/es.po @@ -918,6 +918,28 @@ msgstr "Configurador de volantes" msgid "game;racing;cars;wheels" msgstr "juego;carreras;coches;volantes" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Encendido" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "" +"Activa o desactiva el volante para todo el sistema. Cuando está desactivado, " +"ningún juego o aplicación puede verlo." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Reactivar {}" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "" +"No tienes los permisos necesarios para activar o desactivar el volante." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/fi.po b/po/fi.po index 79c34b6..f87aca8 100644 --- a/po/fi.po +++ b/po/fi.po @@ -909,3 +909,22 @@ msgstr "Rattimanageri" #: data/io.github.berarma.Oversteer.desktop.in:12 msgid "game;racing;cars;wheels" msgstr "peli;ajo;autot;ratit" + +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Virta" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Ota ratti käyttöön tai poista se käytöstä koko järjestelmässä. Kun se on poistettu käytöstä, mikään peli tai sovellus ei näe sitä." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Ota {} uudelleen käyttöön" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Sinulla ei ole tarvittavia oikeuksia ottaa rattia käyttöön tai poistaa sitä käytöstä." diff --git a/po/gl.po b/po/gl.po index c905505..209f19d 100644 --- a/po/gl.po +++ b/po/gl.po @@ -913,6 +913,25 @@ msgstr "Configurador de Volantes" msgid "game;racing;cars;wheels" msgstr "xogo;carreiras;coches;volantes" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Acendido" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Activa ou desactiva o volante para todo o sistema. Cando está desactivado, ningún xogo ou aplicación pode velo." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Reactivar {}" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Non tes os permisos necesarios para activar ou desactivar o volante." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/hu.po b/po/hu.po index 38f9235..930e53b 100644 --- a/po/hu.po +++ b/po/hu.po @@ -926,5 +926,24 @@ msgstr "Kormánykerék-kezelő" msgid "game;racing;cars;wheels" msgstr "game;racing;cars;wheels;játék;verseny;autók;kormánykerék" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Be/Ki" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Engedélyezi vagy letiltja a kormánykereket az egész rendszer számára. Letiltva egyetlen játék vagy alkalmazás sem látja." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "{} újraengedélyezése" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Nincs jogosultsága a kormánykerék engedélyezéséhez vagy letiltásához." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/pl.po b/po/pl.po index 1f1240d..0288657 100644 --- a/po/pl.po +++ b/po/pl.po @@ -918,3 +918,22 @@ msgstr "Oversteer" #: data/io.github.berarma.Oversteer.desktop.in:12 msgid "game;racing;cars;wheels" msgstr "gra;wyścigi;auta;kierownice;" + +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Zasilanie" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Włącza lub wyłącza kierownicę dla całego systemu. Po wyłączeniu żadna gra ani aplikacja jej nie widzi." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Włącz ponownie {}" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Nie masz uprawnień by włączyć lub wyłączyć kierownicę." diff --git a/po/ru.po b/po/ru.po index 6e705a3..e950156 100644 --- a/po/ru.po +++ b/po/ru.po @@ -913,5 +913,24 @@ msgstr "Мастер настройки руля" msgid "game;racing;cars;wheels" msgstr "игра;гонки;автомобили;рули" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Питание" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Включает или отключает руль для всей системы. В отключённом состоянии его не видит ни одна игра или приложение." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "Снова включить {}" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "У вас нет необходимых разрешений для включения или отключения руля." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer" diff --git a/po/tr.po b/po/tr.po index ff7c561..1fd0854 100644 --- a/po/tr.po +++ b/po/tr.po @@ -912,6 +912,25 @@ msgstr "Direksiyon Yöneticisi" msgid "game;racing;cars;wheels" msgstr "oyun;yarış;arabalar;direksiyonlar" +#: oversteer/main.ui:369 +msgid "Power" +msgstr "Güç" + +#: oversteer/main.ui:364 +msgid "" +"Enable or disable the wheel for the whole system. When disabled, no game or " +"application can see it." +msgstr "Direksiyonu tüm sistem için etkinleştirir veya devre dışı bırakır. Devre dışı bırakıldığında hiçbir oyun veya uygulama onu göremez." + +#: oversteer/gui.py:178 +#, python-brace-format +msgid "Re-enable {}" +msgstr "{} cihazını yeniden etkinleştir" + +#: oversteer/gui.py:214 +msgid "You don't have the required permissions to enable or disable the wheel." +msgstr "Direksiyonu etkinleştirmek veya devre dışı bırakmak için gerekli izinlere sahip değilsiniz." + #~ msgid "io.github.berarma.Oversteer" #~ msgstr "io.github.berarma.Oversteer"