Merge branch 'master' into finnish
Conflicts: po/solaar.pot - run tools/po-compile.sh
This commit is contained in:
commit
372e4e0949
|
@ -1,3 +1,10 @@
|
||||||
|
0.9.3:
|
||||||
|
* Merged solaar-cli functionality into main solaar.
|
||||||
|
* Scrolling over the systray icon switches between multiple peripherals.
|
||||||
|
* Swedish translation courtesy of Daniel Zippert and Emelie Snecker
|
||||||
|
* French translation courtesy of Papoteur, David Geiger and Damien Lallement.
|
||||||
|
* Fixed some untranslated strings.
|
||||||
|
|
||||||
0.9.2:
|
0.9.2:
|
||||||
* Added support for hand detection on the K800.
|
* Added support for hand detection on the K800.
|
||||||
* Added support for V550 and V450 Nano.
|
* Added support for V550 and V450 Nano.
|
||||||
|
|
10
README.md
10
README.md
|
@ -28,14 +28,16 @@ Pre-built packages are available for a few Linux distros.
|
||||||
The `solaar` package uses a standard system tray implementation; to ensure
|
The `solaar` package uses a standard system tray implementation; to ensure
|
||||||
integration with *gnome-shell* or *Unity*, install `solaar-gnome3`.
|
integration with *gnome-shell* or *Unity*, install `solaar-gnome3`.
|
||||||
|
|
||||||
* a [Gentoo overlay][gentoo], courtesy of Carlos Silva
|
|
||||||
* an [OpenSUSE rpm][opensuse], courtesy of Mathias Homann
|
|
||||||
* an [Arch package][arch], courtesy of Arnaud Taffanel
|
* an [Arch package][arch], courtesy of Arnaud Taffanel
|
||||||
|
* a [Gentoo overlay][gentoo], courtesy of Carlos Silva
|
||||||
|
* a [Mageia package][mageia], courtesy of Damien Lallement
|
||||||
|
* an [OpenSUSE rpm][opensuse], courtesy of Mathias Homann
|
||||||
|
|
||||||
[ppa]: http://launchpad.net/~daniel.pavel/+archive/solaar
|
[ppa]: http://launchpad.net/~daniel.pavel/+archive/solaar
|
||||||
[gentoo]: http://code.r3pek.org/gentoo-overlay/src
|
|
||||||
[opensuse]: http://software.opensuse.org/package/Solaar
|
|
||||||
[arch]: http://aur.archlinux.org/packages/solaar
|
[arch]: http://aur.archlinux.org/packages/solaar
|
||||||
|
[gentoo]: http://code.r3pek.org/gentoo-overlay/src
|
||||||
|
[mageia]: http://mageia.madb.org/package/show/release/cauldron/application/0/name/solaar
|
||||||
|
[opensuse]: http://software.opensuse.org/package/Solaar
|
||||||
|
|
||||||
|
|
||||||
## Manual installation
|
## Manual installation
|
||||||
|
|
|
@ -37,6 +37,7 @@ def init_paths():
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
print ('WARNING: solaar-cli is deprecated; use solaar with the usual arguments')
|
||||||
init_paths()
|
init_paths()
|
||||||
import solaar.cli
|
import solaar.cli
|
||||||
solaar.cli.main()
|
solaar.cli.run()
|
||||||
|
|
|
@ -40,9 +40,6 @@ Solaar, but its supported features are not specified here, I would love to hear
|
||||||
about it.
|
about it.
|
||||||
|
|
||||||
|
|
||||||
Devices marked with an asterisk (*) use a Nano receiver that knows the Unifying
|
|
||||||
protocol, and should be fully supported by Solaar.
|
|
||||||
|
|
||||||
The HID++ column specifies the device's HID++ version.
|
The HID++ column specifies the device's HID++ version.
|
||||||
|
|
||||||
The Battery column specifies if Solaar is able to read the device's battery
|
The Battery column specifies if Solaar is able to read the device's battery
|
||||||
|
@ -56,14 +53,14 @@ You are able to read this feature using solaar-cli, but it is not possible to
|
||||||
assign different keys.
|
assign different keys.
|
||||||
|
|
||||||
|
|
||||||
Keyboards:
|
Keyboards (Unifying):
|
||||||
|
|
||||||
| Device | HID++ | Battery | Other supported features |
|
| Device | HID++ | Battery | Other supported features |
|
||||||
|------------------|-------|---------|-----------------------------------------|
|
|------------------|-------|---------|-----------------------------------------|
|
||||||
| K230 | 2.0 | yes | |
|
| K230 | 2.0 | yes | |
|
||||||
| K270 | | | |
|
| K270 | 1.0 | yes | |
|
||||||
| K340 | | | |
|
| K340 | 1.0 | yes | |
|
||||||
| K350 | | | |
|
| K350 | 1.0 | yes | |
|
||||||
| K360 | 2.0 | yes | FN swap, reprog keys |
|
| K360 | 2.0 | yes | FN swap, reprog keys |
|
||||||
| K400 Touch | 2.0 | yes | |
|
| K400 Touch | 2.0 | yes | |
|
||||||
| K750 Solar | 2.0 | yes | FN swap, Lux reading, light button |
|
| K750 Solar | 2.0 | yes | FN swap, Lux reading, light button |
|
||||||
|
@ -71,50 +68,70 @@ Keyboards:
|
||||||
| MK700 | 1.0 | yes | FN swap, reprog keys |
|
| MK700 | 1.0 | yes | FN swap, reprog keys |
|
||||||
|
|
||||||
|
|
||||||
Mice:
|
Mice (Unifying):
|
||||||
|
|
||||||
| Device | HID++ | Battery | DPI | Other supported features |
|
| Device | HID++ | Battery | DPI | Other supported features |
|
||||||
|------------------|-------|---------|-------|---------------------------------|
|
|------------------|-------|---------|-------|---------------------------------|
|
||||||
| V450 Nano | 1.0 | yes | - | smooth scrolling |
|
|
||||||
| V550 Nano | 1.0 | yes | - | smooth scrolling |
|
|
||||||
| VX Nano | 1.0 | yes | - | smooth scrolling |
|
|
||||||
| M175 * | | yes | | |
|
|
||||||
| M185 * | | yes | | |
|
|
||||||
| M187 * | 2.0 | yes | | |
|
|
||||||
| M215 * | 1.0 | yes | | |
|
|
||||||
| M235 * | | yes | | |
|
|
||||||
| M305 * | 1.0 | yes | | |
|
|
||||||
| M310 * | | yes | | |
|
|
||||||
| M315 * | | yes | | |
|
|
||||||
| M317 | | | | |
|
| M317 | | | | |
|
||||||
| M325 | | | | |
|
| M325 | | | | |
|
||||||
| M345 | 2.0 | yes | - | |
|
| M345 | 2.0 | yes | - | |
|
||||||
| M505 | 1.0 | yes | | |
|
| M350 | 1.0 | yes | | |
|
||||||
|
| M505 | 1.0 | yes | | smooth scrolling |
|
||||||
| M510 | 1.0 | yes | | smooth scrolling |
|
| M510 | 1.0 | yes | | smooth scrolling |
|
||||||
| M515 Couch | 2.0 | yes | - | |
|
| M515 Couch | 2.0 | yes | - | |
|
||||||
| M525 | 2.0 | yes | - | |
|
| M525 | 2.0 | yes | - | |
|
||||||
| M600 Touch | 2.0 | yes | | |
|
| M600 Touch | 2.0 | yes | | |
|
||||||
| M705 Marathon | 1.0 | yes | - | smooth scrolling |
|
| M705 Marathon | 1.0 | yes | - | smooth scrolling |
|
||||||
| T400 Zone Touch | | | | |
|
| T400 Zone Touch | | | | |
|
||||||
| T620 Touch | 2.0 | | | |
|
| T620 Touch | 2.0 | yes | | |
|
||||||
| Performance MX | 1.0 | yes | R/W | |
|
| Performance MX | 1.0 | yes | R/W | |
|
||||||
| Anywhere MX | 1.0 | yes | - | |
|
| Anywhere MX | 1.0 | yes | - | |
|
||||||
| Cube | 2.0 | yes | | |
|
| Cube | 2.0 | yes | | |
|
||||||
|
|
||||||
|
|
||||||
Trackballs:
|
Mice (Nano):
|
||||||
|
|
||||||
|
| Device | HID++ | Battery | DPI | Other supported features |
|
||||||
|
|------------------|-------|---------|-------|---------------------------------|
|
||||||
|
| V450 Nano | 1.0 | yes | - | smooth scrolling |
|
||||||
|
| V550 Nano | 1.0 | yes | - | smooth scrolling |
|
||||||
|
| VX Nano | 1.0 | yes | - | smooth scrolling |
|
||||||
|
| M175 | | yes | | |
|
||||||
|
| M185 | | yes | | |
|
||||||
|
| M187 | 2.0 | yes | | |
|
||||||
|
| M215 | 1.0 | yes | | |
|
||||||
|
| M235 | | yes | | |
|
||||||
|
| M305 | 1.0 | yes | | |
|
||||||
|
| M310 | 1.0 | yes | | |
|
||||||
|
| M315 | | yes | | |
|
||||||
|
|
||||||
|
|
||||||
|
Mice (Mini):
|
||||||
|
|
||||||
|
| Device | HID++ | Battery | DPI | Other supported features |
|
||||||
|
|------------------|-------|---------|-------|---------------------------------|
|
||||||
|
| MX610 | 1.0 | yes | | |
|
||||||
|
| MX610 lefthanded | 1.0 | yes | | |
|
||||||
|
| V400 | 1.0 | yes | | |
|
||||||
|
| V450 | 1.0 | yes | | |
|
||||||
|
| VX Revolution | 1.0 | yes | | |
|
||||||
|
| MX Air | 1.0 | yes | | |
|
||||||
|
| MX Revolution | 1.0 | yes | | |
|
||||||
|
|
||||||
|
|
||||||
|
Trackballs (Unifying):
|
||||||
|
|
||||||
| Device | HID++ | Battery | DPI | Other supported features |
|
| Device | HID++ | Battery | DPI | Other supported features |
|
||||||
|------------------|-------|---------|-------|---------------------------------|
|
|------------------|-------|---------|-------|---------------------------------|
|
||||||
| M570 Trackball | | | | |
|
| M570 Trackball | | | | |
|
||||||
|
|
||||||
|
|
||||||
Touchpads:
|
Touchpads (Unifying):
|
||||||
|
|
||||||
| Device | HID++ | Battery | DPI | Other supported features |
|
| Device | HID++ | Battery | DPI | Other supported features |
|
||||||
|------------------|-------|---------|-------|---------------------------------|
|
|------------------|-------|---------|-------|---------------------------------|
|
||||||
| Wireless Touch | 2.0 | | | |
|
| Wireless Touch | 2.0 | yes | | |
|
||||||
| T650 Touchpad | 2.0 | | | |
|
| T650 Touchpad | 2.0 | yes | | |
|
||||||
|
|
||||||
|
|
||||||
Mouse-Keyboard combos:
|
Mouse-Keyboard combos:
|
||||||
|
|
21
docs/i18n.md
21
docs/i18n.md
|
@ -28,3 +28,24 @@ the source root):
|
||||||
|
|
||||||
You can edit the translation iteratively, just repeat from step 3.
|
You can edit the translation iteratively, just repeat from step 3.
|
||||||
If the upstream changes, do a `git pull` and then repeat from step 2.
|
If the upstream changes, do a `git pull` and then repeat from step 2.
|
||||||
|
|
||||||
|
Before opening a pull request, please run `./tools/po-update.sh` again. It will
|
||||||
|
format and sort the translation file, and ensure a minimal diff when updating
|
||||||
|
a translation.
|
||||||
|
|
||||||
|
|
||||||
|
# Supported languages
|
||||||
|
|
||||||
|
Currently Solaar has been translated in the following languages:
|
||||||
|
|
||||||
|
- Français: [Papoteur][papoteur], [David Geiger][david-geiger],
|
||||||
|
[Damien Lallement][damsweb]
|
||||||
|
- Polski: [Adrian Piotrowicz][nexces]
|
||||||
|
- Română: Daniel Pavel
|
||||||
|
- Svensk: [Daniel Zippert][zipperten], Emelie Snecker
|
||||||
|
|
||||||
|
[papoteur]: http://github.com/papoteur
|
||||||
|
[david-geiger]: http://github.com/david-geiger
|
||||||
|
[damsweb]: http://github.com/damsweb
|
||||||
|
[nexces]: http://github.com/nexces
|
||||||
|
[zipperten]: http://github.com/zipperten
|
||||||
|
|
|
@ -3,8 +3,8 @@ tagline: Linux devices manager for the Logitech Unifying Receiver.
|
||||||
owner: pwr
|
owner: pwr
|
||||||
owner_url: https://github.com/pwr
|
owner_url: https://github.com/pwr
|
||||||
repository: https://github.com/pwr/Solaar
|
repository: https://github.com/pwr/Solaar
|
||||||
version: 0.9.1
|
version: 0.9.2
|
||||||
tar_download: https://github.com/pwr/Solaar/archive/0.9.1.tar.gz
|
tar_download: https://github.com/pwr/Solaar/archive/0.9.2.tar.gz
|
||||||
ga_id: UA-36908718-1
|
ga_id: UA-36908718-1
|
||||||
|
|
||||||
pygments: true
|
pygments: true
|
||||||
|
|
|
@ -28,30 +28,33 @@ _GENERIC_DRIVER = ('hid-generic', 'generic-usb')
|
||||||
|
|
||||||
|
|
||||||
# each tuple contains (vendor_id, product_id, usb interface number, hid driver)
|
# each tuple contains (vendor_id, product_id, usb interface number, hid driver)
|
||||||
|
_unifying_receiver = lambda product_id: (0x046d, product_id, 2, _UNIFYING_DRIVER)
|
||||||
|
_nano_receiver = lambda product_id: (0x046d, product_id, 1, _GENERIC_DRIVER)
|
||||||
|
|
||||||
|
|
||||||
# standard Unifying receivers (marked with the orange Unifying logo)
|
# standard Unifying receivers (marked with the orange Unifying logo)
|
||||||
UNIFYING_RECEIVER = (0x046d, 0xc52b, 2, _UNIFYING_DRIVER)
|
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
|
||||||
UNIFYING_RECEIVER_2 = (0x046d, 0xc532, 2, _UNIFYING_DRIVER)
|
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Nano receviers that support the Unifying protocol
|
# Nano receviers that support the Unifying protocol
|
||||||
NANO_RECEIVER_ADVANCED = (0x046d, 0xc52f, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_ADVANCED = _nano_receiver(0xc52f)
|
||||||
|
|
||||||
# Nano receivers that don't support the Unifying protocol
|
# Nano receivers that don't support the Unifying protocol
|
||||||
NANO_RECEIVER_C517 = (0x046d, 0xc517, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C517 = _nano_receiver(0xc517)
|
||||||
NANO_RECEIVER_C518 = (0x046d, 0xc518, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
|
||||||
NANO_RECEIVER_C51A = (0x046d, 0xc51a, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
|
||||||
NANO_RECEIVER_C51B = (0x046d, 0xc51b, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
|
||||||
NANO_RECEIVER_C521 = (0x046d, 0xc521, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C521 = _nano_receiver(0xc521)
|
||||||
NANO_RECEIVER_C525 = (0x046d, 0xc525, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C525 = _nano_receiver(0xc525)
|
||||||
NANO_RECEIVER_C526 = (0x046d, 0xc526, 1, _GENERIC_DRIVER)
|
NANO_RECEIVER_C526 = _nano_receiver(0xc526)
|
||||||
|
|
||||||
|
|
||||||
|
del _unifying_receiver, _nano_receiver
|
||||||
|
|
||||||
|
|
||||||
ALL = (
|
ALL = (
|
||||||
UNIFYING_RECEIVER,
|
UNIFYING_RECEIVER_C52B,
|
||||||
UNIFYING_RECEIVER_2,
|
UNIFYING_RECEIVER_C532,
|
||||||
NANO_RECEIVER_ADVANCED,
|
NANO_RECEIVER_ADVANCED,
|
||||||
NANO_RECEIVER_C517,
|
NANO_RECEIVER_C517,
|
||||||
NANO_RECEIVER_C518,
|
NANO_RECEIVER_C518,
|
||||||
|
|
|
@ -20,12 +20,10 @@
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
from . import hidpp10 as _hidpp10
|
|
||||||
from .common import NamedInts as _NamedInts
|
from .common import NamedInts as _NamedInts
|
||||||
|
from .hidpp10 import REGISTERS as _R, DEVICE_KIND as _DK
|
||||||
from .settings_templates import RegisterSettings as _RS, FeatureSettings as _FS
|
from .settings_templates import RegisterSettings as _RS, FeatureSettings as _FS
|
||||||
|
|
||||||
_R = _hidpp10.REGISTERS
|
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -41,10 +39,11 @@ def _D(name, codename=None, kind=None, wpid=None, protocol=None, registers=None,
|
||||||
assert name
|
assert name
|
||||||
|
|
||||||
if kind is None:
|
if kind is None:
|
||||||
kind = (_hidpp10.DEVICE_KIND.mouse if 'Mouse' in name
|
kind = (_DK.mouse if 'Mouse' in name
|
||||||
else _hidpp10.DEVICE_KIND.keyboard if 'Keyboard' in name
|
else _DK.keyboard if 'Keyboard' in name
|
||||||
else _hidpp10.DEVICE_KIND.touchpad if 'Touchpad' in name
|
else _DK.numpad if 'Number Pad' in name
|
||||||
else _hidpp10.DEVICE_KIND.trackball if 'Trackball' in name
|
else _DK.touchpad if 'Touchpad' in name
|
||||||
|
else _DK.trackball if 'Trackball' in name
|
||||||
else None)
|
else None)
|
||||||
assert kind is not None, 'descriptor for %s does not have kind set' % name
|
assert kind is not None, 'descriptor for %s does not have kind set' % name
|
||||||
|
|
||||||
|
@ -64,12 +63,12 @@ def _D(name, codename=None, kind=None, wpid=None, protocol=None, registers=None,
|
||||||
if wpid:
|
if wpid:
|
||||||
for w in wpid if isinstance(wpid, tuple) else (wpid, ):
|
for w in wpid if isinstance(wpid, tuple) else (wpid, ):
|
||||||
if protocol > 1.0:
|
if protocol > 1.0:
|
||||||
assert w[0:1] == '4', name + ' has protocol ' + protocol + ', wpid ' + w
|
assert w[0:1] == '4', '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||||
else:
|
else:
|
||||||
if w[0:1] == '1':
|
if w[0:1] == '1':
|
||||||
assert kind == _hidpp10.DEVICE_KIND.mouse, name + ' has protocol ' + protocol + ', wpid ' + w
|
assert kind == _DK.mouse, '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||||
elif w[0:1] == '2':
|
elif w[0:1] == '2':
|
||||||
assert kind == _hidpp10.DEVICE_KIND.keyboard, name + ' has protocol ' + protocol + ', wpid ' + w
|
assert kind in (_DK.keyboard, _DK.numpad), '%s has protocol %0.1f, wpid %s' % (name, protocol, w)
|
||||||
|
|
||||||
device_descriptor = _DeviceDescriptor(name=name, kind=kind,
|
device_descriptor = _DeviceDescriptor(name=name, kind=kind,
|
||||||
wpid=wpid, codename=codename, protocol=protocol,
|
wpid=wpid, codename=codename, protocol=protocol,
|
||||||
|
@ -144,10 +143,16 @@ _PERFORMANCE_MX_DPIS = _NamedInts.range(0x81, 0x8F, lambda x: str((x - 0x80) * 1
|
||||||
# Keyboards
|
# Keyboards
|
||||||
|
|
||||||
_D('Wireless Keyboard K230', protocol=2.0, wpid='400D')
|
_D('Wireless Keyboard K230', protocol=2.0, wpid='400D')
|
||||||
_D('Wireless Keyboard K270')
|
_D('Wireless Keyboard K270', protocol=1.0,
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
_D('Wireless Keyboard MK330')
|
_D('Wireless Keyboard MK330')
|
||||||
_D('Wireless Keyboard K340')
|
_D('Wireless Compact Keyboard K340', protocol=1.0, wpid='2007',
|
||||||
_D('Wireless Keyboard K350', wpid='200A')
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('Wireless Wave Keyboard K350', protocol=1.0, wpid='200A',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
_D('Wireless Keyboard K360', protocol=2.0, wpid='4004',
|
_D('Wireless Keyboard K360', protocol=2.0, wpid='4004',
|
||||||
settings=[
|
settings=[
|
||||||
_FS.fn_swap()
|
_FS.fn_swap()
|
||||||
|
@ -158,7 +163,15 @@ _D('Wireless Touch Keyboard K400', protocol=2.0, wpid=('400E', '4024'),
|
||||||
_FS.fn_swap()
|
_FS.fn_swap()
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
_D('Wireless Keyboard MK520')
|
_D('Wireless Keyboard K520', protocol=1.0, wpid='2011',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
settings=[
|
||||||
|
_RS.fn_swap(),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
_D('Number Pad N545', protocol=1.0, wpid='2006',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
_D('Wireless Keyboard MK550')
|
_D('Wireless Keyboard MK550')
|
||||||
_D('Wireless Keyboard MK700', protocol=1.0, wpid='2008',
|
_D('Wireless Keyboard MK700', protocol=1.0, wpid='2008',
|
||||||
registers=(_R.battery_status, ),
|
registers=(_R.battery_status, ),
|
||||||
|
@ -192,11 +205,16 @@ _D('Wireless Mouse M305', protocol=1.0, wpid='101F',
|
||||||
_RS.side_scroll(),
|
_RS.side_scroll(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
_D('Wireless Mouse M310')
|
_D('Wireless Mouse M310', protocol=1.0, wpid='1024',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
_D('Wireless Mouse M315')
|
_D('Wireless Mouse M315')
|
||||||
_D('Wireless Mouse M317')
|
_D('Wireless Mouse M317')
|
||||||
_D('Wireless Mouse M325')
|
_D('Wireless Mouse M325')
|
||||||
_D('Wireless Mouse M345', protocol=2.0, wpid='4017')
|
_D('Wireless Mouse M345', protocol=2.0, wpid='4017')
|
||||||
|
_D('Wireless Mouse M350', protocol=1.0, wpid='101C',
|
||||||
|
registers=(_R.battery_charge, ),
|
||||||
|
)
|
||||||
_D('Wireless Mouse M505', codename='M505/B605', protocol=1.0, wpid='101D',
|
_D('Wireless Mouse M505', codename='M505/B605', protocol=1.0, wpid='101D',
|
||||||
registers=(_R.battery_charge, ),
|
registers=(_R.battery_charge, ),
|
||||||
settings=[
|
settings=[
|
||||||
|
@ -223,7 +241,7 @@ _D('Marathon Mouse M705', protocol=1.0, wpid='101B',
|
||||||
)
|
)
|
||||||
_D('Zone Touch Mouse T400')
|
_D('Zone Touch Mouse T400')
|
||||||
_D('Touch Mouse T620', protocol=2.0)
|
_D('Touch Mouse T620', protocol=2.0)
|
||||||
_D('Logitech Cube', kind=_hidpp10.DEVICE_KIND.mouse, protocol=2.0)
|
_D('Logitech Cube', kind=_DK.mouse, protocol=2.0)
|
||||||
_D('Anywhere Mouse MX', codename='Anywhere MX', protocol=1.0, wpid='1017',
|
_D('Anywhere Mouse MX', codename='Anywhere MX', protocol=1.0, wpid='1017',
|
||||||
registers=(_R.battery_charge, ),
|
registers=(_R.battery_charge, ),
|
||||||
settings=[
|
settings=[
|
||||||
|
@ -240,6 +258,13 @@ _D('Performance Mouse MX', codename='Performance MX', protocol=1.0, wpid='101A',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_D('G7 Cordless Laser Mouse', codename='G7', protocol=1.0, wpid='1002',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('G700 Gaming Mouse', codename='G700', protocol=1.0, wpid='1023',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
|
||||||
# Trackballs
|
# Trackballs
|
||||||
|
|
||||||
_D('Wireless Trackball M570')
|
_D('Wireless Trackball M570')
|
||||||
|
@ -254,7 +279,7 @@ _D('Wireless Touchpad', codename='Wireless Touch', protocol=2.0, wpid='4011')
|
||||||
# A wpid is necessary to properly identify them.
|
# A wpid is necessary to properly identify them.
|
||||||
#
|
#
|
||||||
|
|
||||||
_D('VX Nano Cordless Laser Mouse', codename='VX Nano', protocol=1.0, wpid='100F',
|
_D('VX Nano Cordless Laser Mouse', codename='VX Nano', protocol=1.0, wpid=('100B', '100F'),
|
||||||
registers=(_R.battery_charge, ),
|
registers=(_R.battery_charge, ),
|
||||||
settings=[
|
settings=[
|
||||||
_RS.smooth_scroll(),
|
_RS.smooth_scroll(),
|
||||||
|
@ -271,3 +296,34 @@ _D('V550 Nano Cordless Laser Mouse', codename='V550 Nano', protocol=1.0, wpid='1
|
||||||
_RS.side_scroll(),
|
_RS.side_scroll(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Mini receiver mice
|
||||||
|
|
||||||
|
_D('MX610 Laser Cordless Mouse', codename='MX610', protocol=1.0, wpid='1001',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('MX620 Laser Cordless Mouse', codename='MX620', protocol=1.0, wpid=('100A', '1016'),
|
||||||
|
registers=(_R.battery_charge, ),
|
||||||
|
)
|
||||||
|
_D('MX610 Left-Handled Mouse', codename='MX610L', protocol=1.0, wpid='1004',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('V400 Laser Cordless Mouse', codename='V400', protocol=1.0, wpid='1003',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('V450 Laser Cordless Mouse', codename='V450', protocol=1.0, wpid='1005',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
_D('VX Revolution', codename='VX Revolution', kind=_DK.mouse, protocol=1.0, wpid=('1006', '100D'),
|
||||||
|
registers=(_R.battery_charge, ),
|
||||||
|
)
|
||||||
|
_D('MX Air', codename='MX Air', protocol=1.0, kind=_DK.mouse, wpid=('1007', '100E'),
|
||||||
|
registers=(_R.battery_charge, ),
|
||||||
|
)
|
||||||
|
_D('MX Revolution', codename='MX Revolution', protocol=1.0, kind=_DK.mouse, wpid=('1008', '100C'),
|
||||||
|
registers=(_R.battery_charge, ),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Some exotics...
|
||||||
|
|
||||||
|
_D('Fujitsu Sonic Mouse', codename='Sonic', protocol=1.0, wpid='1029')
|
||||||
|
|
|
@ -147,7 +147,7 @@ def _process_hidpp10_notification(device, status, n):
|
||||||
device.status = None
|
device.status = None
|
||||||
if device.number in device.receiver:
|
if device.number in device.receiver:
|
||||||
del device.receiver[device.number]
|
del device.receiver[device.number]
|
||||||
status.changed(active=False, alert=_ALERT.ALL, reason='unpaired')
|
status.changed(active=False, alert=_ALERT.ALL, reason=_("unpaired"))
|
||||||
else:
|
else:
|
||||||
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -140,13 +140,9 @@ class DeviceStatus(dict):
|
||||||
self.updated = 0
|
self.updated = 0
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
def _item(name, format):
|
|
||||||
value = self.get(name)
|
|
||||||
if value is not None:
|
|
||||||
return format % value
|
|
||||||
|
|
||||||
def _items():
|
def _items():
|
||||||
# TODO properly string approximative battery levels
|
comma = False
|
||||||
|
|
||||||
battery_level = self.get(KEYS.BATTERY_LEVEL)
|
battery_level = self.get(KEYS.BATTERY_LEVEL)
|
||||||
if battery_level is not None:
|
if battery_level is not None:
|
||||||
if isinstance(battery_level, _NamedInt):
|
if isinstance(battery_level, _NamedInt):
|
||||||
|
@ -154,20 +150,24 @@ class DeviceStatus(dict):
|
||||||
else:
|
else:
|
||||||
yield _("Battery") + ': ' + ('%d%%' % battery_level)
|
yield _("Battery") + ': ' + ('%d%%' % battery_level)
|
||||||
|
|
||||||
battery_status = _item(KEYS.BATTERY_STATUS, ' (%s)')
|
battery_status = self.get(KEYS.BATTERY_STATUS)
|
||||||
if battery_status:
|
if battery_status is not None:
|
||||||
yield battery_status
|
yield ' (%s)' % _(str(battery_status))
|
||||||
|
|
||||||
light_level = _item(KEYS.LIGHT_LEVEL, _("Lighting") + ': %d ' + _("lux"))
|
comma = True
|
||||||
if light_level:
|
|
||||||
if battery_level:
|
light_level = self.get(KEYS.LIGHT_LEVEL)
|
||||||
yield ', '
|
if light_level is not None:
|
||||||
yield light_level
|
if comma: yield ', '
|
||||||
|
yield _("Lighting") + (': %d ' % light_level) + _("lux")
|
||||||
|
|
||||||
return ''.join(i for i in _items())
|
return ''.join(i for i in _items())
|
||||||
|
|
||||||
__unicode__ = __str__
|
__unicode__ = __str__
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '{' + ', '.join('\'%s\': %r' % (k, v) for k, v in self.items()) + '}'
|
||||||
|
|
||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return bool(self._active)
|
return bool(self._active)
|
||||||
__nonzero__ = __bool__
|
__nonzero__ = __bool__
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
from logging import getLogger, DEBUG as _DEBUG
|
||||||
|
_log = getLogger(__name__)
|
||||||
|
del getLogger
|
||||||
|
|
||||||
|
from threading import Thread as _Thread
|
||||||
|
|
||||||
|
try:
|
||||||
|
from Queue import Queue as _Queue
|
||||||
|
except ImportError:
|
||||||
|
from queue import Queue as _Queue
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
class TaskRunner(_Thread):
|
||||||
|
def __init__(self, name):
|
||||||
|
super(TaskRunner, self).__init__(name=name)
|
||||||
|
self.daemon = True
|
||||||
|
self.queue = _Queue(16)
|
||||||
|
self.alive = False
|
||||||
|
|
||||||
|
def __call__(self, function, *args, **kwargs):
|
||||||
|
task = (function, args, kwargs)
|
||||||
|
self.queue.put(task)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.alive = False
|
||||||
|
self.queue.put(None)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.alive = True
|
||||||
|
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("started")
|
||||||
|
|
||||||
|
while self.alive:
|
||||||
|
task = self.queue.get()
|
||||||
|
if task:
|
||||||
|
function, args, kwargs = task
|
||||||
|
assert function
|
||||||
|
try:
|
||||||
|
function(*args, **kwargs)
|
||||||
|
except:
|
||||||
|
_log.exception("calling %s", function)
|
||||||
|
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("stopped")
|
|
@ -1,434 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- python-mode -*-
|
|
||||||
# -*- coding: UTF-8 -*-
|
|
||||||
|
|
||||||
## Copyright (C) 2012-2013 Daniel Pavel
|
|
||||||
##
|
|
||||||
## This program is free software; you can redistribute it and/or modify
|
|
||||||
## it under the terms of the GNU General Public License as published by
|
|
||||||
## the Free Software Foundation; either version 2 of the License, or
|
|
||||||
## (at your option) any later version.
|
|
||||||
##
|
|
||||||
## This program is distributed in the hope that it will be useful,
|
|
||||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
## GNU General Public License for more details.
|
|
||||||
##
|
|
||||||
## You should have received a copy of the GNU General Public License along
|
|
||||||
## with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import logging
|
|
||||||
|
|
||||||
|
|
||||||
NAME = 'solaar-cli'
|
|
||||||
from solaar import __version__
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def _fail(text):
|
|
||||||
if sys.exc_info()[0]:
|
|
||||||
logging.exception(text)
|
|
||||||
sys.exit("%s: error: %s" % (NAME, text))
|
|
||||||
|
|
||||||
|
|
||||||
def _require(module, os_package):
|
|
||||||
try:
|
|
||||||
__import__(module)
|
|
||||||
except ImportError:
|
|
||||||
_fail("missing required package '%s'" % os_package)
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def _receiver(dev_path=None):
|
|
||||||
from logitech_receiver import Receiver
|
|
||||||
from logitech_receiver.base import receivers
|
|
||||||
for dev_info in receivers():
|
|
||||||
if dev_path is not None and dev_path != dev_info.path:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
r = Receiver.open(dev_info)
|
|
||||||
if r:
|
|
||||||
return r
|
|
||||||
except Exception as e:
|
|
||||||
_fail(str(e))
|
|
||||||
return r
|
|
||||||
_fail("Logitech receiver not found")
|
|
||||||
|
|
||||||
|
|
||||||
def _find_device(receiver, name, may_be_receiver=False):
|
|
||||||
if len(name) == 1:
|
|
||||||
try:
|
|
||||||
number = int(name)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if number < 1 or number > receiver.max_devices:
|
|
||||||
_fail("%s (%s) supports device numbers 1 to %d" % (receiver.name, receiver.path, receiver.max_devices))
|
|
||||||
dev = receiver[number]
|
|
||||||
if dev is None:
|
|
||||||
_fail("no paired device with number %s" % number)
|
|
||||||
return dev
|
|
||||||
|
|
||||||
if len(name) < 3:
|
|
||||||
_fail("need at least 3 characters to match a device")
|
|
||||||
|
|
||||||
name = name.lower()
|
|
||||||
if may_be_receiver and ('receiver'.startswith(name) or name == receiver.serial.lower()):
|
|
||||||
return receiver
|
|
||||||
|
|
||||||
for dev in receiver:
|
|
||||||
if (name == dev.serial.lower() or
|
|
||||||
name == dev.codename.lower() or
|
|
||||||
name == str(dev.kind).lower() or
|
|
||||||
name in dev.name.lower()):
|
|
||||||
return dev
|
|
||||||
|
|
||||||
_fail("no device found matching '%s'" % name)
|
|
||||||
|
|
||||||
|
|
||||||
def _print_receiver(receiver, verbose=False):
|
|
||||||
paired_count = receiver.count()
|
|
||||||
if not verbose:
|
|
||||||
print ("Unifying Receiver [%s:%s] with %d devices" % (receiver.path, receiver.serial, paired_count))
|
|
||||||
return
|
|
||||||
|
|
||||||
print ("Unifying Receiver")
|
|
||||||
print (" Device path :", receiver.path)
|
|
||||||
print (" USB id : 046d:%s" % receiver.product_id)
|
|
||||||
print (" Serial :", receiver.serial)
|
|
||||||
for f in receiver.firmware:
|
|
||||||
print (" %-11s: %s" % (f.kind, f.version))
|
|
||||||
|
|
||||||
print (" Has", paired_count, "paired device(s) out of a maximum of", receiver.max_devices, ".")
|
|
||||||
|
|
||||||
from logitech_receiver import hidpp10
|
|
||||||
notification_flags = hidpp10.get_notification_flags(receiver)
|
|
||||||
if notification_flags is not None:
|
|
||||||
if notification_flags:
|
|
||||||
notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
|
||||||
print (" Notifications: 0x%06X = %s" % (notification_flags, ', '.join(notification_names)))
|
|
||||||
else:
|
|
||||||
print (" Notifications: (none)")
|
|
||||||
|
|
||||||
activity = receiver.read_register(hidpp10.REGISTERS.devices_activity)
|
|
||||||
if activity:
|
|
||||||
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
|
|
||||||
activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0)
|
|
||||||
print (" Device activity counters:", activity_text or '(empty)')
|
|
||||||
|
|
||||||
|
|
||||||
def _print_device(dev, verbose=False):
|
|
||||||
assert dev
|
|
||||||
state = '' if dev.ping() else 'offline'
|
|
||||||
|
|
||||||
if not verbose:
|
|
||||||
print ("%d: %s [%s:%s]" % (dev.number, dev.name, dev.codename, dev.serial), state)
|
|
||||||
return
|
|
||||||
|
|
||||||
print ("%d: %s" % (dev.number, dev.name))
|
|
||||||
print (" Codename :", dev.codename)
|
|
||||||
print (" Kind :", dev.kind)
|
|
||||||
print (" Wireless PID :", dev.wpid)
|
|
||||||
if dev.protocol:
|
|
||||||
print (" Protocol : HID++ %1.1f" % dev.protocol)
|
|
||||||
else:
|
|
||||||
print (" Protocol : unknown (device is offline)")
|
|
||||||
print (" Polling rate :", dev.polling_rate, "ms")
|
|
||||||
print (" Serial number:", dev.serial)
|
|
||||||
for fw in dev.firmware:
|
|
||||||
print (" %11s:" % fw.kind, (fw.name + ' ' + fw.version).strip())
|
|
||||||
|
|
||||||
if dev.power_switch_location:
|
|
||||||
print (" The power switch is located on the %s." % dev.power_switch_location)
|
|
||||||
|
|
||||||
from logitech_receiver import hidpp10, hidpp20, special_keys
|
|
||||||
|
|
||||||
if dev.online:
|
|
||||||
notification_flags = hidpp10.get_notification_flags(dev)
|
|
||||||
if notification_flags is not None:
|
|
||||||
if notification_flags:
|
|
||||||
notification_names = hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
|
||||||
print (" Notifications: 0x%06X = %s." % (notification_flags, ', '.join(notification_names)))
|
|
||||||
else:
|
|
||||||
print (" Notifications: (none).")
|
|
||||||
|
|
||||||
if dev.online:
|
|
||||||
if dev.features:
|
|
||||||
print (" Supports %d HID++ 2.0 features:" % len(dev.features))
|
|
||||||
for index, feature in enumerate(dev.features):
|
|
||||||
feature = dev.features[index]
|
|
||||||
flags = dev.request(0x0000, feature.bytes(2))
|
|
||||||
flags = 0 if flags is None else ord(flags[1:2])
|
|
||||||
flags = hidpp20.FEATURE_FLAG.flag_names(flags)
|
|
||||||
print (" %2d: %-22s {%04X} %s" % (index, feature, feature, ', '.join(flags)))
|
|
||||||
|
|
||||||
if dev.online:
|
|
||||||
if dev.keys:
|
|
||||||
print (" Has %d reprogrammable keys:" % len(dev.keys))
|
|
||||||
for k in dev.keys:
|
|
||||||
flags = special_keys.KEY_FLAG.flag_names(k.flags)
|
|
||||||
print (" %2d: %-26s => %-27s %s" % (k.index, k.key, k.task, ', '.join(flags)))
|
|
||||||
|
|
||||||
if dev.online:
|
|
||||||
battery = hidpp20.get_battery(dev)
|
|
||||||
if battery is None:
|
|
||||||
battery = hidpp10.get_battery(dev)
|
|
||||||
if battery is not None:
|
|
||||||
from logitech_receiver.common import NamedInt as _NamedInt
|
|
||||||
level, status = battery
|
|
||||||
if isinstance(level, _NamedInt):
|
|
||||||
text = str(level)
|
|
||||||
else:
|
|
||||||
text = '%d%%' % level
|
|
||||||
print (" Battery: %s, %s," % (text, status))
|
|
||||||
else:
|
|
||||||
print (" Battery status unavailable.")
|
|
||||||
else:
|
|
||||||
print (" Battery status is unknown (device is offline).")
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def show_devices(receiver, args):
|
|
||||||
if args.device == 'all':
|
|
||||||
_print_receiver(receiver, args.verbose)
|
|
||||||
for dev in receiver:
|
|
||||||
if args.verbose:
|
|
||||||
print ("")
|
|
||||||
_print_device(dev, args.verbose)
|
|
||||||
else:
|
|
||||||
dev = _find_device(receiver, args.device, True)
|
|
||||||
if dev is receiver:
|
|
||||||
_print_receiver(receiver, args.verbose)
|
|
||||||
else:
|
|
||||||
_print_device(dev, args.verbose)
|
|
||||||
|
|
||||||
|
|
||||||
def pair_device(receiver, args):
|
|
||||||
# get all current devices
|
|
||||||
known_devices = [dev.number for dev in receiver]
|
|
||||||
|
|
||||||
from logitech_receiver import base, hidpp10, status, notifications
|
|
||||||
receiver.status = status.ReceiverStatus(receiver, lambda *args, **kwargs: None)
|
|
||||||
|
|
||||||
# check if it's necessary to set the notification flags
|
|
||||||
old_notification_flags = hidpp10.get_notification_flags(receiver) or 0
|
|
||||||
if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless):
|
|
||||||
hidpp10.set_notification_flags(receiver, old_notification_flags | hidpp10.NOTIFICATION_FLAG.wireless)
|
|
||||||
|
|
||||||
class HandleWithNotificationHook(int):
|
|
||||||
def notifications_hook(self, n):
|
|
||||||
assert n
|
|
||||||
if n.devnumber == 0xFF:
|
|
||||||
notifications.process(receiver, n)
|
|
||||||
elif n.sub_id == 0x41 and n.address == 0x04:
|
|
||||||
if n.devnumber not in known_devices:
|
|
||||||
receiver.status.new_device = receiver[n.devnumber]
|
|
||||||
|
|
||||||
timeout = 20 # seconds
|
|
||||||
receiver.handle = HandleWithNotificationHook(receiver.handle)
|
|
||||||
receiver.set_lock(False, timeout=timeout)
|
|
||||||
print ("Pairing: turn your new device on (timing out in", timeout, "seconds).")
|
|
||||||
|
|
||||||
# the lock-open notification may come slightly later, wait for it a bit
|
|
||||||
from time import time as timestamp
|
|
||||||
pairing_start = timestamp()
|
|
||||||
patience = 5 # seconds
|
|
||||||
|
|
||||||
while receiver.status.lock_open or timestamp() - pairing_start < patience:
|
|
||||||
n = base.read(receiver.handle)
|
|
||||||
if n:
|
|
||||||
n = base.make_notification(*n)
|
|
||||||
if n:
|
|
||||||
receiver.handle.notifications_hook(n)
|
|
||||||
|
|
||||||
if not (old_notification_flags & hidpp10.NOTIFICATION_FLAG.wireless):
|
|
||||||
# only clear the flags if they weren't set before, otherwise a
|
|
||||||
# concurrently running Solaar app might stop working properly
|
|
||||||
hidpp10.set_notification_flags(receiver, old_notification_flags)
|
|
||||||
|
|
||||||
if receiver.status.new_device:
|
|
||||||
dev = receiver.status.new_device
|
|
||||||
print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial))
|
|
||||||
else:
|
|
||||||
error = receiver.status[status.KEYS.ERROR] or 'no device detected?'
|
|
||||||
_fail(error)
|
|
||||||
|
|
||||||
|
|
||||||
def unpair_device(receiver, args):
|
|
||||||
dev = _find_device(receiver, args.device)
|
|
||||||
|
|
||||||
# query these now, it's last chance to get them
|
|
||||||
number, name, codename, serial = dev.number, dev.name, dev.codename, dev.serial
|
|
||||||
try:
|
|
||||||
del receiver[number]
|
|
||||||
print ("Unpaired %d: %s [%s:%s]" % (number, name, codename, serial))
|
|
||||||
except Exception as e:
|
|
||||||
_fail("failed to unpair device %s: %s" % (dev.name, e))
|
|
||||||
|
|
||||||
|
|
||||||
def config_device(receiver, args):
|
|
||||||
dev = _find_device(receiver, args.device)
|
|
||||||
# if dev is receiver:
|
|
||||||
# _fail("no settings for the receiver")
|
|
||||||
|
|
||||||
if not dev.settings:
|
|
||||||
_fail("no settings for %s" % dev.name)
|
|
||||||
|
|
||||||
if not args.setting:
|
|
||||||
print ("[%s:%s]" % (dev.serial, dev.kind))
|
|
||||||
print ("#", dev.name)
|
|
||||||
for s in dev.settings:
|
|
||||||
print ("")
|
|
||||||
print ("# %s" % s.label)
|
|
||||||
if s.choices:
|
|
||||||
print ("# possible values: one of [", ', '.join(str(v) for v in s.choices), "], or higher/lower/highest/max/lowest/min")
|
|
||||||
else:
|
|
||||||
print ("# possible values: on/true/t/yes/y/1 or off/false/f/no/n/0")
|
|
||||||
value = s.read()
|
|
||||||
if value is None:
|
|
||||||
print ("# %s = ? (failed to read from device)" % s.name)
|
|
||||||
else:
|
|
||||||
print (s.name, "=", value)
|
|
||||||
return
|
|
||||||
|
|
||||||
setting = None
|
|
||||||
for s in dev.settings:
|
|
||||||
if args.setting.lower() == s.name.lower():
|
|
||||||
setting = s
|
|
||||||
break
|
|
||||||
if setting is None:
|
|
||||||
_fail("no setting '%s' for %s" % (args.setting, dev.name))
|
|
||||||
|
|
||||||
if args.value is None:
|
|
||||||
result = setting.read()
|
|
||||||
if result is None:
|
|
||||||
_fail("failed to read '%s'" % setting.name)
|
|
||||||
print ("%s = %s" % (setting.name, setting.read()))
|
|
||||||
return
|
|
||||||
|
|
||||||
from logitech_receiver import settings as _settings
|
|
||||||
|
|
||||||
if setting.kind == _settings.KIND.toggle:
|
|
||||||
value = args.value
|
|
||||||
try:
|
|
||||||
value = bool(int(value))
|
|
||||||
except:
|
|
||||||
if value.lower() in ('1', 'true', 'yes', 'on', 't', 'y'):
|
|
||||||
value = True
|
|
||||||
elif value.lower() in ('0', 'false', 'no', 'off', 'f', 'n'):
|
|
||||||
value = False
|
|
||||||
else:
|
|
||||||
_fail("don't know how to interpret '%s' as boolean" % value)
|
|
||||||
|
|
||||||
elif setting.choices:
|
|
||||||
value = args.value.lower()
|
|
||||||
|
|
||||||
if value in ('higher', 'lower'):
|
|
||||||
old_value = setting.read()
|
|
||||||
if old_value is None:
|
|
||||||
_fail("could not read current value of '%s'" % setting.name)
|
|
||||||
|
|
||||||
if value == 'lower':
|
|
||||||
lower_values = setting.choices[:old_value]
|
|
||||||
value = lower_values[-1] if lower_values else setting.choices[:][0]
|
|
||||||
elif value == 'higher':
|
|
||||||
higher_values = setting.choices[old_value + 1:]
|
|
||||||
value = higher_values[0] if higher_values else setting.choices[:][-1]
|
|
||||||
elif value in ('highest', 'max'):
|
|
||||||
value = setting.choices[:][-1]
|
|
||||||
elif value in ('lowest', 'min'):
|
|
||||||
value = setting.choices[:][0]
|
|
||||||
elif value not in setting.choices:
|
|
||||||
_fail("possible values for '%s' are: [%s]" % (setting.name, ', '.join(str(v) for v in setting.choices)))
|
|
||||||
value = setting.choices[value]
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise NotImplemented
|
|
||||||
|
|
||||||
result = setting.write(value)
|
|
||||||
if result is None:
|
|
||||||
_fail("failed to set '%s' = '%s' [%r]" % (setting.name, value, value))
|
|
||||||
print ("%s = %s" % (setting.name, result))
|
|
||||||
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
def _parse_arguments():
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
arg_parser = ArgumentParser(prog=NAME.lower())
|
|
||||||
arg_parser.add_argument('-d', '--debug', action='count', default=0,
|
|
||||||
help='print logging messages, for debugging purposes (may be repeated for extra verbosity)')
|
|
||||||
arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
|
|
||||||
arg_parser.add_argument('-D', '--hidraw', action='store', dest='hidraw_path', metavar='PATH',
|
|
||||||
help='unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2')
|
|
||||||
|
|
||||||
subparsers = arg_parser.add_subparsers(title='commands')
|
|
||||||
|
|
||||||
sp = subparsers.add_parser('show', help='show information about paired devices')
|
|
||||||
sp.add_argument('device', nargs='?', default='all',
|
|
||||||
help='device to show information about; may be a device number (1..6), a device serial, '
|
|
||||||
'at least 3 characters of a device\'s name, "receiver", or "all" (the default)')
|
|
||||||
sp.add_argument('-v', '--verbose', action='store_true',
|
|
||||||
help='print all available information about the inspected device(s)')
|
|
||||||
sp.set_defaults(cmd=show_devices)
|
|
||||||
|
|
||||||
sp = subparsers.add_parser('config', help='read/write device-specific settings',
|
|
||||||
epilog='Please note that configuration only works on active devices.')
|
|
||||||
sp.add_argument('device',
|
|
||||||
help='device to configure; may be a device number (1..6), a device serial, '
|
|
||||||
'or at least 3 characters of a device\'s name')
|
|
||||||
sp.add_argument('setting', nargs='?',
|
|
||||||
help='device-specific setting; leave empty to list available settings')
|
|
||||||
sp.add_argument('value', nargs='?',
|
|
||||||
help='new value for the setting')
|
|
||||||
sp.set_defaults(cmd=config_device)
|
|
||||||
|
|
||||||
sp = subparsers.add_parser('pair', help='pair a new device',
|
|
||||||
epilog='The Logitech Unifying Receiver supports up to 6 paired devices at the same time.')
|
|
||||||
sp.set_defaults(cmd=pair_device)
|
|
||||||
|
|
||||||
sp = subparsers.add_parser('unpair', help='unpair a device')
|
|
||||||
sp.add_argument('device',
|
|
||||||
help='device to unpair; may be a device number (1..6), a device serial, '
|
|
||||||
'or at least 3 characters of a device\'s name.')
|
|
||||||
sp.set_defaults(cmd=unpair_device)
|
|
||||||
|
|
||||||
args = arg_parser.parse_args()
|
|
||||||
|
|
||||||
# Python 3 has an undocumented 'feature' that breaks parsing empty args
|
|
||||||
# http://bugs.python.org/issue16308
|
|
||||||
if not 'cmd' in args:
|
|
||||||
arg_parser.print_usage(sys.stderr)
|
|
||||||
sys.stderr.write('%s: error: too few arguments\n' % NAME.lower())
|
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
if args.debug > 0:
|
|
||||||
log_level = logging.WARNING - 10 * args.debug
|
|
||||||
log_format='%(asctime)s,%(msecs)03d %(levelname)8s %(name)s: %(message)s'
|
|
||||||
logging.basicConfig(level=max(log_level, logging.DEBUG), format=log_format, datefmt='%H:%M:%S')
|
|
||||||
else:
|
|
||||||
logging.root.addHandler(logging.NullHandler())
|
|
||||||
logging.root.setLevel(logging.ERROR)
|
|
||||||
|
|
||||||
return args
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
_require('pyudev', 'python-pyudev')
|
|
||||||
args = _parse_arguments()
|
|
||||||
receiver = _receiver(args.hidraw_path)
|
|
||||||
args.cmd(receiver, args)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
import argparse as _argparse
|
||||||
|
import sys as _sys
|
||||||
|
|
||||||
|
from logging import getLogger, DEBUG as _DEBUG
|
||||||
|
_log = getLogger(__name__)
|
||||||
|
del getLogger
|
||||||
|
|
||||||
|
|
||||||
|
from solaar import NAME
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
def _create_parser():
|
||||||
|
parser = _argparse.ArgumentParser(prog=NAME.lower(), add_help=False,
|
||||||
|
epilog='For details on individual actions, run `%s <action> --help`.' % NAME.lower())
|
||||||
|
subparsers = parser.add_subparsers(title='actions',
|
||||||
|
help='optional action to perform')
|
||||||
|
|
||||||
|
sp = subparsers.add_parser('show', help='show information about devices')
|
||||||
|
sp.add_argument('device', nargs='?', default='all',
|
||||||
|
help='device to show information about; may be a device number (1..6), a serial, '
|
||||||
|
'a substring of a device\'s name, or "all" (the default)')
|
||||||
|
sp.set_defaults(action='show')
|
||||||
|
|
||||||
|
sp = subparsers.add_parser('config', help='read/write device-specific settings',
|
||||||
|
epilog='Please note that configuration only works on active devices.')
|
||||||
|
sp.add_argument('device',
|
||||||
|
help='device to configure; may be a device number (1..6), a device serial, '
|
||||||
|
'or at least 3 characters of a device\'s name')
|
||||||
|
sp.add_argument('setting', nargs='?',
|
||||||
|
help='device-specific setting; leave empty to list available settings')
|
||||||
|
sp.add_argument('value', nargs='?',
|
||||||
|
help='new value for the setting')
|
||||||
|
sp.set_defaults(action='config')
|
||||||
|
|
||||||
|
sp = subparsers.add_parser('pair', help='pair a new device',
|
||||||
|
epilog='The Logitech Unifying Receiver supports up to 6 paired devices at the same time.')
|
||||||
|
sp.add_argument('receiver', nargs='?',
|
||||||
|
help='select a certain receiver when more than one is present')
|
||||||
|
sp.set_defaults(action='pair')
|
||||||
|
|
||||||
|
sp = subparsers.add_parser('unpair', help='unpair a device')
|
||||||
|
sp.add_argument('device',
|
||||||
|
help='device to unpair; may be a device number (1..6), a serial, '
|
||||||
|
'or a substring of a device\'s name.')
|
||||||
|
sp.set_defaults(action='unpair')
|
||||||
|
|
||||||
|
return parser, subparsers.choices
|
||||||
|
|
||||||
|
|
||||||
|
_cli_parser, actions = _create_parser()
|
||||||
|
|
||||||
|
|
||||||
|
def _receivers():
|
||||||
|
from logitech_receiver import Receiver
|
||||||
|
from logitech_receiver.base import receivers
|
||||||
|
for dev_info in receivers():
|
||||||
|
try:
|
||||||
|
r = Receiver.open(dev_info)
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("[%s] => %s", dev_info.path, r)
|
||||||
|
if r:
|
||||||
|
yield r
|
||||||
|
except Exception as e:
|
||||||
|
_log.exception('opening ' + str(dev_info))
|
||||||
|
_sys.exit("%s: error: %s" % (NAME, str(e)))
|
||||||
|
|
||||||
|
|
||||||
|
def _find_receiver(receivers, name):
|
||||||
|
assert receivers
|
||||||
|
assert name
|
||||||
|
|
||||||
|
for r in receivers:
|
||||||
|
if name in r.name.lower() or name == r.serial.lower():
|
||||||
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
def _find_device(receivers, name):
|
||||||
|
assert receivers
|
||||||
|
assert name
|
||||||
|
|
||||||
|
number = None
|
||||||
|
if len(name) == 1:
|
||||||
|
try:
|
||||||
|
number = int(name)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
assert not (number < 0)
|
||||||
|
if number > 6: number = None
|
||||||
|
|
||||||
|
for r in receivers:
|
||||||
|
if number and number <= r.max_devices:
|
||||||
|
dev = r[number]
|
||||||
|
if dev:
|
||||||
|
return dev
|
||||||
|
|
||||||
|
for dev in r:
|
||||||
|
if (name == dev.serial.lower() or
|
||||||
|
name == dev.codename.lower() or
|
||||||
|
name == str(dev.kind).lower() or
|
||||||
|
name in dev.name.lower()):
|
||||||
|
return dev
|
||||||
|
|
||||||
|
raise Exception("no device found matching '%s'" % name)
|
||||||
|
|
||||||
|
|
||||||
|
def run(cli_args=None):
|
||||||
|
if cli_args == 'help':
|
||||||
|
_cli_parser.print_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
if cli_args:
|
||||||
|
action = cli_args[0]
|
||||||
|
args = _cli_parser.parse_args(cli_args)
|
||||||
|
else:
|
||||||
|
args = _cli_parser.parse_args()
|
||||||
|
action = args.action
|
||||||
|
assert action in actions
|
||||||
|
|
||||||
|
try:
|
||||||
|
c = list(_receivers())
|
||||||
|
if not c:
|
||||||
|
raise Exception('Logitech receiver not found')
|
||||||
|
|
||||||
|
from importlib import import_module
|
||||||
|
m = import_module('.' + action, package=__name__)
|
||||||
|
m.run(c, args, _find_receiver, _find_device)
|
||||||
|
except Exception as e:
|
||||||
|
_sys.exit('%s: error: %s' % (NAME.lower(), e))
|
|
@ -0,0 +1,120 @@
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from solaar import configuration as _configuration
|
||||||
|
from logitech_receiver import settings as _settings
|
||||||
|
|
||||||
|
|
||||||
|
def _print_setting(s, verbose=True):
|
||||||
|
print ('#', s.label)
|
||||||
|
if verbose:
|
||||||
|
print ('#', s.description.replace('\n', ' '))
|
||||||
|
if s.kind == _settings.KIND.toggle:
|
||||||
|
print ('# possible values: on/true/t/yes/y/1 or off/false/f/no/n/0')
|
||||||
|
elif s.choices:
|
||||||
|
print ('# possible values: one of [', ', '.join(str(v) for v in s.choices), '], or higher/lower/highest/max/lowest/min')
|
||||||
|
else:
|
||||||
|
# wtf?
|
||||||
|
pass
|
||||||
|
value = s.read(cached=False)
|
||||||
|
if value is None:
|
||||||
|
print (s.name, '= ? (failed to read from device)')
|
||||||
|
else:
|
||||||
|
print (s.name, '= %r' % value)
|
||||||
|
|
||||||
|
|
||||||
|
def run(receivers, args, find_receiver, find_device):
|
||||||
|
assert receivers
|
||||||
|
assert args.device
|
||||||
|
|
||||||
|
device_name = args.device.lower()
|
||||||
|
dev = find_device(receivers, device_name)
|
||||||
|
|
||||||
|
if not dev.ping():
|
||||||
|
raise Exception('%s is offline' % dev.name)
|
||||||
|
|
||||||
|
if not dev.settings:
|
||||||
|
raise Exception('no settings for %s' % dev.name)
|
||||||
|
|
||||||
|
_configuration.attach_to(dev)
|
||||||
|
|
||||||
|
if not args.setting:
|
||||||
|
print (dev.name, '(%s) [%s:%s]' % (dev.codename, dev.wpid, dev.serial))
|
||||||
|
for s in dev.settings:
|
||||||
|
print ('')
|
||||||
|
_print_setting(s)
|
||||||
|
return
|
||||||
|
|
||||||
|
setting_name = args.setting.lower()
|
||||||
|
setting = None
|
||||||
|
for s in dev.settings:
|
||||||
|
if setting_name == s.name.lower():
|
||||||
|
setting = s
|
||||||
|
break
|
||||||
|
if setting is None:
|
||||||
|
raise Exception("no setting '%s' for %s" % (args.setting, dev.name))
|
||||||
|
|
||||||
|
if args.value is None:
|
||||||
|
_print_setting(setting)
|
||||||
|
return
|
||||||
|
|
||||||
|
if setting.kind == _settings.KIND.toggle:
|
||||||
|
value = args.value
|
||||||
|
try:
|
||||||
|
value = bool(int(value))
|
||||||
|
except:
|
||||||
|
if value.lower() in ('true', 'yes', 'on', 't', 'y'):
|
||||||
|
value = True
|
||||||
|
elif value.lower() in ('false', 'no', 'off', 'f', 'n'):
|
||||||
|
value = False
|
||||||
|
else:
|
||||||
|
raise Exception("don't know how to interpret '%s' as boolean" % value)
|
||||||
|
|
||||||
|
elif setting.choices:
|
||||||
|
value = args.value.lower()
|
||||||
|
|
||||||
|
if value in ('higher', 'lower'):
|
||||||
|
old_value = setting.read()
|
||||||
|
if old_value is None:
|
||||||
|
raise Exception("could not read current value of '%s'" % setting.name)
|
||||||
|
|
||||||
|
if value == 'lower':
|
||||||
|
lower_values = setting.choices[:old_value]
|
||||||
|
value = lower_values[-1] if lower_values else setting.choices[:][0]
|
||||||
|
elif value == 'higher':
|
||||||
|
higher_values = setting.choices[old_value + 1:]
|
||||||
|
value = higher_values[0] if higher_values else setting.choices[:][-1]
|
||||||
|
elif value in ('highest', 'max'):
|
||||||
|
value = setting.choices[:][-1]
|
||||||
|
elif value in ('lowest', 'min'):
|
||||||
|
value = setting.choices[:][0]
|
||||||
|
elif value not in setting.choices:
|
||||||
|
raise Exception("possible values for '%s' are: [%s]" % (setting.name, ', '.join(str(v) for v in setting.choices)))
|
||||||
|
value = setting.choices[value]
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise NotImplemented
|
||||||
|
|
||||||
|
result = setting.write(value)
|
||||||
|
if result is None:
|
||||||
|
raise Exception("failed to set '%s' = '%s' [%r]" % (setting.name, value, value))
|
||||||
|
_print_setting(setting, False)
|
|
@ -0,0 +1,91 @@
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from time import time as _timestamp
|
||||||
|
|
||||||
|
from logitech_receiver import (
|
||||||
|
base as _base,
|
||||||
|
hidpp10 as _hidpp10,
|
||||||
|
status as _status,
|
||||||
|
notifications as _notifications,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run(receivers, args, find_receiver, _ignore):
|
||||||
|
assert receivers
|
||||||
|
|
||||||
|
if args.receiver:
|
||||||
|
receiver_name = args.receiver.lower()
|
||||||
|
receiver = find_receiver(receiver_name)
|
||||||
|
if not receiver:
|
||||||
|
raise Exception("no receiver found matching '%s'" % receiver_name)
|
||||||
|
else:
|
||||||
|
receiver = receivers[0]
|
||||||
|
|
||||||
|
assert receiver
|
||||||
|
receiver.status = _status.ReceiverStatus(receiver, lambda *args, **kwargs: None)
|
||||||
|
|
||||||
|
# check if it's necessary to set the notification flags
|
||||||
|
old_notification_flags = _hidpp10.get_notification_flags(receiver) or 0
|
||||||
|
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
|
||||||
|
_hidpp10.set_notification_flags(receiver, old_notification_flags | _hidpp10.NOTIFICATION_FLAG.wireless)
|
||||||
|
|
||||||
|
# get all current devices
|
||||||
|
known_devices = [dev.number for dev in receiver]
|
||||||
|
|
||||||
|
class _HandleWithNotificationHook(int):
|
||||||
|
def notifications_hook(self, n):
|
||||||
|
assert n
|
||||||
|
if n.devnumber == 0xFF:
|
||||||
|
_notifications.process(receiver, n)
|
||||||
|
elif n.sub_id == 0x41 and n.address == 0x04:
|
||||||
|
if n.devnumber not in known_devices:
|
||||||
|
receiver.status.new_device = receiver[n.devnumber]
|
||||||
|
|
||||||
|
timeout = 20 # seconds
|
||||||
|
receiver.handle = _HandleWithNotificationHook(receiver.handle)
|
||||||
|
|
||||||
|
receiver.set_lock(False, timeout=timeout)
|
||||||
|
print ('Pairing: turn your new device on (timing out in', timeout, 'seconds).')
|
||||||
|
|
||||||
|
# the lock-open notification may come slightly later, wait for it a bit
|
||||||
|
pairing_start = _timestamp()
|
||||||
|
patience = 5 # seconds
|
||||||
|
|
||||||
|
while receiver.status.lock_open or _timestamp() - pairing_start < patience:
|
||||||
|
n = _base.read(receiver.handle)
|
||||||
|
if n:
|
||||||
|
n = _base.make_notification(*n)
|
||||||
|
if n:
|
||||||
|
receiver.handle.notifications_hook(n)
|
||||||
|
|
||||||
|
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
|
||||||
|
# only clear the flags if they weren't set before, otherwise a
|
||||||
|
# concurrently running Solaar app might stop working properly
|
||||||
|
_hidpp10.set_notification_flags(receiver, old_notification_flags)
|
||||||
|
|
||||||
|
if receiver.status.new_device:
|
||||||
|
dev = receiver.status.new_device
|
||||||
|
print ('Paired device %d: %s (%s) [%s:%s]' % (dev.number, dev.name, dev.codename, dev.wpid, dev.serial))
|
||||||
|
else:
|
||||||
|
error = receiver.status.get(_status.KEYS.ERROR) or 'no device detected?'
|
||||||
|
raise Exception("pairing failed: %s" % error)
|
|
@ -0,0 +1,146 @@
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
from logitech_receiver import (
|
||||||
|
hidpp10 as _hidpp10,
|
||||||
|
hidpp20 as _hidpp20,
|
||||||
|
special_keys as _special_keys,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _print_receiver(receiver):
|
||||||
|
paired_count = receiver.count()
|
||||||
|
|
||||||
|
print ('Unifying Receiver')
|
||||||
|
print (' Device path :', receiver.path)
|
||||||
|
print (' USB id : 046d:%s' % receiver.product_id)
|
||||||
|
print (' Serial :', receiver.serial)
|
||||||
|
for f in receiver.firmware:
|
||||||
|
print (' %-11s: %s' % (f.kind, f.version))
|
||||||
|
|
||||||
|
print (' Has', paired_count, 'paired device(s) out of a maximum of %d.' % receiver.max_devices)
|
||||||
|
|
||||||
|
notification_flags = _hidpp10.get_notification_flags(receiver)
|
||||||
|
if notification_flags is not None:
|
||||||
|
if notification_flags:
|
||||||
|
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||||
|
print (' Notifications: %s (0x%06X)' % (', '.join(notification_names), notification_flags))
|
||||||
|
else:
|
||||||
|
print (' Notifications: (none)')
|
||||||
|
|
||||||
|
activity = receiver.read_register(_hidpp10.REGISTERS.devices_activity)
|
||||||
|
if activity:
|
||||||
|
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
|
||||||
|
activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0)
|
||||||
|
print (' Device activity counters:', activity_text or '(empty)')
|
||||||
|
|
||||||
|
|
||||||
|
def _print_device(dev):
|
||||||
|
assert dev
|
||||||
|
# check if the device is online
|
||||||
|
dev.ping()
|
||||||
|
|
||||||
|
print (' %d: %s' % (dev.number, dev.name))
|
||||||
|
print (' Codename :', dev.codename)
|
||||||
|
print (' Kind :', dev.kind)
|
||||||
|
print (' Wireless PID :', dev.wpid)
|
||||||
|
if dev.protocol:
|
||||||
|
print (' Protocol : HID++ %1.1f' % dev.protocol)
|
||||||
|
else:
|
||||||
|
print (' Protocol : unknown (device is offline)')
|
||||||
|
if dev.polling_rate:
|
||||||
|
print (' Polling rate :', dev.polling_rate, 'ms (%dHz)' % (1000 // dev.polling_rate))
|
||||||
|
print (' Serial number:', dev.serial)
|
||||||
|
for fw in dev.firmware:
|
||||||
|
print (' %11s:' % fw.kind, (fw.name + ' ' + fw.version).strip())
|
||||||
|
|
||||||
|
if dev.power_switch_location:
|
||||||
|
print (' The power switch is located on the %s.' % dev.power_switch_location)
|
||||||
|
|
||||||
|
if dev.online:
|
||||||
|
notification_flags = _hidpp10.get_notification_flags(dev)
|
||||||
|
if notification_flags is not None:
|
||||||
|
if notification_flags:
|
||||||
|
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||||
|
print (' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags))
|
||||||
|
else:
|
||||||
|
print (' Notifications: (none).')
|
||||||
|
|
||||||
|
if dev.online and dev.features:
|
||||||
|
print (' Supports %d HID++ 2.0 features:' % len(dev.features))
|
||||||
|
for index, feature in enumerate(dev.features):
|
||||||
|
feature = dev.features[index]
|
||||||
|
flags = dev.request(0x0000, feature.bytes(2))
|
||||||
|
flags = 0 if flags is None else ord(flags[1:2])
|
||||||
|
flags = _hidpp20.FEATURE_FLAG.flag_names(flags)
|
||||||
|
print (' %2d: %-22s {%04X} %s' % (index, feature, feature, ', '.join(flags)))
|
||||||
|
|
||||||
|
if dev.online and dev.keys:
|
||||||
|
print (' Has %d reprogrammable keys:' % len(dev.keys))
|
||||||
|
for k in dev.keys:
|
||||||
|
flags = _special_keys.KEY_FLAG.flag_names(k.flags)
|
||||||
|
print (' %2d: %-26s => %-27s %s' % (k.index, k.key, k.task, ', '.join(flags)))
|
||||||
|
|
||||||
|
if dev.online:
|
||||||
|
battery = _hidpp20.get_battery(dev)
|
||||||
|
if battery is None:
|
||||||
|
battery = _hidpp10.get_battery(dev)
|
||||||
|
if battery is not None:
|
||||||
|
from logitech_receiver.common import NamedInt as _NamedInt
|
||||||
|
level, status = battery
|
||||||
|
if isinstance(level, _NamedInt):
|
||||||
|
text = str(level)
|
||||||
|
else:
|
||||||
|
text = '%d%%' % level
|
||||||
|
print (' Battery: %s, %s.' % (text, status))
|
||||||
|
else:
|
||||||
|
print (' Battery status unavailable.')
|
||||||
|
else:
|
||||||
|
print (' Battery: unknown (device is offline).')
|
||||||
|
|
||||||
|
|
||||||
|
def run(receivers, args, find_receiver, find_device):
|
||||||
|
assert receivers
|
||||||
|
assert args.device
|
||||||
|
|
||||||
|
device_name = args.device.lower()
|
||||||
|
|
||||||
|
if device_name == 'all':
|
||||||
|
for r in receivers:
|
||||||
|
_print_receiver(r)
|
||||||
|
count = r.count()
|
||||||
|
for dev in r:
|
||||||
|
print ('')
|
||||||
|
_print_device(dev)
|
||||||
|
count -= 1
|
||||||
|
if count == 0:
|
||||||
|
break
|
||||||
|
return
|
||||||
|
|
||||||
|
dev = find_receiver(receivers, device_name)
|
||||||
|
if dev:
|
||||||
|
_print_receiver(dev)
|
||||||
|
return
|
||||||
|
|
||||||
|
dev = find_device(receivers, device_name)
|
||||||
|
assert dev
|
||||||
|
_print_device(dev)
|
|
@ -0,0 +1,36 @@
|
||||||
|
# -*- python-mode -*-
|
||||||
|
# -*- coding: UTF-8 -*-
|
||||||
|
|
||||||
|
## Copyright (C) 2012-2013 Daniel Pavel
|
||||||
|
##
|
||||||
|
## This program is free software; you can redistribute it and/or modify
|
||||||
|
## it under the terms of the GNU General Public License as published by
|
||||||
|
## the Free Software Foundation; either version 2 of the License, or
|
||||||
|
## (at your option) any later version.
|
||||||
|
##
|
||||||
|
## This program is distributed in the hope that it will be useful,
|
||||||
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
## GNU General Public License for more details.
|
||||||
|
##
|
||||||
|
## You should have received a copy of the GNU General Public License along
|
||||||
|
## with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
|
def run(receivers, args, find_receiver, find_device):
|
||||||
|
assert receivers
|
||||||
|
assert args.device
|
||||||
|
|
||||||
|
device_name = args.device.lower()
|
||||||
|
dev = find_device(receivers, device_name)
|
||||||
|
|
||||||
|
# query these now, it's last chance to get them
|
||||||
|
try:
|
||||||
|
number, codename, wpid, serial = dev.number, dev.codename, dev.wpid, dev.serial
|
||||||
|
del dev.receiver[number]
|
||||||
|
print ('Unpaired %d: %s (%s) [%s:%s]' % (number, dev.name, codename, wpid, serial))
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception('failed to unpair device %s: %s' % (dev.name, e))
|
|
@ -23,6 +23,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
||||||
|
|
||||||
from solaar import __version__, NAME
|
from solaar import __version__, NAME
|
||||||
import solaar.i18n as _i18n
|
import solaar.i18n as _i18n
|
||||||
|
import solaar.cli as _cli
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -40,10 +41,18 @@ def _parse_arguments():
|
||||||
import argparse
|
import argparse
|
||||||
arg_parser = argparse.ArgumentParser(prog=NAME.lower())
|
arg_parser = argparse.ArgumentParser(prog=NAME.lower())
|
||||||
arg_parser.add_argument('-d', '--debug', action='count', default=0,
|
arg_parser.add_argument('-d', '--debug', action='count', default=0,
|
||||||
help="print logging messages, for debugging purposes (may be repeated for extra verbosity)")
|
help='print logging messages, for debugging purposes (may be repeated for extra verbosity)')
|
||||||
arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
|
arg_parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__)
|
||||||
|
arg_parser.add_argument('--help-actions', action='store_true',
|
||||||
|
help='print help for the optional actions')
|
||||||
|
arg_parser.add_argument('action', nargs=argparse.REMAINDER, choices=_cli.actions,
|
||||||
|
help='optional actions to perform')
|
||||||
|
|
||||||
args = arg_parser.parse_args()
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
|
if args.help_actions:
|
||||||
|
return 'help'
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
if args.debug > 0:
|
if args.debug > 0:
|
||||||
log_level = logging.WARNING - 10 * args.debug
|
log_level = logging.WARNING - 10 * args.debug
|
||||||
|
@ -53,34 +62,33 @@ def _parse_arguments():
|
||||||
logging.root.addHandler(logging.NullHandler())
|
logging.root.addHandler(logging.NullHandler())
|
||||||
logging.root.setLevel(logging.ERROR)
|
logging.root.setLevel(logging.ERROR)
|
||||||
|
|
||||||
|
if args.action:
|
||||||
|
return args.action
|
||||||
|
|
||||||
if logging.root.isEnabledFor(logging.INFO):
|
if logging.root.isEnabledFor(logging.INFO):
|
||||||
logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)
|
logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)
|
||||||
|
|
||||||
return args
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
_require('pyudev', 'python-pyudev')
|
_require('pyudev', 'python-pyudev')
|
||||||
_require('gi.repository', 'python-gi')
|
|
||||||
_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
|
|
||||||
_parse_arguments()
|
|
||||||
|
|
||||||
# handle ^C in console
|
# handle ^C in console
|
||||||
import signal
|
import signal
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||||
|
|
||||||
|
cli_action = _parse_arguments()
|
||||||
|
if cli_action:
|
||||||
|
return _cli.run(cli_action)
|
||||||
|
|
||||||
|
_require('gi.repository', 'python-gi')
|
||||||
|
_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import solaar.ui as ui
|
import solaar.ui as ui
|
||||||
ui.init()
|
|
||||||
|
|
||||||
import solaar.listener as listener
|
import solaar.listener as listener
|
||||||
listener.setup_scanner(ui.status_changed, ui.error_dialog)
|
listener.setup_scanner(ui.status_changed, ui.error_dialog)
|
||||||
listener.start_all()
|
|
||||||
|
|
||||||
# main UI event loop
|
# main UI event loop
|
||||||
ui.run_loop()
|
ui.run_loop(listener.start_all, listener.stop_all)
|
||||||
|
|
||||||
listener.stop_all()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
import sys
|
import sys
|
||||||
sys.exit('%s: error: %s' % (NAME.lower(), e))
|
sys.exit('%s: error: %s' % (NAME.lower(), e))
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
|
||||||
from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
|
from logging import getLogger, DEBUG as _DEBUG
|
||||||
_log = getLogger(__name__)
|
_log = getLogger(__name__)
|
||||||
del getLogger
|
del getLogger
|
||||||
|
|
||||||
|
@ -37,27 +37,6 @@ assert Gtk.get_major_version() > 2, 'Solaar requires Gtk 3 python bindings'
|
||||||
|
|
||||||
GLib.threads_init()
|
GLib.threads_init()
|
||||||
|
|
||||||
def _init_application():
|
|
||||||
APP_ID = 'io.github.pwr.solaar'
|
|
||||||
app = Gtk.Application.new(APP_ID, 0)
|
|
||||||
# not sure this is necessary...
|
|
||||||
# app.set_property('register-session', True)
|
|
||||||
registered = app.register(None)
|
|
||||||
dbus_path = app.get_dbus_object_path() if hasattr(app, 'get_dbus_object_path') else APP_ID
|
|
||||||
if _log.isEnabledFor(_INFO):
|
|
||||||
_log.info("application %s, registered %s", dbus_path, registered)
|
|
||||||
# assert registered, "failed to register unique application %s" % app
|
|
||||||
|
|
||||||
# if there is already a running instance, bail out
|
|
||||||
if app.get_is_remote():
|
|
||||||
# pop up the window in the other instance
|
|
||||||
app.activate()
|
|
||||||
raise Exception("already running")
|
|
||||||
|
|
||||||
return app
|
|
||||||
|
|
||||||
application = _init_application()
|
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -72,7 +51,7 @@ def _error_dialog(reason, object):
|
||||||
_("If you've just installed Solaar, try removing the receiver and plugging it back in.")
|
_("If you've just installed Solaar, try removing the receiver and plugging it back in.")
|
||||||
elif reason == 'unpair':
|
elif reason == 'unpair':
|
||||||
title = _("Unpairing failed")
|
title = _("Unpairing failed")
|
||||||
text = _("Failed to unpair %s from %s.") % (object.name, object.receiver.name) + \
|
text = _("Failed to unpair %{device} from %{receiver}.").format(device=object.name, receiver=object.receiver.name) + \
|
||||||
'\n\n' + \
|
'\n\n' + \
|
||||||
_("The receiver returned an error, with no further details.")
|
_("The receiver returned an error, with no further details.")
|
||||||
else:
|
else:
|
||||||
|
@ -92,40 +71,13 @@ def error_dialog(reason, object):
|
||||||
GLib.idle_add(_error_dialog, reason, object)
|
GLib.idle_add(_error_dialog, reason, object)
|
||||||
|
|
||||||
#
|
#
|
||||||
# A separate thread is used to read/write from the device
|
#
|
||||||
# so as not to block the main (GUI) thread.
|
|
||||||
#
|
#
|
||||||
|
|
||||||
try:
|
_task_runner = None
|
||||||
from Queue import Queue
|
|
||||||
except ImportError:
|
|
||||||
from queue import Queue
|
|
||||||
_task_queue = Queue(16)
|
|
||||||
del Queue
|
|
||||||
|
|
||||||
|
|
||||||
from threading import Thread, current_thread as _current_thread
|
|
||||||
|
|
||||||
def _process_async_queue():
|
|
||||||
t = _current_thread()
|
|
||||||
t.alive = True
|
|
||||||
while t.alive:
|
|
||||||
function, args, kwargs = _task_queue.get()
|
|
||||||
if function:
|
|
||||||
function(*args, **kwargs)
|
|
||||||
if _log.isEnabledFor(_DEBUG):
|
|
||||||
_log.debug("stopped")
|
|
||||||
|
|
||||||
_queue_processor = Thread(name='AsyncUI', target=_process_async_queue)
|
|
||||||
_queue_processor.daemon = True
|
|
||||||
_queue_processor.alive = False
|
|
||||||
_queue_processor.start()
|
|
||||||
|
|
||||||
del Thread
|
|
||||||
|
|
||||||
def async(function, *args, **kwargs):
|
def async(function, *args, **kwargs):
|
||||||
task = (function, args, kwargs)
|
if _task_runner:
|
||||||
_task_queue.put(task)
|
_task_runner(function, *args, **kwargs)
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -133,36 +85,73 @@ def async(function, *args, **kwargs):
|
||||||
|
|
||||||
from . import notify, tray, window
|
from . import notify, tray, window
|
||||||
|
|
||||||
def init():
|
|
||||||
|
def _startup(app, startup_hook):
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("startup registered=%s, remote=%s", app.get_is_registered(), app.get_is_remote())
|
||||||
|
|
||||||
|
from solaar.async import TaskRunner as _TaskRunner
|
||||||
|
global _task_runner
|
||||||
|
_task_runner = _TaskRunner('AsyncUI')
|
||||||
|
_task_runner.start()
|
||||||
|
|
||||||
notify.init()
|
notify.init()
|
||||||
tray.init(lambda _ignore: window.destroy())
|
tray.init(lambda _ignore: window.destroy())
|
||||||
window.init()
|
window.init()
|
||||||
|
|
||||||
def run_loop():
|
startup_hook()
|
||||||
def _activate(app):
|
|
||||||
assert app == application
|
|
||||||
if app.get_windows():
|
|
||||||
window.popup()
|
|
||||||
else:
|
|
||||||
app.add_window(window._window)
|
|
||||||
|
|
||||||
def _shutdown(app):
|
|
||||||
# stop the async UI processor
|
|
||||||
_queue_processor.alive = False
|
|
||||||
async(None)
|
|
||||||
|
|
||||||
tray.destroy()
|
def _activate(app):
|
||||||
notify.uninit()
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("activate")
|
||||||
|
if app.get_windows():
|
||||||
|
window.popup()
|
||||||
|
else:
|
||||||
|
app.add_window(window._window)
|
||||||
|
|
||||||
|
|
||||||
|
def _command_line(app, command_line):
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("command_line %s", command_line.get_arguments())
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _shutdown(app, shutdown_hook):
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("shutdown")
|
||||||
|
|
||||||
|
shutdown_hook()
|
||||||
|
|
||||||
|
# stop the async UI processor
|
||||||
|
global _task_runner
|
||||||
|
_task_runner.stop()
|
||||||
|
_task_runner = None
|
||||||
|
|
||||||
|
tray.destroy()
|
||||||
|
notify.uninit()
|
||||||
|
|
||||||
|
|
||||||
|
def run_loop(startup_hook, shutdown_hook, args=None):
|
||||||
|
# from gi.repository.Gio import ApplicationFlags as _ApplicationFlags
|
||||||
|
APP_ID = 'io.github.pwr.solaar'
|
||||||
|
application = Gtk.Application.new(APP_ID, 0) # _ApplicationFlags.HANDLES_COMMAND_LINE)
|
||||||
|
|
||||||
|
application.connect('startup', _startup, startup_hook)
|
||||||
|
application.connect('command-line', _command_line)
|
||||||
application.connect('activate', _activate)
|
application.connect('activate', _activate)
|
||||||
application.connect('shutdown', _shutdown)
|
application.connect('shutdown', _shutdown, shutdown_hook)
|
||||||
application.run(None)
|
|
||||||
|
application.run(args)
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
from logitech_receiver.status import ALERT
|
from logitech_receiver.status import ALERT
|
||||||
|
|
||||||
|
|
||||||
def _status_changed(device, alert, reason):
|
def _status_changed(device, alert, reason):
|
||||||
assert device is not None
|
assert device is not None
|
||||||
if _log.isEnabledFor(_DEBUG):
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
|
|
@ -65,8 +65,10 @@ def _create():
|
||||||
logging.exception("failed to fully create the about dialog")
|
logging.exception("failed to fully create the about dialog")
|
||||||
|
|
||||||
about.set_translator_credits('\n'.join((
|
about.set_translator_credits('\n'.join((
|
||||||
|
'Papoteur, David Geiger, Damien Lallement (français)',
|
||||||
'Adrian Piotrowicz (polski)',
|
'Adrian Piotrowicz (polski)',
|
||||||
'Daniel Pavel (română)',
|
'Daniel Pavel (română)',
|
||||||
|
'Daniel Zippert, Emelie Snecker (svensk)',
|
||||||
)))
|
)))
|
||||||
|
|
||||||
about.set_website('http://pwr.github.io/Solaar/')
|
about.set_website('http://pwr.github.io/Solaar/')
|
||||||
|
|
|
@ -69,29 +69,41 @@ def _look_for_application_icons():
|
||||||
del _environ
|
del _environ
|
||||||
# del _path
|
# del _path
|
||||||
|
|
||||||
_default_theme = Gtk.IconTheme.get_default()
|
|
||||||
for p in _look_for_application_icons():
|
|
||||||
_default_theme.prepend_search_path(p)
|
|
||||||
if _log.isEnabledFor(_DEBUG):
|
|
||||||
_log.debug("icon theme paths: %s", _default_theme.get_search_path())
|
|
||||||
|
|
||||||
#
|
_default_theme = None
|
||||||
#
|
_has_gpm_icons = None
|
||||||
#
|
_has_oxygen_icons = None
|
||||||
|
_has_gnome_icons = None
|
||||||
|
_has_elementary_icons = None
|
||||||
|
|
||||||
_has_gpm_icons = _default_theme.has_icon('gpm-battery-020-charging')
|
|
||||||
_has_oxygen_icons = _default_theme.has_icon('battery-charging-caution') and \
|
|
||||||
_default_theme.has_icon('battery-charging-040')
|
|
||||||
_has_gnome_icons = _default_theme.has_icon('battery-caution-charging') and \
|
|
||||||
_default_theme.has_icon('battery-full-charged')
|
|
||||||
_has_elementary_icons = _default_theme.has_icon('battery-020-charging')
|
|
||||||
|
|
||||||
if _log.isEnabledFor(_DEBUG):
|
def _init_icon_paths():
|
||||||
_log.debug("detected icon sets: gpm %s, oxygen %s, gnome %s, elementary %s",
|
global _default_theme
|
||||||
_has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons)
|
if _default_theme:
|
||||||
if (not _has_gpm_icons and not _has_oxygen_icons and
|
return
|
||||||
not _has_gnome_icons and not _has_elementary_icons):
|
|
||||||
_log.warning("failed to detect a known icon set")
|
_default_theme = Gtk.IconTheme.get_default()
|
||||||
|
for p in _look_for_application_icons():
|
||||||
|
_default_theme.prepend_search_path(p)
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("icon theme paths: %s", _default_theme.get_search_path())
|
||||||
|
|
||||||
|
global _has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons
|
||||||
|
|
||||||
|
_has_gpm_icons = _default_theme.has_icon('gpm-battery-020-charging')
|
||||||
|
_has_oxygen_icons = _default_theme.has_icon('battery-charging-caution') and \
|
||||||
|
_default_theme.has_icon('battery-charging-040')
|
||||||
|
_has_gnome_icons = _default_theme.has_icon('battery-caution-charging') and \
|
||||||
|
_default_theme.has_icon('battery-full-charged')
|
||||||
|
_has_elementary_icons = _default_theme.has_icon('battery-020-charging')
|
||||||
|
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("detected icon sets: gpm %s, oxygen %s, gnome %s, elementary %s",
|
||||||
|
_has_gpm_icons, _has_oxygen_icons, _has_gnome_icons, _has_elementary_icons)
|
||||||
|
|
||||||
|
if (not _has_gpm_icons and not _has_oxygen_icons and
|
||||||
|
not _has_gnome_icons and not _has_elementary_icons):
|
||||||
|
_log.warning("failed to detect a known icon set")
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -106,6 +118,8 @@ def battery(level=None, charging=False):
|
||||||
return icon_name
|
return icon_name
|
||||||
|
|
||||||
def _battery_icon_name(level, charging):
|
def _battery_icon_name(level, charging):
|
||||||
|
_init_icon_paths()
|
||||||
|
|
||||||
if level is None or level < 0:
|
if level is None or level < 0:
|
||||||
return 'gpm-battery-missing' \
|
return 'gpm-battery-missing' \
|
||||||
if _has_gpm_icons and _default_theme.has_icon('gpm-battery-missing') \
|
if _has_gpm_icons and _default_theme.has_icon('gpm-battery-missing') \
|
||||||
|
@ -186,6 +200,8 @@ def device_icon_set(name='_', kind=None):
|
||||||
|
|
||||||
|
|
||||||
def device_icon_file(name, kind=None, size=_LARGE_SIZE):
|
def device_icon_file(name, kind=None, size=_LARGE_SIZE):
|
||||||
|
_init_icon_paths()
|
||||||
|
|
||||||
icon_set = device_icon_set(name, kind)
|
icon_set = device_icon_set(name, kind)
|
||||||
assert icon_set
|
assert icon_set
|
||||||
for n in reversed(icon_set.names):
|
for n in reversed(icon_set.names):
|
||||||
|
@ -194,6 +210,8 @@ def device_icon_file(name, kind=None, size=_LARGE_SIZE):
|
||||||
|
|
||||||
|
|
||||||
def device_icon_name(name, kind=None):
|
def device_icon_name(name, kind=None):
|
||||||
|
_init_icon_paths()
|
||||||
|
|
||||||
icon_set = device_icon_set(name, kind)
|
icon_set = device_icon_set(name, kind)
|
||||||
assert icon_set
|
assert icon_set
|
||||||
for n in reversed(icon_set.names):
|
for n in reversed(icon_set.names):
|
||||||
|
@ -202,6 +220,8 @@ def device_icon_name(name, kind=None):
|
||||||
|
|
||||||
|
|
||||||
def icon_file(name, size=_LARGE_SIZE):
|
def icon_file(name, size=_LARGE_SIZE):
|
||||||
|
_init_icon_paths()
|
||||||
|
|
||||||
if _default_theme.has_icon(name):
|
if _default_theme.has_icon(name):
|
||||||
theme_icon = _default_theme.lookup_icon(name, size, 0)
|
theme_icon = _default_theme.lookup_icon(name, size, 0)
|
||||||
file_name = theme_icon.get_filename()
|
file_name = theme_icon.get_filename()
|
||||||
|
|
|
@ -112,8 +112,14 @@ try:
|
||||||
if n is None:
|
if n is None:
|
||||||
n = _notifications[summary] = Notify.Notification()
|
n = _notifications[summary] = Notify.Notification()
|
||||||
|
|
||||||
message = reason or (_("unpaired") if dev.status is None else
|
if reason:
|
||||||
(str(dev.status) or (_("connected") if dev.status else _("offline"))))
|
message = reason
|
||||||
|
elif dev.status is None:
|
||||||
|
message = _("unpaired")
|
||||||
|
elif bool(dev.status):
|
||||||
|
message = dev.status.__str__() or _("connected")
|
||||||
|
else:
|
||||||
|
message = _("offline")
|
||||||
|
|
||||||
# we need to use the filename here because the notifications daemon
|
# we need to use the filename here because the notifications daemon
|
||||||
# is an external application that does not know about our icon sets
|
# is an external application that does not know about our icon sets
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
from logging import getLogger, DEBUG as _DEBUG, INFO as _INFO
|
from logging import getLogger, DEBUG as _DEBUG
|
||||||
_log = getLogger(__name__)
|
_log = getLogger(__name__)
|
||||||
del getLogger
|
del getLogger
|
||||||
|
|
||||||
|
@ -67,82 +67,88 @@ def _create_menu(quit_handler):
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
|
|
||||||
|
_last_scroll = 0
|
||||||
|
def _scroll(tray_icon, event, direction=None):
|
||||||
|
if direction is None:
|
||||||
|
direction = event.direction
|
||||||
|
now = event.time / 1000.0
|
||||||
|
else:
|
||||||
|
now = None
|
||||||
|
|
||||||
|
if direction != ScrollDirection.UP and direction != ScrollDirection.DOWN:
|
||||||
|
# ignore all other directions
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(_devices_info) < 4:
|
||||||
|
# don't bother with scrolling when there's only one receiver
|
||||||
|
# with only one device (3 = [receiver, device, separator])
|
||||||
|
return
|
||||||
|
|
||||||
|
# scroll events come way too fast (at least 5-6 at once)
|
||||||
|
# so take a little break between them
|
||||||
|
global _last_scroll
|
||||||
|
now = now or _timestamp()
|
||||||
|
if now - _last_scroll < 0.33: # seconds
|
||||||
|
return
|
||||||
|
_last_scroll = now
|
||||||
|
|
||||||
|
# if _log.isEnabledFor(_DEBUG):
|
||||||
|
# _log.debug("scroll direction %s", direction)
|
||||||
|
|
||||||
|
global _picked_device
|
||||||
|
candidate = None
|
||||||
|
|
||||||
|
if _picked_device is None:
|
||||||
|
for info in _devices_info:
|
||||||
|
# pick first peripheral found
|
||||||
|
if info[1] is not None:
|
||||||
|
candidate = info
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
found = False
|
||||||
|
for info in _devices_info:
|
||||||
|
if not info[1]:
|
||||||
|
# only conside peripherals
|
||||||
|
continue
|
||||||
|
# compare peripherals
|
||||||
|
if info[0:2] == _picked_device[0:2]:
|
||||||
|
if direction == ScrollDirection.UP and candidate:
|
||||||
|
# select previous device
|
||||||
|
break
|
||||||
|
found = True
|
||||||
|
else:
|
||||||
|
if found:
|
||||||
|
candidate = info
|
||||||
|
if direction == ScrollDirection.DOWN:
|
||||||
|
break
|
||||||
|
# if direction is up, but no candidate found before _picked,
|
||||||
|
# let it run through all candidates, will get stuck with the last one
|
||||||
|
else:
|
||||||
|
if direction == ScrollDirection.DOWN:
|
||||||
|
# only use the first one, in case no candidates are after _picked
|
||||||
|
if candidate is None:
|
||||||
|
candidate = info
|
||||||
|
else:
|
||||||
|
candidate = info
|
||||||
|
|
||||||
|
# if the last _picked_device is gone, clear it
|
||||||
|
# the candidate will be either the first or last one remaining,
|
||||||
|
# depending on the scroll direction
|
||||||
|
if not found:
|
||||||
|
_picked_device = None
|
||||||
|
|
||||||
|
_picked_device = candidate or _picked_device
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("scroll: picked %s", _picked_device)
|
||||||
|
_update_tray_icon()
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# raise ImportError
|
# raise ImportError
|
||||||
from gi.repository import AppIndicator3
|
from gi.repository import AppIndicator3
|
||||||
|
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_DEBUG):
|
||||||
_log.info("using AppIndicator3")
|
_log.debug("using AppIndicator3")
|
||||||
|
|
||||||
_last_scroll = 0
|
|
||||||
def _scroll(ind, _ignore, direction):
|
|
||||||
if direction != ScrollDirection.UP and direction != ScrollDirection.DOWN:
|
|
||||||
# ignore all other directions
|
|
||||||
return
|
|
||||||
|
|
||||||
if len(_devices_info) < 4:
|
|
||||||
# don't bother with scrolling when there's only one receiver
|
|
||||||
# with only one device (3 = [receiver, device, separator])
|
|
||||||
return
|
|
||||||
|
|
||||||
# scroll events come way too fast (at least 5-6 at once)
|
|
||||||
# so take a little break between them
|
|
||||||
global _last_scroll
|
|
||||||
now = _timestamp()
|
|
||||||
if now - _last_scroll < 0.33: # seconds
|
|
||||||
return
|
|
||||||
_last_scroll = now
|
|
||||||
|
|
||||||
# if _log.isEnabledFor(_DEBUG):
|
|
||||||
# _log.debug("scroll direction %s", direction)
|
|
||||||
|
|
||||||
global _picked_device
|
|
||||||
candidate = None
|
|
||||||
|
|
||||||
if _picked_device is None:
|
|
||||||
for info in _devices_info:
|
|
||||||
# pick first peripheral found
|
|
||||||
if info[1] is not None:
|
|
||||||
candidate = info
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
found = False
|
|
||||||
for info in _devices_info:
|
|
||||||
if not info[1]:
|
|
||||||
# only conside peripherals
|
|
||||||
continue
|
|
||||||
# compare peripherals
|
|
||||||
if info[0:2] == _picked_device[0:2]:
|
|
||||||
if direction == ScrollDirection.UP and candidate:
|
|
||||||
# select previous device
|
|
||||||
break
|
|
||||||
found = True
|
|
||||||
else:
|
|
||||||
if found:
|
|
||||||
candidate = info
|
|
||||||
if direction == ScrollDirection.DOWN:
|
|
||||||
break
|
|
||||||
# if direction is up, but no candidate found before _picked,
|
|
||||||
# let it run through all candidates, will get stuck with the last one
|
|
||||||
else:
|
|
||||||
if direction == ScrollDirection.DOWN:
|
|
||||||
# only use the first one, in case no candidates are after _picked
|
|
||||||
if candidate is None:
|
|
||||||
candidate = info
|
|
||||||
else:
|
|
||||||
candidate = info
|
|
||||||
|
|
||||||
# if the last _picked_device is gone, clear it
|
|
||||||
# the candidate will be either the first or last one remaining,
|
|
||||||
# depending on the scroll direction
|
|
||||||
if not found:
|
|
||||||
_picked_device = None
|
|
||||||
|
|
||||||
_picked_device = candidate or _picked_device
|
|
||||||
if _log.isEnabledFor(_DEBUG):
|
|
||||||
_log.debug("scroll: picked %s", _picked_device)
|
|
||||||
_update_tray_icon()
|
|
||||||
|
|
||||||
|
|
||||||
def _create(menu):
|
def _create(menu):
|
||||||
theme_paths = Gtk.IconTheme.get_default().get_search_path()
|
theme_paths = Gtk.IconTheme.get_default().get_search_path()
|
||||||
|
@ -201,8 +207,8 @@ try:
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_DEBUG):
|
||||||
_log.info("using StatusIcon")
|
_log.debug("using StatusIcon")
|
||||||
|
|
||||||
def _create(menu):
|
def _create(menu):
|
||||||
icon = Gtk.StatusIcon.new_from_icon_name(_icons.TRAY_INIT)
|
icon = Gtk.StatusIcon.new_from_icon_name(_icons.TRAY_INIT)
|
||||||
|
@ -210,10 +216,9 @@ except ImportError:
|
||||||
icon.set_title(NAME)
|
icon.set_title(NAME)
|
||||||
icon.set_tooltip_text(NAME)
|
icon.set_tooltip_text(NAME)
|
||||||
icon.connect('activate', _window_toggle)
|
icon.connect('activate', _window_toggle)
|
||||||
|
icon.connect('scroll-event', _scroll)
|
||||||
icon.connect('popup_menu',
|
icon.connect('popup-menu',
|
||||||
lambda icon, button, time:
|
lambda icon, button, time: menu.popup(None, None, icon.position_menu, icon, button, time))
|
||||||
menu.popup(None, None, icon.position_menu, icon, button, time))
|
|
||||||
|
|
||||||
return icon
|
return icon
|
||||||
|
|
||||||
|
@ -506,7 +511,7 @@ def update(device=None):
|
||||||
menu_items[no_receivers_index + 1].set_visible(not _devices_info)
|
menu_items[no_receivers_index + 1].set_visible(not _devices_info)
|
||||||
|
|
||||||
global _picked_device
|
global _picked_device
|
||||||
if not _picked_device and device is not None and device.kind is not None:
|
if (not _picked_device or _last_scroll == 0) and device is not None and device.kind is not None:
|
||||||
# if it's just a receiver update, it's unlikely the picked device would change
|
# if it's just a receiver update, it's unlikely the picked device would change
|
||||||
_picked_device = _pick_device_with_lowest_battery()
|
_picked_device = _pick_device_with_lowest_battery()
|
||||||
|
|
||||||
|
|
|
@ -76,9 +76,6 @@ _NANO_RECEIVER_TEXT = (
|
||||||
# create UI layout
|
# create UI layout
|
||||||
#
|
#
|
||||||
|
|
||||||
Gtk.Window.set_default_icon_name(NAME.lower())
|
|
||||||
Gtk.Window.set_default_icon_from_file(_icons.icon_file(NAME.lower()))
|
|
||||||
|
|
||||||
def _new_button(label, icon_name=None, icon_size=_NORMAL_BUTTON_ICON_SIZE, tooltip=None, toggle=False, clicked=None):
|
def _new_button(label, icon_name=None, icon_size=_NORMAL_BUTTON_ICON_SIZE, tooltip=None, toggle=False, clicked=None):
|
||||||
if toggle:
|
if toggle:
|
||||||
b = Gtk.ToggleButton()
|
b = Gtk.ToggleButton()
|
||||||
|
@ -630,7 +627,7 @@ def _update_device_panel(device, panel, buttons, full=False):
|
||||||
panel._battery._icon.set_sensitive(True)
|
panel._battery._icon.set_sensitive(True)
|
||||||
|
|
||||||
if isinstance(battery_level, _NamedInt):
|
if isinstance(battery_level, _NamedInt):
|
||||||
text = str(battery_level)
|
text = _(str(battery_level))
|
||||||
else:
|
else:
|
||||||
text = '%d%%' % battery_level
|
text = '%d%%' % battery_level
|
||||||
if is_online:
|
if is_online:
|
||||||
|
@ -734,6 +731,9 @@ _window = None
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
|
Gtk.Window.set_default_icon_name(NAME.lower())
|
||||||
|
Gtk.Window.set_default_icon_from_file(_icons.icon_file(NAME.lower()))
|
||||||
|
|
||||||
global _model, _tree, _details, _info, _empty, _window
|
global _model, _tree, _details, _info, _empty, _window
|
||||||
_model = Gtk.TreeStore(*_COLUMN_TYPES)
|
_model = Gtk.TreeStore(*_COLUMN_TYPES)
|
||||||
_tree = _create_tree(_model)
|
_tree = _create_tree(_model)
|
||||||
|
|
|
@ -1,3 +1,16 @@
|
||||||
|
solaar (0.9.2-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fixes for lintian warnings.
|
||||||
|
|
||||||
|
-- Daniel Pavel <daniel.pavel+debian@gmail.com> Wed, 24 Jul 2013 21:47:17 +0200
|
||||||
|
|
||||||
|
solaar (0.9.2-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* Release 0.9.2.
|
||||||
|
* Closes: #717766.
|
||||||
|
|
||||||
|
-- Daniel Pavel <daniel.pavel+debian@gmail.com> Wed, 24 Jul 2013 20:59:52 +0200
|
||||||
|
|
||||||
solaar (0.9.1-1) unstable; urgency=low
|
solaar (0.9.1-1) unstable; urgency=low
|
||||||
|
|
||||||
* Release 0.9.1.
|
* Release 0.9.1.
|
||||||
|
|
|
@ -2,7 +2,7 @@ Source: solaar
|
||||||
Section: misc
|
Section: misc
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Daniel Pavel <daniel.pavel@gmail.com>
|
Maintainer: Daniel Pavel <daniel.pavel@gmail.com>
|
||||||
Build-Depends: debhelper (>= 8)
|
Build-Depends: debhelper (>= 9)
|
||||||
Build-Depends-Indep: python, po-debconf
|
Build-Depends-Indep: python, po-debconf
|
||||||
X-Python-Version: >= 2.7
|
X-Python-Version: >= 2.7
|
||||||
X-Python3-Version: >= 3.2
|
X-Python3-Version: >= 3.2
|
||||||
|
|
|
@ -42,7 +42,6 @@ License: LGPL
|
||||||
Files: share/icons/light_*.png
|
Files: share/icons/light_*.png
|
||||||
Copyright: Oxygen Icons
|
Copyright: Oxygen Icons
|
||||||
License: LGPL
|
License: LGPL
|
||||||
Comment: These files were copied from the Oxygen icon theme (weather-*).
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
|
@ -55,3 +54,4 @@ Comment: These files were copied from the Oxygen icon theme (weather-*).
|
||||||
.
|
.
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
Comment: These files were copied from the Oxygen icon theme (weather-*).
|
||||||
|
|
|
@ -0,0 +1,453 @@
|
||||||
|
# French translations for solaar package.
|
||||||
|
# Copyright (C) 2013 THE solaar'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the solaar package.
|
||||||
|
# Automatically generated, 2013.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr "Project-Id-Version: solaar 0.9.2\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2013-08-08 21:51+0200\n"
|
||||||
|
"PO-Revision-Date: 2013-08-07 14:43+0200\n"
|
||||||
|
"Last-Translator: Damien Lallement <dams@mageia.org>\n"
|
||||||
|
"Language-Team: Language: fr\n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "critical"
|
||||||
|
msgstr "critique"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "empty"
|
||||||
|
msgstr "vide"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38 lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "full"
|
||||||
|
msgstr "pleine"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "good"
|
||||||
|
msgstr "bonne"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "low"
|
||||||
|
msgstr "faible"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "almost full"
|
||||||
|
msgstr "presque pleine"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "discharging"
|
||||||
|
msgstr "En décharge"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "recharging"
|
||||||
|
msgstr "En charge"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "invalid battery"
|
||||||
|
msgstr "batterie invalide"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "slow recharge"
|
||||||
|
msgstr "recharge lente"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "thermal error"
|
||||||
|
msgstr "erreur thermique"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "device not supported"
|
||||||
|
msgstr "périphérique non pris en charge"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "device timeout"
|
||||||
|
msgstr "le périphérique ne répond pas"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "sequence timeout"
|
||||||
|
msgstr "dépassement de délai"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "too many devices"
|
||||||
|
msgstr "trop de périphériques"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Bootloader"
|
||||||
|
msgstr "Chargeur d'amorçage"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||||
|
msgid "Firmware"
|
||||||
|
msgstr "Micrologiciel"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Hardware"
|
||||||
|
msgstr "Matériel"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Other"
|
||||||
|
msgstr "Autre"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "closed"
|
||||||
|
msgstr "fermé"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "open"
|
||||||
|
msgstr "ouvert"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "pairing lock is "
|
||||||
|
msgstr "le verrou de jumelage est "
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||||
|
msgid "unpaired"
|
||||||
|
msgstr "non jumelé"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:192
|
||||||
|
msgid "powered on"
|
||||||
|
msgstr "sous tension"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||||
|
msgid "unknown"
|
||||||
|
msgstr "inconnu"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:77
|
||||||
|
msgid "Smooth Scrolling"
|
||||||
|
msgstr "Défilement fluide"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:78
|
||||||
|
msgid "High-sensitivity mode for vertical scroll with the wheel."
|
||||||
|
msgstr "Mode haute sensibilité pour défilement vertical avec la molette."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:79
|
||||||
|
msgid "Side Scrolling"
|
||||||
|
msgstr "Défilement latéral"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:80
|
||||||
|
msgid "When disabled, pushing the wheel sideways sends custom button "
|
||||||
|
"events\n"
|
||||||
|
"instead of the standard side-scrolling events."
|
||||||
|
msgstr "Lorsque désactivé, l'appui sur les côtés de la molette envoie des "
|
||||||
|
"évènements\n"
|
||||||
|
" de bouton personnalisés à la place des évènements standards de "
|
||||||
|
"défilement latéral."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:82
|
||||||
|
msgid "Sensitivity (DPI)"
|
||||||
|
msgstr "Sensibilité (DPI)"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:83
|
||||||
|
msgid "Swap Fx function"
|
||||||
|
msgstr "Fonction Swap Fx"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:84
|
||||||
|
msgid "When set, the F1..F12 keys will activate their special function,\n"
|
||||||
|
"and you must hold the FN key to activate their standard function."
|
||||||
|
msgstr "Lorsque défini, les touches F1..F12 activeront leurs fonctions "
|
||||||
|
"spéciales,\n"
|
||||||
|
"et vous devez maintenir la touche FN pour activer leurs fonctions "
|
||||||
|
"standards."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:87
|
||||||
|
msgid "When unset, the F1..F12 keys will activate their standard function,\n"
|
||||||
|
"and you must hold the FN key to activate their special function."
|
||||||
|
msgstr "Lorsque non défini, les touches F1..F12 activeront leurs fonctions "
|
||||||
|
"standards,\n"
|
||||||
|
"et vous devez maintenir la touche FN pour activer leurs fonctions "
|
||||||
|
"spéciales."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:89
|
||||||
|
msgid "Hand Detection"
|
||||||
|
msgstr "Détection manuelle"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:90
|
||||||
|
msgid "Turn on illumination when the hands hover over the keyboard."
|
||||||
|
msgstr "Allume l'éclairage lorsque les mains passent au-dessus du clavier."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:98
|
||||||
|
msgid "No paired devices."
|
||||||
|
msgstr "Aucun périphériques jumelés"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:99
|
||||||
|
msgid "1 paired device."
|
||||||
|
msgstr "1 périphérique jumelé."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:100
|
||||||
|
msgid " paired devices."
|
||||||
|
msgstr " périphériques jumelés."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||||
|
#: lib/solaar/ui/window.py:143
|
||||||
|
msgid "Battery"
|
||||||
|
msgstr "Batterie"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||||
|
msgid "Lighting"
|
||||||
|
msgstr "Éclairage"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||||
|
msgid "lux"
|
||||||
|
msgstr "lux"
|
||||||
|
|
||||||
|
#: lib/solaar/listener.py:95
|
||||||
|
msgid "The receiver was unplugged."
|
||||||
|
msgstr "Le récepteur a été débranché."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:48
|
||||||
|
msgid "Permissions error"
|
||||||
|
msgstr "Erreur de permissions"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||||
|
"it."
|
||||||
|
msgstr "Trouvé un récepteur Logitech (%s), mais n'a pas eu l'autorisation de "
|
||||||
|
"l'ouvrir."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:51
|
||||||
|
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||||
|
"plugging it back in."
|
||||||
|
msgstr "Si vous venez juste d'installer Solaar, essayez de retirer le "
|
||||||
|
"récepteur et de le rebrancher."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:53
|
||||||
|
msgid "Unpairing failed"
|
||||||
|
msgstr "La déconnexion a échoué"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:54
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Failed to unpair %{device} from %{receiver}."
|
||||||
|
msgstr "Impossible de dissocier %{device} de %{receiver}."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:56
|
||||||
|
msgid "The receiver returned an error, with no further details."
|
||||||
|
msgstr "Le récepteur a retourné une erreur, sans plus de détails."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:39
|
||||||
|
msgid "Shows status of devices connected\n"
|
||||||
|
"through wireless Logitech receivers."
|
||||||
|
msgstr "Affiche l'état des périphériques connectés\n"
|
||||||
|
"à travers les récepteurs sans fil Logitech."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:48
|
||||||
|
msgid "GUI design"
|
||||||
|
msgstr "Interface graphique"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:49
|
||||||
|
msgid "Testing"
|
||||||
|
msgstr "Testeur"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:54
|
||||||
|
msgid "Logitech documentation"
|
||||||
|
msgstr "Documentațion Logitech"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||||
|
msgid "About"
|
||||||
|
msgstr "À propos de"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||||
|
#: lib/solaar/ui/window.py:203
|
||||||
|
msgid "Unpair"
|
||||||
|
msgstr "Déconnecter"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/config_panel.py:97
|
||||||
|
msgid "Working"
|
||||||
|
msgstr "En fonctionnement"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/config_panel.py:100
|
||||||
|
msgid "Read/write operation failed."
|
||||||
|
msgstr "Les opérations de lecture/écriture ont échoué."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/notify.py:120
|
||||||
|
msgid "connected"
|
||||||
|
msgstr "connecté"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||||
|
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||||
|
msgid "offline"
|
||||||
|
msgstr "non connecté"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:133
|
||||||
|
msgid "Pairing failed"
|
||||||
|
msgstr "Le jumelage a échoué"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:135
|
||||||
|
msgid "Make sure your device is within range, and has a decent battery "
|
||||||
|
"charge."
|
||||||
|
msgstr "Assurez-vous que votre périphérique soit à portée, et que sa "
|
||||||
|
"batterie soit suffisamment chargée."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:137
|
||||||
|
msgid "A new device was detected, but it is not compatible with this "
|
||||||
|
"receiver."
|
||||||
|
msgstr "Un nouveau périphérique a été détecté, mais il n'est pas compatible "
|
||||||
|
"avec ce récepteur."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:139
|
||||||
|
#, python-format
|
||||||
|
msgid "The receiver only supports %d paired device(s)."
|
||||||
|
msgstr "Le récepteur supporte seulement %d périphérique(s). "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:141
|
||||||
|
msgid "No further details are available about the error."
|
||||||
|
msgstr "Aucun autre détail n'est disponible à propos de l'erreur."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:155
|
||||||
|
msgid "Found a new device"
|
||||||
|
msgstr "Nouveau périphérique disponible"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:180
|
||||||
|
msgid "The wireless link is not encrypted"
|
||||||
|
msgstr "La connexion sans fil n'est pas chiffrée"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:197
|
||||||
|
msgid "pair new device"
|
||||||
|
msgstr "Jumele le nouveau périphérique"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:205
|
||||||
|
msgid "Turn on the device you want to pair."
|
||||||
|
msgstr "Allumez le périphérique que vous souhaitez jumeler."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:206
|
||||||
|
msgid "If the device is already turned on,\n"
|
||||||
|
"turn if off and on again."
|
||||||
|
msgstr "Si le périphérique est déjà allumé,\n"
|
||||||
|
"éteignez le et rallumez-le à nouveau."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:55
|
||||||
|
msgid "No Logitech receiver found"
|
||||||
|
msgstr "Aucun récepteur Logitech trouvé"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:62
|
||||||
|
msgid "Quit"
|
||||||
|
msgstr "Quitter"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:274
|
||||||
|
msgid "no receiver"
|
||||||
|
msgstr "aucun récepteur"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:293
|
||||||
|
msgid "no status"
|
||||||
|
msgstr "aucun statut"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:58
|
||||||
|
msgid "The wireless link between this device and its receiver is encrypted."
|
||||||
|
msgstr "La connexion sans fil entre cet appareil et son récepteur est "
|
||||||
|
"chiffrée."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:59
|
||||||
|
msgid "The wireless link between this device and its receiver is not "
|
||||||
|
"encrypted.\n"
|
||||||
|
"\n"
|
||||||
|
"For pointing devices (mice, trackballs, trackpads), this is a minor "
|
||||||
|
"security issue.\n"
|
||||||
|
"\n"
|
||||||
|
"It is, however, a major security issue for text-input devices "
|
||||||
|
"(keyboards, numpads),\n"
|
||||||
|
"because typed text can be sniffed inconspicuously by 3rd parties "
|
||||||
|
"within range."
|
||||||
|
msgstr "La connexion sans fil entre cet appareil et son récepteur n'est pas "
|
||||||
|
"chiffrée.\n"
|
||||||
|
"\n"
|
||||||
|
"Pour des dispositifs de pointage (souris, trackball, trackpad), "
|
||||||
|
"c'est une faille mineure de sécurité\n"
|
||||||
|
"\n"
|
||||||
|
"Par contre, c'est une faille majeure pour les dispositifs d'entrée "
|
||||||
|
"de texte (clavier, pavé numérique)\n"
|
||||||
|
"car les données saisies peuvent être volées à votre insu par des "
|
||||||
|
"tiers à proximité."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:71
|
||||||
|
msgid "No device paired"
|
||||||
|
msgstr "Aucun périphérique jumelé"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:68
|
||||||
|
#, python-format
|
||||||
|
msgid "Up to %d devices can be paired to this receiver"
|
||||||
|
msgstr "Jusqu'à %d périphériques peuvent être jumelés à ce récepteur"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:68
|
||||||
|
msgid "paired devices"
|
||||||
|
msgstr "périphérique(s) jumelé(s)"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:72
|
||||||
|
msgid "Only one device can be paired to this receiver"
|
||||||
|
msgstr "Un seul périphérique peut être jumelé à ce récepteur"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:110
|
||||||
|
msgid "Scanning"
|
||||||
|
msgstr "Balayage"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:146
|
||||||
|
msgid "Wireless Link"
|
||||||
|
msgstr "Connexion sans fil"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:179
|
||||||
|
msgid "Show Technical Details"
|
||||||
|
msgstr "Voir les détails techniques"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:192
|
||||||
|
msgid "Pair new device"
|
||||||
|
msgstr "Jumeler un nouveau périphérique"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:211
|
||||||
|
msgid "Select a device"
|
||||||
|
msgstr "Sélectionner un périphérique"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:508
|
||||||
|
msgid "Path"
|
||||||
|
msgstr "Chemin"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:510
|
||||||
|
msgid "USB id"
|
||||||
|
msgstr "Id USB"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||||
|
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||||
|
msgid "Serial"
|
||||||
|
msgstr "Numéro de série"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:519
|
||||||
|
msgid "Index"
|
||||||
|
msgstr "Index"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:520
|
||||||
|
msgid "Wireless PID"
|
||||||
|
msgstr "PID sans fil"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:522
|
||||||
|
msgid "Protocol"
|
||||||
|
msgstr "Protocole"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:524
|
||||||
|
msgid "Polling rate"
|
||||||
|
msgstr "Taux de scrutation"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:539
|
||||||
|
msgid "none"
|
||||||
|
msgstr "aucun"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:540
|
||||||
|
msgid "Notifications"
|
||||||
|
msgstr "Notifications"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:635
|
||||||
|
msgid "charging"
|
||||||
|
msgstr "en charge"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:637
|
||||||
|
msgid "last known"
|
||||||
|
msgstr "dernière valeur connue"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:644
|
||||||
|
msgid "not encrypted"
|
||||||
|
msgstr "non chiffrée"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:648
|
||||||
|
msgid "encrypted"
|
||||||
|
msgstr "chiffrée"
|
92
po/pl.po
92
po/pl.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2013-07-23 22:38+0200\n"
|
"POT-Creation-Date: 2013-08-08 21:53+0200\n"
|
||||||
"PO-Revision-Date: 2013-07-23 10:41+0100\n"
|
"PO-Revision-Date: 2013-07-23 10:41+0100\n"
|
||||||
"Last-Translator: Adrian Piotrowicz <nexces@nxstudio.pl>\n"
|
"Last-Translator: Adrian Piotrowicz <nexces@nxstudio.pl>\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
|
@ -82,7 +82,7 @@ msgstr "za dużo urządzeń"
|
||||||
msgid "Bootloader"
|
msgid "Bootloader"
|
||||||
msgstr "Bootloader"
|
msgstr "Bootloader"
|
||||||
|
|
||||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||||
msgid "Firmware"
|
msgid "Firmware"
|
||||||
msgstr "Firmware"
|
msgstr "Firmware"
|
||||||
|
|
||||||
|
@ -106,11 +106,15 @@ msgstr "otwarte"
|
||||||
msgid "pairing lock is "
|
msgid "pairing lock is "
|
||||||
msgstr "blokada parowania jest"
|
msgstr "blokada parowania jest"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||||
|
msgid "unpaired"
|
||||||
|
msgstr "nie sparowany"
|
||||||
|
|
||||||
#: lib/logitech_receiver/notifications.py:192
|
#: lib/logitech_receiver/notifications.py:192
|
||||||
msgid "powered on"
|
msgid "powered on"
|
||||||
msgstr "włączone"
|
msgstr "włączone"
|
||||||
|
|
||||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr "nieznane"
|
msgstr "nieznane"
|
||||||
|
|
||||||
|
@ -177,16 +181,16 @@ msgstr "1 sparowane urządzenie."
|
||||||
msgid " paired devices."
|
msgid " paired devices."
|
||||||
msgstr "sparowane(-ych) urządzeń."
|
msgstr "sparowane(-ych) urządzeń."
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||||
#: lib/solaar/ui/window.py:146
|
#: lib/solaar/ui/window.py:143
|
||||||
msgid "Battery"
|
msgid "Battery"
|
||||||
msgstr "Bateria"
|
msgstr "Bateria"
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||||
msgid "Lighting"
|
msgid "Lighting"
|
||||||
msgstr "Podświetlenie"
|
msgstr "Podświetlenie"
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||||
msgid "lux"
|
msgid "lux"
|
||||||
msgstr "lux"
|
msgstr "lux"
|
||||||
|
|
||||||
|
@ -194,33 +198,33 @@ msgstr "lux"
|
||||||
msgid "The receiver was unplugged."
|
msgid "The receiver was unplugged."
|
||||||
msgstr "Odbiornik został odłączony."
|
msgstr "Odbiornik został odłączony."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:69
|
#: lib/solaar/ui/__init__.py:48
|
||||||
msgid "Permissions error"
|
msgid "Permissions error"
|
||||||
msgstr "Błąd uprawnień"
|
msgstr "Błąd uprawnień"
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:70
|
#: lib/solaar/ui/__init__.py:49
|
||||||
#, fuzzy, python-format
|
#, fuzzy, python-format
|
||||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||||
"it."
|
"it."
|
||||||
msgstr "Znaleziono odbiornik Logitech (%s), ale nie ma uprawnień do "
|
msgstr "Znaleziono odbiornik Logitech (%s), ale nie ma uprawnień do "
|
||||||
"otworzenia go."
|
"otworzenia go."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:72
|
#: lib/solaar/ui/__init__.py:51
|
||||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||||
"plugging it back in."
|
"plugging it back in."
|
||||||
msgstr "Jeżeli właśnie zainstalowałeś Solaar spróbuj odłączyć nadajnik i "
|
msgstr "Jeżeli właśnie zainstalowałeś Solaar spróbuj odłączyć nadajnik i "
|
||||||
"podłączyć go ponownie."
|
"podłączyć go ponownie."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:74
|
#: lib/solaar/ui/__init__.py:53
|
||||||
msgid "Unpairing failed"
|
msgid "Unpairing failed"
|
||||||
msgstr "Usunięcie parowania nie powiodło się"
|
msgstr "Usunięcie parowania nie powiodło się"
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:75
|
#: lib/solaar/ui/__init__.py:54
|
||||||
#, python-format
|
#, python-brace-format
|
||||||
msgid "Failed to unpair %s from %s."
|
msgid "Failed to unpair %{device} from %{receiver}."
|
||||||
msgstr "Nie powidło się usunięcie parowania %s z %s."
|
msgstr "Nie powidło się usunięcie parowania %{device} z %{receiver}."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:77
|
#: lib/solaar/ui/__init__.py:56
|
||||||
msgid "The receiver returned an error, with no further details."
|
msgid "The receiver returned an error, with no further details."
|
||||||
msgstr "Odbiornik zwrócił błąd bez dodatkowych informacji."
|
msgstr "Odbiornik zwrócił błąd bez dodatkowych informacji."
|
||||||
|
|
||||||
|
@ -242,12 +246,12 @@ msgstr "Testy"
|
||||||
msgid "Logitech documentation"
|
msgid "Logitech documentation"
|
||||||
msgstr "Dokumentacja Logitech"
|
msgstr "Dokumentacja Logitech"
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr "O"
|
msgstr "O"
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||||
#: lib/solaar/ui/window.py:206
|
#: lib/solaar/ui/window.py:203
|
||||||
msgid "Unpair"
|
msgid "Unpair"
|
||||||
msgstr "Usuń parowanie"
|
msgstr "Usuń parowanie"
|
||||||
|
|
||||||
|
@ -259,16 +263,12 @@ msgstr "Pracuję"
|
||||||
msgid "Read/write operation failed."
|
msgid "Read/write operation failed."
|
||||||
msgstr "Operacja odczytu/zapisu nie powiodła się."
|
msgstr "Operacja odczytu/zapisu nie powiodła się."
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:115
|
#: lib/solaar/ui/notify.py:120
|
||||||
msgid "unpaired"
|
|
||||||
msgstr "nie sparowany"
|
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116
|
|
||||||
msgid "connected"
|
msgid "connected"
|
||||||
msgstr "podłączony"
|
msgstr "podłączony"
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||||
msgid "offline"
|
msgid "offline"
|
||||||
msgstr "wyłączony"
|
msgstr "wyłączony"
|
||||||
|
|
||||||
|
@ -326,11 +326,11 @@ msgstr "Nie znaleziono odbiornika Logitech"
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr "Wyjdź"
|
msgstr "Wyjdź"
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:269
|
#: lib/solaar/ui/tray.py:274
|
||||||
msgid "no receiver"
|
msgid "no receiver"
|
||||||
msgstr "brak odbiornika"
|
msgstr "brak odbiornika"
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:288
|
#: lib/solaar/ui/tray.py:293
|
||||||
msgid "no status"
|
msgid "no status"
|
||||||
msgstr "brak statusu"
|
msgstr "brak statusu"
|
||||||
|
|
||||||
|
@ -380,75 +380,75 @@ msgstr "sparowane urządzenia"
|
||||||
msgid "Only one device can be paired to this receiver"
|
msgid "Only one device can be paired to this receiver"
|
||||||
msgstr "Tylko jedno urządzenie może być sparowane z tym odbiornikiem"
|
msgstr "Tylko jedno urządzenie może być sparowane z tym odbiornikiem"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:113
|
#: lib/solaar/ui/window.py:110
|
||||||
msgid "Scanning"
|
msgid "Scanning"
|
||||||
msgstr "Wyszukiwanie"
|
msgstr "Wyszukiwanie"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:149
|
#: lib/solaar/ui/window.py:146
|
||||||
msgid "Wireless Link"
|
msgid "Wireless Link"
|
||||||
msgstr "Połączenie bezprzewodowe"
|
msgstr "Połączenie bezprzewodowe"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:182
|
#: lib/solaar/ui/window.py:179
|
||||||
msgid "Show Technical Details"
|
msgid "Show Technical Details"
|
||||||
msgstr "Wyświetl szczegóły techniczne"
|
msgstr "Wyświetl szczegóły techniczne"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:195
|
#: lib/solaar/ui/window.py:192
|
||||||
msgid "Pair new device"
|
msgid "Pair new device"
|
||||||
msgstr "Sparuj nowe urządzenie"
|
msgstr "Sparuj nowe urządzenie"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:214
|
#: lib/solaar/ui/window.py:211
|
||||||
msgid "Select a device"
|
msgid "Select a device"
|
||||||
msgstr "Wybierz urządzenie"
|
msgstr "Wybierz urządzenie"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:511
|
#: lib/solaar/ui/window.py:508
|
||||||
msgid "Path"
|
msgid "Path"
|
||||||
msgstr "Ścieżka"
|
msgstr "Ścieżka"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:513
|
#: lib/solaar/ui/window.py:510
|
||||||
msgid "USB id"
|
msgid "USB id"
|
||||||
msgstr "USB id"
|
msgstr "USB id"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||||
msgid "Serial"
|
msgid "Serial"
|
||||||
msgstr "Serial"
|
msgstr "Serial"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:522
|
#: lib/solaar/ui/window.py:519
|
||||||
msgid "Index"
|
msgid "Index"
|
||||||
msgstr "Index"
|
msgstr "Index"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:523
|
#: lib/solaar/ui/window.py:520
|
||||||
msgid "Wireless PID"
|
msgid "Wireless PID"
|
||||||
msgstr "Wireless PID"
|
msgstr "Wireless PID"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:525
|
#: lib/solaar/ui/window.py:522
|
||||||
msgid "Protocol"
|
msgid "Protocol"
|
||||||
msgstr "Protokół"
|
msgstr "Protokół"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:527
|
#: lib/solaar/ui/window.py:524
|
||||||
msgid "Polling rate"
|
msgid "Polling rate"
|
||||||
msgstr "Częstotliwość próbkowania"
|
msgstr "Częstotliwość próbkowania"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:542
|
#: lib/solaar/ui/window.py:539
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "brak"
|
msgstr "brak"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:543
|
#: lib/solaar/ui/window.py:540
|
||||||
msgid "Notifications"
|
msgid "Notifications"
|
||||||
msgstr "Powiadomienia"
|
msgstr "Powiadomienia"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:638
|
#: lib/solaar/ui/window.py:635
|
||||||
msgid "charging"
|
msgid "charging"
|
||||||
msgstr "ładowanie"
|
msgstr "ładowanie"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:640
|
#: lib/solaar/ui/window.py:637
|
||||||
msgid "last known"
|
msgid "last known"
|
||||||
msgstr "ostatni znany"
|
msgstr "ostatni znany"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:647
|
#: lib/solaar/ui/window.py:644
|
||||||
msgid "not encrypted"
|
msgid "not encrypted"
|
||||||
msgstr "nie szyfrowane"
|
msgstr "nie szyfrowane"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:651
|
#: lib/solaar/ui/window.py:648
|
||||||
msgid "encrypted"
|
msgid "encrypted"
|
||||||
msgstr "szyfrowane"
|
msgstr "szyfrowane"
|
||||||
|
|
92
po/ro.po
92
po/ro.po
|
@ -6,7 +6,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2013-07-23 22:35+0200\n"
|
"POT-Creation-Date: 2013-08-08 21:53+0200\n"
|
||||||
"PO-Revision-Date: 2013-07-17 20:27+0100\n"
|
"PO-Revision-Date: 2013-07-17 20:27+0100\n"
|
||||||
"Last-Translator: Daniel Pavel <daniel.pavel@gmail.com>\n"
|
"Last-Translator: Daniel Pavel <daniel.pavel@gmail.com>\n"
|
||||||
"Language-Team: none\n"
|
"Language-Team: none\n"
|
||||||
|
@ -82,7 +82,7 @@ msgstr "prea multe periferice"
|
||||||
msgid "Bootloader"
|
msgid "Bootloader"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||||
msgid "Firmware"
|
msgid "Firmware"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -106,11 +106,15 @@ msgstr "deschis"
|
||||||
msgid "pairing lock is "
|
msgid "pairing lock is "
|
||||||
msgstr "lacătul de contectare este "
|
msgstr "lacătul de contectare este "
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||||
|
msgid "unpaired"
|
||||||
|
msgstr "deconectat(ă)"
|
||||||
|
|
||||||
#: lib/logitech_receiver/notifications.py:192
|
#: lib/logitech_receiver/notifications.py:192
|
||||||
msgid "powered on"
|
msgid "powered on"
|
||||||
msgstr "a pornit"
|
msgstr "a pornit"
|
||||||
|
|
||||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr "necunoscută"
|
msgstr "necunoscută"
|
||||||
|
|
||||||
|
@ -174,16 +178,16 @@ msgstr "Un periferic contectat."
|
||||||
msgid " paired devices."
|
msgid " paired devices."
|
||||||
msgstr " periferice contectate."
|
msgstr " periferice contectate."
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||||
#: lib/solaar/ui/window.py:146
|
#: lib/solaar/ui/window.py:143
|
||||||
msgid "Battery"
|
msgid "Battery"
|
||||||
msgstr "Baterie"
|
msgstr "Baterie"
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||||
msgid "Lighting"
|
msgid "Lighting"
|
||||||
msgstr "Lumină"
|
msgstr "Lumină"
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||||
msgid "lux"
|
msgid "lux"
|
||||||
msgstr "lucși"
|
msgstr "lucși"
|
||||||
|
|
||||||
|
@ -191,32 +195,32 @@ msgstr "lucși"
|
||||||
msgid "The receiver was unplugged."
|
msgid "The receiver was unplugged."
|
||||||
msgstr "Receptor deconectat."
|
msgstr "Receptor deconectat."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:69
|
#: lib/solaar/ui/__init__.py:48
|
||||||
msgid "Permissions error"
|
msgid "Permissions error"
|
||||||
msgstr "Eroare de permisiuni"
|
msgstr "Eroare de permisiuni"
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:70
|
#: lib/solaar/ui/__init__.py:49
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||||
"it."
|
"it."
|
||||||
msgstr "Receptor Logitech detectat (%s), dar nu am permisiunea să-l deschid."
|
msgstr "Receptor Logitech detectat (%s), dar nu am permisiunea să-l deschid."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:72
|
#: lib/solaar/ui/__init__.py:51
|
||||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||||
"plugging it back in."
|
"plugging it back in."
|
||||||
msgstr "Dacă tocmai ați instalat Solaar, scoateți receptorul și re-"
|
msgstr "Dacă tocmai ați instalat Solaar, scoateți receptorul și re-"
|
||||||
"introduceți-l."
|
"introduceți-l."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:74
|
#: lib/solaar/ui/__init__.py:53
|
||||||
msgid "Unpairing failed"
|
msgid "Unpairing failed"
|
||||||
msgstr "Deconectare eșuată"
|
msgstr "Deconectare eșuată"
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:75
|
#: lib/solaar/ui/__init__.py:54
|
||||||
#, python-format
|
#, python-brace-format
|
||||||
msgid "Failed to unpair %s from %s."
|
msgid "Failed to unpair %{device} from %{receiver}."
|
||||||
msgstr "Deconectarea %s de la %s a eșuat."
|
msgstr "Deconectarea %{device} de la %{receiver} a eșuat."
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:77
|
#: lib/solaar/ui/__init__.py:56
|
||||||
msgid "The receiver returned an error, with no further details."
|
msgid "The receiver returned an error, with no further details."
|
||||||
msgstr "Receptorul a semnalat o eroare, fără alte detalii."
|
msgstr "Receptorul a semnalat o eroare, fără alte detalii."
|
||||||
|
|
||||||
|
@ -238,12 +242,12 @@ msgstr "Testare"
|
||||||
msgid "Logitech documentation"
|
msgid "Logitech documentation"
|
||||||
msgstr "Documentație Logitech"
|
msgstr "Documentație Logitech"
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr "Despre"
|
msgstr "Despre"
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||||
#: lib/solaar/ui/window.py:206
|
#: lib/solaar/ui/window.py:203
|
||||||
msgid "Unpair"
|
msgid "Unpair"
|
||||||
msgstr "Deconectează"
|
msgstr "Deconectează"
|
||||||
|
|
||||||
|
@ -255,16 +259,12 @@ msgstr "Prelucrez"
|
||||||
msgid "Read/write operation failed."
|
msgid "Read/write operation failed."
|
||||||
msgstr "Operațiunea a eșuat."
|
msgstr "Operațiunea a eșuat."
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:115
|
#: lib/solaar/ui/notify.py:120
|
||||||
msgid "unpaired"
|
|
||||||
msgstr "deconectat(ă)"
|
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116
|
|
||||||
msgid "connected"
|
msgid "connected"
|
||||||
msgstr "conectat(ă)"
|
msgstr "conectat(ă)"
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||||
msgid "offline"
|
msgid "offline"
|
||||||
msgstr "inactivă"
|
msgstr "inactivă"
|
||||||
|
|
||||||
|
@ -323,11 +323,11 @@ msgstr "Nu am găsit nici un receptor Logitech"
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr "Ieșire"
|
msgstr "Ieșire"
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:269
|
#: lib/solaar/ui/tray.py:274
|
||||||
msgid "no receiver"
|
msgid "no receiver"
|
||||||
msgstr "nici un receptor"
|
msgstr "nici un receptor"
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:288
|
#: lib/solaar/ui/tray.py:293
|
||||||
msgid "no status"
|
msgid "no status"
|
||||||
msgstr "stare necunoscută"
|
msgstr "stare necunoscută"
|
||||||
|
|
||||||
|
@ -365,75 +365,75 @@ msgstr "periferice conectate"
|
||||||
msgid "Only one device can be paired to this receiver"
|
msgid "Only one device can be paired to this receiver"
|
||||||
msgstr "Acest receptor suportă un singur periferic conectat"
|
msgstr "Acest receptor suportă un singur periferic conectat"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:113
|
#: lib/solaar/ui/window.py:110
|
||||||
msgid "Scanning"
|
msgid "Scanning"
|
||||||
msgstr "Caut"
|
msgstr "Caut"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:149
|
#: lib/solaar/ui/window.py:146
|
||||||
msgid "Wireless Link"
|
msgid "Wireless Link"
|
||||||
msgstr "Legatură fără fir"
|
msgstr "Legatură fără fir"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:182
|
#: lib/solaar/ui/window.py:179
|
||||||
msgid "Show Technical Details"
|
msgid "Show Technical Details"
|
||||||
msgstr "Detalii tehnice"
|
msgstr "Detalii tehnice"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:195
|
#: lib/solaar/ui/window.py:192
|
||||||
msgid "Pair new device"
|
msgid "Pair new device"
|
||||||
msgstr "Conectează periferic"
|
msgstr "Conectează periferic"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:214
|
#: lib/solaar/ui/window.py:211
|
||||||
msgid "Select a device"
|
msgid "Select a device"
|
||||||
msgstr "Selectați un dispozitiv"
|
msgstr "Selectați un dispozitiv"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:511
|
#: lib/solaar/ui/window.py:508
|
||||||
msgid "Path"
|
msgid "Path"
|
||||||
msgstr "Cale"
|
msgstr "Cale"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:513
|
#: lib/solaar/ui/window.py:510
|
||||||
msgid "USB id"
|
msgid "USB id"
|
||||||
msgstr "USB"
|
msgstr "USB"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||||
msgid "Serial"
|
msgid "Serial"
|
||||||
msgstr "Serial"
|
msgstr "Serial"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:522
|
#: lib/solaar/ui/window.py:519
|
||||||
msgid "Index"
|
msgid "Index"
|
||||||
msgstr "Index"
|
msgstr "Index"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:523
|
#: lib/solaar/ui/window.py:520
|
||||||
msgid "Wireless PID"
|
msgid "Wireless PID"
|
||||||
msgstr "Cod WPID"
|
msgstr "Cod WPID"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:525
|
#: lib/solaar/ui/window.py:522
|
||||||
msgid "Protocol"
|
msgid "Protocol"
|
||||||
msgstr "Protocol"
|
msgstr "Protocol"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:527
|
#: lib/solaar/ui/window.py:524
|
||||||
msgid "Polling rate"
|
msgid "Polling rate"
|
||||||
msgstr "Rată acces"
|
msgstr "Rată acces"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:542
|
#: lib/solaar/ui/window.py:539
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr "nici una"
|
msgstr "nici una"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:543
|
#: lib/solaar/ui/window.py:540
|
||||||
msgid "Notifications"
|
msgid "Notifications"
|
||||||
msgstr "Notificări"
|
msgstr "Notificări"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:638
|
#: lib/solaar/ui/window.py:635
|
||||||
msgid "charging"
|
msgid "charging"
|
||||||
msgstr "se încarcă"
|
msgstr "se încarcă"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:640
|
#: lib/solaar/ui/window.py:637
|
||||||
msgid "last known"
|
msgid "last known"
|
||||||
msgstr "ultima valoare"
|
msgstr "ultima valoare"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:647
|
#: lib/solaar/ui/window.py:644
|
||||||
msgid "not encrypted"
|
msgid "not encrypted"
|
||||||
msgstr "ne-criptată"
|
msgstr "ne-criptată"
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:651
|
#: lib/solaar/ui/window.py:648
|
||||||
msgid "encrypted"
|
msgid "encrypted"
|
||||||
msgstr "criptată"
|
msgstr "criptată"
|
||||||
|
|
|
@ -7,7 +7,11 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr "Project-Id-Version: solaar 0.9.2\n"
|
msgstr "Project-Id-Version: solaar 0.9.2\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
<<<<<<< HEAD
|
||||||
"POT-Creation-Date: 2013-08-05 18:51+0300\n"
|
"POT-Creation-Date: 2013-08-05 18:51+0300\n"
|
||||||
|
=======
|
||||||
|
"POT-Creation-Date: 2013-08-08 22:21+0200\n"
|
||||||
|
>>>>>>> master
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -80,7 +84,7 @@ msgstr ""
|
||||||
msgid "Bootloader"
|
msgid "Bootloader"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:538
|
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||||
msgid "Firmware"
|
msgid "Firmware"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -104,11 +108,15 @@ msgstr ""
|
||||||
msgid "pairing lock is "
|
msgid "pairing lock is "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||||
|
msgid "unpaired"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/notifications.py:192
|
#: lib/logitech_receiver/notifications.py:192
|
||||||
msgid "powered on"
|
msgid "powered on"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:625
|
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||||
msgid "unknown"
|
msgid "unknown"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -168,16 +176,16 @@ msgstr ""
|
||||||
msgid " paired devices."
|
msgid " paired devices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:153 lib/logitech_receiver/status.py:155
|
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||||
#: lib/solaar/ui/window.py:146
|
#: lib/solaar/ui/window.py:143
|
||||||
msgid "Battery"
|
msgid "Battery"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:153
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||||
msgid "Lighting"
|
msgid "Lighting"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/logitech_receiver/status.py:161 lib/solaar/ui/window.py:666
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||||
msgid "lux"
|
msgid "lux"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -185,31 +193,31 @@ msgstr ""
|
||||||
msgid "The receiver was unplugged."
|
msgid "The receiver was unplugged."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:69
|
#: lib/solaar/ui/__init__.py:48
|
||||||
msgid "Permissions error"
|
msgid "Permissions error"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:70
|
#: lib/solaar/ui/__init__.py:49
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||||
"it."
|
"it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:72
|
#: lib/solaar/ui/__init__.py:51
|
||||||
msgid "If you've just installed Solaar, try removing the receiver and "
|
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||||
"plugging it back in."
|
"plugging it back in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:74
|
#: lib/solaar/ui/__init__.py:53
|
||||||
msgid "Unpairing failed"
|
msgid "Unpairing failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:75
|
#: lib/solaar/ui/__init__.py:54
|
||||||
#, python-format
|
#, python-brace-format
|
||||||
msgid "Failed to unpair %s from %s."
|
msgid "Failed to unpair %{device} from %{receiver}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/__init__.py:77
|
#: lib/solaar/ui/__init__.py:56
|
||||||
msgid "The receiver returned an error, with no further details."
|
msgid "The receiver returned an error, with no further details."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -230,12 +238,12 @@ msgstr ""
|
||||||
msgid "Logitech documentation"
|
msgid "Logitech documentation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:319
|
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||||
msgid "About"
|
msgid "About"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||||
#: lib/solaar/ui/window.py:206
|
#: lib/solaar/ui/window.py:203
|
||||||
msgid "Unpair"
|
msgid "Unpair"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -247,16 +255,12 @@ msgstr ""
|
||||||
msgid "Read/write operation failed."
|
msgid "Read/write operation failed."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:115
|
#: lib/solaar/ui/notify.py:120
|
||||||
msgid "unpaired"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116
|
|
||||||
msgid "connected"
|
msgid "connected"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/notify.py:116 lib/solaar/ui/tray.py:285
|
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||||
#: lib/solaar/ui/tray.py:290 lib/solaar/ui/window.py:656
|
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||||
msgid "offline"
|
msgid "offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -312,11 +316,11 @@ msgstr ""
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:269
|
#: lib/solaar/ui/tray.py:274
|
||||||
msgid "no receiver"
|
msgid "no receiver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/tray.py:288
|
#: lib/solaar/ui/tray.py:293
|
||||||
msgid "no status"
|
msgid "no status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -354,75 +358,75 @@ msgstr ""
|
||||||
msgid "Only one device can be paired to this receiver"
|
msgid "Only one device can be paired to this receiver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:113
|
#: lib/solaar/ui/window.py:110
|
||||||
msgid "Scanning"
|
msgid "Scanning"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:149
|
#: lib/solaar/ui/window.py:146
|
||||||
msgid "Wireless Link"
|
msgid "Wireless Link"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:182
|
#: lib/solaar/ui/window.py:179
|
||||||
msgid "Show Technical Details"
|
msgid "Show Technical Details"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:195
|
#: lib/solaar/ui/window.py:192
|
||||||
msgid "Pair new device"
|
msgid "Pair new device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:214
|
#: lib/solaar/ui/window.py:211
|
||||||
msgid "Select a device"
|
msgid "Select a device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:511
|
#: lib/solaar/ui/window.py:508
|
||||||
msgid "Path"
|
msgid "Path"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:513
|
#: lib/solaar/ui/window.py:510
|
||||||
msgid "USB id"
|
msgid "USB id"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:516 lib/solaar/ui/window.py:518
|
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||||
#: lib/solaar/ui/window.py:530 lib/solaar/ui/window.py:532
|
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||||
msgid "Serial"
|
msgid "Serial"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:522
|
#: lib/solaar/ui/window.py:519
|
||||||
msgid "Index"
|
msgid "Index"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:523
|
#: lib/solaar/ui/window.py:520
|
||||||
msgid "Wireless PID"
|
msgid "Wireless PID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:525
|
#: lib/solaar/ui/window.py:522
|
||||||
msgid "Protocol"
|
msgid "Protocol"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:527
|
#: lib/solaar/ui/window.py:524
|
||||||
msgid "Polling rate"
|
msgid "Polling rate"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:542
|
#: lib/solaar/ui/window.py:539
|
||||||
msgid "none"
|
msgid "none"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:543
|
#: lib/solaar/ui/window.py:540
|
||||||
msgid "Notifications"
|
msgid "Notifications"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:638
|
#: lib/solaar/ui/window.py:635
|
||||||
msgid "charging"
|
msgid "charging"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:640
|
#: lib/solaar/ui/window.py:637
|
||||||
msgid "last known"
|
msgid "last known"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:647
|
#: lib/solaar/ui/window.py:644
|
||||||
msgid "not encrypted"
|
msgid "not encrypted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: lib/solaar/ui/window.py:651
|
#: lib/solaar/ui/window.py:648
|
||||||
msgid "encrypted"
|
msgid "encrypted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -0,0 +1,451 @@
|
||||||
|
# Swedish translations for solaar package.
|
||||||
|
# Copyright (C) 2013 THE solaar'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the solaar package.
|
||||||
|
# Automatically generated, 2013.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr "Project-Id-Version: solaar 0.9.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2013-08-08 19:46+0200\n"
|
||||||
|
"PO-Revision-Date: 2013-07-27 16:28+0100\n"
|
||||||
|
"Last-Translator: Daniel Zippert & Emelie Snecker <daniel@zippert."
|
||||||
|
"se>\n"
|
||||||
|
"Language-Team: none\n"
|
||||||
|
"Language: sv\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"X-Generator: Poedit 1.5.4\n"
|
||||||
|
"X-Poedit-Basepath: /pwr/Solaar/po\n"
|
||||||
|
"X-Poedit-SearchPath-0: /pwr/Solaar/po\n"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "critical"
|
||||||
|
msgstr "kritisk"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "empty"
|
||||||
|
msgstr "tom"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38 lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "full"
|
||||||
|
msgstr "full"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "good"
|
||||||
|
msgstr "normal"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:38
|
||||||
|
msgid "low"
|
||||||
|
msgstr "låg"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "almost full"
|
||||||
|
msgstr "nästan full"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "discharging"
|
||||||
|
msgstr "laddar ur"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:41
|
||||||
|
msgid "recharging"
|
||||||
|
msgstr "laddar"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "invalid battery"
|
||||||
|
msgstr "batterifel"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "slow recharge"
|
||||||
|
msgstr "långsam laddning"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:42
|
||||||
|
msgid "thermal error"
|
||||||
|
msgstr "termiskt fel"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "device not supported"
|
||||||
|
msgstr "enheten stöds inte"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "device timeout"
|
||||||
|
msgstr "enheten svarde inte i tid"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "sequence timeout"
|
||||||
|
msgstr "sekvens timout"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:45
|
||||||
|
msgid "too many devices"
|
||||||
|
msgstr "för många enheter"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Bootloader"
|
||||||
|
msgstr "Bootloader"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48 lib/solaar/ui/window.py:535
|
||||||
|
msgid "Firmware"
|
||||||
|
msgstr "Firmware"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Hardware"
|
||||||
|
msgstr "Hårdvara"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/i18n.py:48
|
||||||
|
msgid "Other"
|
||||||
|
msgstr "Annan"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "closed"
|
||||||
|
msgstr "låst"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "open"
|
||||||
|
msgstr "öppen"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:67
|
||||||
|
msgid "pairing lock is "
|
||||||
|
msgstr "parkopplingsläge låst"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:150 lib/solaar/ui/notify.py:118
|
||||||
|
msgid "unpaired"
|
||||||
|
msgstr "inte parkopplad"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/notifications.py:192
|
||||||
|
msgid "powered on"
|
||||||
|
msgstr "påslagen"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/receiver.py:107 lib/solaar/ui/window.py:622
|
||||||
|
msgid "unknown"
|
||||||
|
msgstr "okänd"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:77
|
||||||
|
msgid "Smooth Scrolling"
|
||||||
|
msgstr "Mjuk Scrollning"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:78
|
||||||
|
msgid "High-sensitivity mode for vertical scroll with the wheel."
|
||||||
|
msgstr "Hög känslighet för scrollhjulet. "
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:79
|
||||||
|
msgid "Side Scrolling"
|
||||||
|
msgstr "Vertikal Scrollning"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:80
|
||||||
|
msgid "When disabled, pushing the wheel sideways sends custom button "
|
||||||
|
"events\n"
|
||||||
|
"instead of the standard side-scrolling events."
|
||||||
|
msgstr "Vid avaktivering, kommer tryckningar sidledes på scrollhjulet\n"
|
||||||
|
"fungera som specialknappar istället för standard sidscrolling."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:82
|
||||||
|
msgid "Sensitivity (DPI)"
|
||||||
|
msgstr "Känslighet (DPI)"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:83
|
||||||
|
msgid "Swap Fx function"
|
||||||
|
msgstr "Skifta funktionen för F1-12 tangenterna"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:84
|
||||||
|
msgid "When set, the F1..F12 keys will activate their special function,\n"
|
||||||
|
"and you must hold the FN key to activate their standard function."
|
||||||
|
msgstr "Vid aktivering, kommer F1-12 tangenterna få sina specialfunktioner,\n"
|
||||||
|
"och du behöver trycka ned FN tangenten för att komma åt dess normala "
|
||||||
|
"funktioner."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:87
|
||||||
|
msgid "When unset, the F1..F12 keys will activate their standard function,\n"
|
||||||
|
"and you must hold the FN key to activate their special function."
|
||||||
|
msgstr "Vid avaktivering, kommer F1-12 tangenterna få sina "
|
||||||
|
"standardfunktioner,\n"
|
||||||
|
"och du behöver trycka ned FN tangenten för att komma åt dess "
|
||||||
|
"spesicalfunktioner."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:89
|
||||||
|
msgid "Hand Detection"
|
||||||
|
msgstr "Handavkänning"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/settings_templates.py:90
|
||||||
|
msgid "Turn on illumination when the hands hover over the keyboard."
|
||||||
|
msgstr "Tänd belysning, om en hand hålls över tangentbordet. "
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:98
|
||||||
|
msgid "No paired devices."
|
||||||
|
msgstr "Inga enheter är parkopplade"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:99
|
||||||
|
msgid "1 paired device."
|
||||||
|
msgstr "1 parkopplad enhet."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:100
|
||||||
|
msgid " paired devices."
|
||||||
|
msgstr "parkopplade enheter."
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:149 lib/logitech_receiver/status.py:151
|
||||||
|
#: lib/solaar/ui/window.py:143
|
||||||
|
msgid "Battery"
|
||||||
|
msgstr "Batteri"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:150
|
||||||
|
msgid "Lighting"
|
||||||
|
msgstr "Belysning"
|
||||||
|
|
||||||
|
#: lib/logitech_receiver/status.py:162 lib/solaar/ui/window.py:663
|
||||||
|
msgid "lux"
|
||||||
|
msgstr "lux"
|
||||||
|
|
||||||
|
#: lib/solaar/listener.py:95
|
||||||
|
msgid "The receiver was unplugged."
|
||||||
|
msgstr "Mottagaren kopplades ur"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:48
|
||||||
|
msgid "Permissions error"
|
||||||
|
msgstr "Behörighetsfel"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:49
|
||||||
|
#, python-format
|
||||||
|
msgid "Found a Logitech Receiver (%s), but did not have permission to open "
|
||||||
|
"it."
|
||||||
|
msgstr "En Logitech mottagare hittades (%s), men behörighet att använda "
|
||||||
|
"den saknas."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:51
|
||||||
|
msgid "If you've just installed Solaar, try removing the receiver and "
|
||||||
|
"plugging it back in."
|
||||||
|
msgstr "Om du just installerade solaar, prova koppla ur mottagaren och "
|
||||||
|
"anslut den sedan igen. "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:53
|
||||||
|
msgid "Unpairing failed"
|
||||||
|
msgstr "Kunde inte bryta parkoppling."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:54
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Failed to unpair %{device} from %{receiver}."
|
||||||
|
msgstr "Misslyckades att bryta parkoppling mellan %{device} och %{receiver}."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/__init__.py:56
|
||||||
|
msgid "The receiver returned an error, with no further details."
|
||||||
|
msgstr "Mottagaren rapporterade ett fel, utan specifika detaljer."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:39
|
||||||
|
msgid "Shows status of devices connected\n"
|
||||||
|
"through wireless Logitech receivers."
|
||||||
|
msgstr "Visa status för enheter kopplade till\n"
|
||||||
|
"din trådlösa Logitech mottagare"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:48
|
||||||
|
msgid "GUI design"
|
||||||
|
msgstr "GUI utseende"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:49
|
||||||
|
msgid "Testing"
|
||||||
|
msgstr "Prövar"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/about.py:54
|
||||||
|
msgid "Logitech documentation"
|
||||||
|
msgstr "Logitech dokumentation"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/action.py:68 lib/solaar/ui/window.py:316
|
||||||
|
msgid "About"
|
||||||
|
msgstr "Om"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/action.py:95 lib/solaar/ui/action.py:98
|
||||||
|
#: lib/solaar/ui/window.py:203
|
||||||
|
msgid "Unpair"
|
||||||
|
msgstr "Ta bort parkoppling"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/config_panel.py:97
|
||||||
|
msgid "Working"
|
||||||
|
msgstr "Lyckades"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/config_panel.py:100
|
||||||
|
msgid "Read/write operation failed."
|
||||||
|
msgstr "Läsning/Skrivning misslyckades."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/notify.py:120
|
||||||
|
msgid "connected"
|
||||||
|
msgstr "ansluten"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/notify.py:122 lib/solaar/ui/tray.py:290
|
||||||
|
#: lib/solaar/ui/tray.py:295 lib/solaar/ui/window.py:653
|
||||||
|
msgid "offline"
|
||||||
|
msgstr "avstängd"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:133
|
||||||
|
msgid "Pairing failed"
|
||||||
|
msgstr "Parkoppling misslyckades"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:135
|
||||||
|
msgid "Make sure your device is within range, and has a decent battery "
|
||||||
|
"charge."
|
||||||
|
msgstr "Se till så att enheten inom räckhåll, och har tillräckligt laddat "
|
||||||
|
"batteri. "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:137
|
||||||
|
msgid "A new device was detected, but it is not compatible with this "
|
||||||
|
"receiver."
|
||||||
|
msgstr "En ny enhet upptäcktes, men är inte kompatibel med mottagaren. "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:139
|
||||||
|
#, python-format
|
||||||
|
msgid "The receiver only supports %d paired device(s)."
|
||||||
|
msgstr "Mottagaren klarar bara %d parkopplad(e) enhet(er)."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:141
|
||||||
|
msgid "No further details are available about the error."
|
||||||
|
msgstr "Ingen mer information är tillgänglig om felet. "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:155
|
||||||
|
msgid "Found a new device"
|
||||||
|
msgstr "Ny enhet har hittats"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:180
|
||||||
|
msgid "The wireless link is not encrypted"
|
||||||
|
msgstr "Den trådlösa anslutningen är okrypterad"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:197
|
||||||
|
msgid "pair new device"
|
||||||
|
msgstr "parkoppla ny enhet"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:205
|
||||||
|
msgid "Turn on the device you want to pair."
|
||||||
|
msgstr "Sätt på enheten du vill parkoppla."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/pair_window.py:206
|
||||||
|
msgid "If the device is already turned on,\n"
|
||||||
|
"turn if off and on again."
|
||||||
|
msgstr "Om enheten redan är igång,\n"
|
||||||
|
"stäng av den och sätt på den igen."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:55
|
||||||
|
msgid "No Logitech receiver found"
|
||||||
|
msgstr "Ingen Logitech motagare hittades"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:62
|
||||||
|
msgid "Quit"
|
||||||
|
msgstr "Stäng"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:274
|
||||||
|
msgid "no receiver"
|
||||||
|
msgstr "ingen mottagare"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/tray.py:293
|
||||||
|
msgid "no status"
|
||||||
|
msgstr "ingen status"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:58
|
||||||
|
msgid "The wireless link between this device and its receiver is encrypted."
|
||||||
|
msgstr "Den trådlösa anslutningen är krypterad."
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:59
|
||||||
|
msgid "The wireless link between this device and its receiver is not "
|
||||||
|
"encrypted.\n"
|
||||||
|
"\n"
|
||||||
|
"For pointing devices (mice, trackballs, trackpads), this is a minor "
|
||||||
|
"security issue.\n"
|
||||||
|
"\n"
|
||||||
|
"It is, however, a major security issue for text-input devices "
|
||||||
|
"(keyboards, numpads),\n"
|
||||||
|
"because typed text can be sniffed inconspicuously by 3rd parties "
|
||||||
|
"within range."
|
||||||
|
msgstr "Den trådlösa anslutningen mellan den här enheten och mottagaren är "
|
||||||
|
"okrypterad\n"
|
||||||
|
"\n"
|
||||||
|
"For pekdon (möss, styrkulor, pekplattor), är detta inget stort "
|
||||||
|
"säkerhetsproblem.\n"
|
||||||
|
"\n"
|
||||||
|
"Men för textinmatande enheter (tangentbord, numpads) är denna "
|
||||||
|
"säkerhetsbrist allvarlig, eftersom skriven text obemärkt kan fångas "
|
||||||
|
"upp av tredje part som befinner sig inom enhetens räckhåll. "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:71
|
||||||
|
msgid "No device paired"
|
||||||
|
msgstr "Inga enheter parkopplade"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:67 lib/solaar/ui/window.py:68
|
||||||
|
#, python-format
|
||||||
|
msgid "Up to %d devices can be paired to this receiver"
|
||||||
|
msgstr "Upp till %d enheter kan parkopplas till mottagaren"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:68
|
||||||
|
msgid "paired devices"
|
||||||
|
msgstr "parkopplade enheter"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:72
|
||||||
|
msgid "Only one device can be paired to this receiver"
|
||||||
|
msgstr "Bara en enhet kan parkopplas till den här mottagaren"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:110
|
||||||
|
msgid "Scanning"
|
||||||
|
msgstr "Söker"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:146
|
||||||
|
msgid "Wireless Link"
|
||||||
|
msgstr "Trådlös anslutning"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:179
|
||||||
|
msgid "Show Technical Details"
|
||||||
|
msgstr "Visa Tekniska Detaljer"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:192
|
||||||
|
msgid "Pair new device"
|
||||||
|
msgstr "Parkoppla en ny enhet"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:211
|
||||||
|
msgid "Select a device"
|
||||||
|
msgstr "Välj en enhet"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:508
|
||||||
|
msgid "Path"
|
||||||
|
msgstr "Sökväg"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:510
|
||||||
|
msgid "USB id"
|
||||||
|
msgstr "USB id"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:513 lib/solaar/ui/window.py:515
|
||||||
|
#: lib/solaar/ui/window.py:527 lib/solaar/ui/window.py:529
|
||||||
|
msgid "Serial"
|
||||||
|
msgstr "Seriell"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:519
|
||||||
|
msgid "Index"
|
||||||
|
msgstr "Index"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:520
|
||||||
|
msgid "Wireless PID"
|
||||||
|
msgstr "Trådlös PID"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:522
|
||||||
|
msgid "Protocol"
|
||||||
|
msgstr "Protokoll"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:524
|
||||||
|
msgid "Polling rate"
|
||||||
|
msgstr "Uppdateringshastighet"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:539
|
||||||
|
msgid "none"
|
||||||
|
msgstr "ingen"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:540
|
||||||
|
msgid "Notifications"
|
||||||
|
msgstr "Notifikation "
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:635
|
||||||
|
msgid "charging"
|
||||||
|
msgstr "laddar"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:637
|
||||||
|
msgid "last known"
|
||||||
|
msgstr "senast kända"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:644
|
||||||
|
msgid "not encrypted"
|
||||||
|
msgstr "okrypterad"
|
||||||
|
|
||||||
|
#: lib/solaar/ui/window.py:648
|
||||||
|
msgid "encrypted"
|
||||||
|
msgstr "krypterad"
|
|
@ -80,8 +80,8 @@ done
|
||||||
|
|
||||||
# create packages/ sub-directory
|
# create packages/ sub-directory
|
||||||
/bin/mkdir --parents "$SITE/../packages" "$SITE/packages/"
|
/bin/mkdir --parents "$SITE/../packages" "$SITE/packages/"
|
||||||
/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar_* || true
|
#/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar_* || true
|
||||||
/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar-gnome3_* || true
|
#/bin/cp --archive --update --target-directory="$SITE/../packages/" "$SELF/dist/debian"/solaar-gnome3_* || true
|
||||||
if test -x /usr/bin/dpkg-scanpackages; then
|
if test -x /usr/bin/dpkg-scanpackages; then
|
||||||
cd "$SITE/../packages/"
|
cd "$SITE/../packages/"
|
||||||
/bin/rm --force *.build
|
/bin/rm --force *.build
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if test -z "$1"; then
|
|
||||||
echo "Use: $0 <locale>"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
LL_CC="$1"
|
|
||||||
shift
|
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
if test "$1" = "-h" -o "$1" = "--help"; then
|
||||||
|
echo "Use: $0 [<language>]"
|
||||||
|
echo "Run without arguments to update all translation files."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
cd "$(readlink -f "$(dirname "$0")/..")"
|
cd "$(readlink -f "$(dirname "$0")/..")"
|
||||||
|
|
||||||
VERSION=$(python setup.py --version)
|
VERSION=$(python setup.py --version)
|
||||||
|
@ -33,18 +32,11 @@ POT_FILE="$POT_DIR/$DOMAIN.pot"
|
||||||
|
|
||||||
/bin/sed --in-place --expression="s/charset=CHARSET/charset=UTF-8/" "$POT_FILE"
|
/bin/sed --in-place --expression="s/charset=CHARSET/charset=UTF-8/" "$POT_FILE"
|
||||||
|
|
||||||
PO_FILE="$POT_DIR/$LL_CC.po"
|
|
||||||
|
|
||||||
test -r "$PO_FILE" || /usr/bin/msginit \
|
|
||||||
--no-translator --locale="$LL_CC" \
|
|
||||||
--input="$POT_FILE" \
|
|
||||||
--output-file="$PO_FILE"
|
|
||||||
|
|
||||||
unfmt() {
|
unfmt() {
|
||||||
local SOURCE="/usr/share/locale/$LL_CC/LC_MESSAGES/$1.mo"
|
local SOURCE="/usr/share/locale/$LL_CC/LC_MESSAGES/$1.mo"
|
||||||
if [ ! -f $SOURCE ]
|
if test ! -f "$SOURCE"; then
|
||||||
then
|
SOURCE="/usr/share/locale-langpack/$LL_CC/LC_MESSAGES/$1.mo"
|
||||||
local SOURCE="/usr/share/locale-langpack/$LL_CC/LC_MESSAGES/$1.mo"
|
|
||||||
fi
|
fi
|
||||||
local TARGET="$(mktemp --tmpdir $1-$LL_CC-XXXXXX.po)"
|
local TARGET="$(mktemp --tmpdir $1-$LL_CC-XXXXXX.po)"
|
||||||
/usr/bin/msgunfmt \
|
/usr/bin/msgunfmt \
|
||||||
|
@ -54,14 +46,32 @@ unfmt() {
|
||||||
echo "$TARGET"
|
echo "$TARGET"
|
||||||
}
|
}
|
||||||
|
|
||||||
/usr/bin/msgmerge \
|
update_po() {
|
||||||
--update --no-fuzzy-matching \
|
local LL_CC="$1"
|
||||||
--no-escape --indent --add-location --sort-by-file \
|
local PO_FILE="$POT_DIR/$LL_CC.po"
|
||||||
--lang="$LL_CC" \
|
|
||||||
--compendium="$(unfmt gtk30)" \
|
|
||||||
--compendium="$(unfmt gtk30-properties)" \
|
|
||||||
"$PO_FILE" "$POT_FILE"
|
|
||||||
|
|
||||||
# /bin/sed --in-place --expression="s/Language: \\\\n/Language: $L_NAME\\\\n/" "$PO_FILE"
|
test -r "$PO_FILE" || /usr/bin/msginit \
|
||||||
|
--no-translator --locale="$LL_CC" \
|
||||||
|
--input="$POT_FILE" \
|
||||||
|
--output-file="$PO_FILE"
|
||||||
|
|
||||||
echo "Language file is $PO_FILE"
|
/usr/bin/msgmerge \
|
||||||
|
--update --no-fuzzy-matching \
|
||||||
|
--no-escape --indent --add-location --sort-by-file \
|
||||||
|
--lang="$LL_CC" \
|
||||||
|
--compendium="$(unfmt gtk30)" \
|
||||||
|
--compendium="$(unfmt gtk30-properties)" \
|
||||||
|
"$PO_FILE" "$POT_FILE"
|
||||||
|
|
||||||
|
# /bin/sed --in-place --expression="s/Language: \\\\n/Language: $L_NAME\\\\n/" "$PO_FILE"
|
||||||
|
echo "Updated $PO_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
if test "$1"; then
|
||||||
|
update_po "$1"
|
||||||
|
else
|
||||||
|
for l in $(ls -1 "$POT_DIR"/??.po); do
|
||||||
|
l="$(basename "$l")"
|
||||||
|
update_po "${l%.po}"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
Loading…
Reference in New Issue