Example #1
0
def run(cli_args=None, hidraw_path=None):
	if cli_args:
		action = cli_args[0]
		args = _cli_parser.parse_args(cli_args)
	else:
		args = _cli_parser.parse_args()
		# Python 3 has an undocumented 'feature' that breaks parsing empty args
		# http://bugs.python.org/issue16308
		if not 'cmd' in args:
			_cli_parser.print_usage(_sys.stderr)
			_sys.stderr.write('%s: error: too few arguments\n' % NAME.lower())
			_sys.exit(2)
		action = args.action
	assert action in actions

	try:
		c = list(_receivers(hidraw_path))
		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))
Example #2
0
def run(cli_args=None, hidraw_path=None):
    if cli_args:
        action = cli_args[0]
        args = _cli_parser.parse_args(cli_args)
    else:
        args = _cli_parser.parse_args()
        # Python 3 has an undocumented 'feature' that breaks parsing empty args
        # http://bugs.python.org/issue16308
        if not 'cmd' in args:
            _cli_parser.print_usage(_sys.stderr)
            _sys.stderr.write('%s: error: too few arguments\n' % NAME.lower())
            _sys.exit(2)
        action = args.action
    assert action in actions

    try:
        c = list(_receivers(hidraw_path))
        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 AssertionError as e:
        from traceback import extract_tb
        tb_last = extract_tb(_sys.exc_info()[2])[-1]
        _sys.exit('%s: assertion failed: %s line %d' %
                  (NAME.lower(), tb_last[0], tb_last[1]))
    except Exception as e:
        _sys.exit('%s: error: %s' % (NAME.lower(), e))
Example #3
0
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 number, '
        'a substring of a device\'s name, or "all" (the default)'
    )
    sp.set_defaults(action='show')

    sp = subparsers.add_parser('probe', help='probe a receiver (debugging use only)')
    sp.add_argument(
        'receiver', nargs='?', help='select receiver by name substring or serial number when more than one is present'
    )
    sp.set_defaults(action='probe')

    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 serial number, '
        'or a substring of a device\'s name'
    )
    sp.add_argument('setting', nargs='?', help='device-specific setting; leave empty to list available settings')
    sp.add_argument('value_key', nargs='?', help='new value for the setting or key for keyed settings')
    sp.add_argument('extra_subkey', nargs='?', help='value for keyed or subkey for subkeyed settings')
    sp.add_argument('extra2', nargs='?', help='value for subkeyed settings')
    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 receiver by name substring or serial number 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 number, '
        'or a substring of a device\'s name.'
    )
    sp.set_defaults(action='unpair')

    return parser, subparsers.choices
Example #4
0
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
	_model = Gtk.TreeStore(*_COLUMN_TYPES)
	_tree = _create_tree(_model)
	_details = _create_details_panel()
	_info = _create_info_panel()
	_empty = _create_empty_panel()
	_window = _create()
Example #5
0
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
    _model = Gtk.TreeStore(*_COLUMN_TYPES)
    _tree = _create_tree(_model)
    _details = _create_details_panel()
    _info = _create_info_panel()
    _empty = _create_empty_panel()
    _window = _create()
Example #6
0
def init(show_window, hide_on_close):
    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
    _model = Gtk.TreeStore(*_COLUMN_TYPES)
    _tree = _create_tree(_model)
    _details = _create_details_panel()
    _info = _create_info_panel()
    _empty = _create_empty_panel()
    _window = _create(_hide if hide_on_close else destroy)
    if show_window:
        _window.present()
Example #7
0
def main():
    _require('pyudev', 'python-pyudev')
    _require('gi.repository', 'python-gi')
    _require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
    _parse_arguments()

    # handle ^C in console
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    try:
        import solaar.ui as ui
        ui.init()

        import solaar.listener as listener
        listener.setup_scanner(ui.status_changed, ui.error_dialog)
        listener.start_all()

        # main UI event loop
        ui.run_loop()

        listener.stop_all()
    except Exception as e:
        import sys
        sys.exit('%s: error: %s' % (NAME.lower(), e))
Example #8
0
def _parse_arguments():
    import argparse
    arg_parser = argparse.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__)
    args = arg_parser.parse_args()

    import logging
    if args.debug > 0:
        log_level = logging.WARNING - 10 * args.debug
        log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

    if logging.root.isEnabledFor(logging.INFO):
        logging.info("language %s (%s), translations path %s", _i18n.language,
                     _i18n.encoding, _i18n.path)

    return args
Example #9
0
def main():
    _require('pyudev', 'python3-pyudev')

    # handle ^C in console
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    signal.signal(signal.SIGINT, _handlesigint)

    args = _parse_arguments()
    if not args:
        return
    if args.action:
        # if any argument, run comandline and exit
        return _cli.run(args.action, args.hidraw_path)

    gi = _require('gi', 'python3-gi or python3-gobject')
    _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0')

    try:
        import solaar.ui as ui
        import solaar.listener as listener
        listener.setup_scanner(ui.status_changed, ui.error_dialog)

        import solaar.upower as _upower
        if args.restart_on_wake_up:
            _upower.watch(listener.start_all, listener.stop_all)
        else:
            _upower.watch(lambda: listener.ping_all(True))

        # main UI event loop
        ui.run_loop(listener.start_all, listener.stop_all, args.window != 'only', args.window != 'hide')
    except Exception:
        import sys
        from traceback import format_exc
        sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
Example #10
0
def _create():
    about = Gtk.AboutDialog()

    about.set_program_name(NAME)
    about.set_version(__version__)
    about.set_comments(
        _('Manages Logitech receivers,\nkeyboards, mice, and tablets.'))
    about.set_logo_icon_name(NAME.lower())

    about.set_copyright(
        '© 2012-2021 Daniel Pavel and contributors to the Solaar project')
    about.set_license_type(Gtk.License.GPL_2_0)

    about.set_authors(('Daniel Pavel http://github.com/pwr', ))
    try:
        about.add_credit_section(_('Additional Programming'),
                                 ('Filipe Laíns', 'Peter F. Patel-Schneider'))
        about.add_credit_section(_('GUI design'),
                                 ('Julien Gascard', 'Daniel Pavel'))
        about.add_credit_section(_('Testing'), (
            'Douglas Wagner',
            'Julien Gascard',
            'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html',
        ))
        about.add_credit_section(_('Logitech documentation'), (
            'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower',
            'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28',
        ))
    except TypeError:
        # gtk3 < ~3.6.4 has incorrect gi bindings
        import logging
        logging.exception('failed to fully create the about dialog')
    except Exception:
        # the Gtk3 version may be too old, and the function does not exist
        import logging
        logging.exception('failed to fully create the about dialog')

    about.set_translator_credits('\n'.join((
        'gogo (croatian)',
        'Papoteur, David Geiger, Damien Lallement (français)',
        'Michele Olivo (italiano)',
        'Adrian Piotrowicz (polski)',
        'Drovetto, JrBenito (Portuguese-BR)',
        'Daniel Pavel (română)',
        'Daniel Zippert, Emelie Snecker (svensk)',
        'Dimitriy Ryazantcev (Russian)',
    )))

    about.set_website('https://pwr-solaar.github.io/Solaar')
    about.set_website_label(NAME)

    about.connect('response', lambda x, y: x.hide())

    def _hide(dialog, event):
        dialog.hide()
        return True

    about.connect('delete-event', _hide)

    return about
Example #11
0
    def show(dev, reason=None, icon=None):
        """Show a notification with title and text."""
        if available and Notify.is_initted():
            summary = dev.name

            # if a notification with same name is already visible, reuse it to avoid spamming
            n = _notifications.get(summary)
            if n is None:
                n = _notifications[summary] = Notify.Notification()

            if reason:
                message = reason
            elif dev.status is None:
                message = _('unpaired')
            elif bool(dev.status):
                message = dev.status.to_string() or _('connected')
            else:
                message = _('offline')

            # we need to use the filename here because the notifications daemon
            # is an external application that does not know about our icon sets
            icon_file = _icons.device_icon_file(
                dev.name, dev.kind) if icon is None else _icons.icon_file(icon)

            n.update(summary, message, icon_file)
            urgency = Notify.Urgency.LOW if dev.status else Notify.Urgency.NORMAL
            n.set_urgency(urgency)
            n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower()))

            try:
                # if _log.isEnabledFor(_DEBUG):
                #     _log.debug("showing %s", n)
                n.show()
            except Exception:
                _log.exception('showing %s', n)
Example #12
0
def main():
	_require('pyudev', 'python-pyudev')

	# handle ^C in console
	import signal
	signal.signal(signal.SIGINT, signal.SIG_DFL)

	args = _parse_arguments()
	if not args: return
	if args.action:
		# if any argument, run comandline and exit
		return _cli.run(args.action, args.hidraw_path)

	gi = _require('gi', 'python-gi')
	gi.require_version('Gtk', '3.0')
	_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')

	try:
		import solaar.ui as ui
		import solaar.listener as listener
		listener.setup_scanner(ui.status_changed, ui.error_dialog)

		import solaar.upower as _upower
		if args.restart_on_wake_up:
			_upower.watch(listener.start_all, listener.stop_all)
		else:
			_upower.watch(listener.ping_all)

		# main UI event loop
		ui.run_loop(listener.start_all, listener.stop_all)
	except Exception as e:
		import sys
		sys.exit('%s: error: %s' % (NAME.lower(), e))
Example #13
0
def _parse_arguments():
	import argparse
	arg_parser = argparse.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('-D', '--hidraw', action='store', dest='hidraw_path', metavar='PATH',
							help='unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2')
	arg_parser.add_argument('--restart-on-wake-up', action='store_true',
							help='restart Solaar on sleep wake-up (experimental)')
	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()

	if args.help_actions:
		_cli.print_help()
		return

	import logging
	if args.debug > 0:
		log_level = logging.WARNING - 10 * args.debug
		log_format='%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

	if not args.action:
		if logging.root.isEnabledFor(logging.INFO):
			logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)

	return args
Example #14
0
def main():
    _require('pyudev', 'python-pyudev')

    # handle ^C in console
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    args = _parse_arguments()
    if not args: return
    if args.action:
        # if any argument, run comandline and exit
        return _cli.run(args.action, args.hidraw_path)

    gi = _require('gi', 'python-gi')
    gi.require_version('Gtk', '3.0')
    _require('gi.repository.Gtk', 'gir1.2-gtk-3.0')

    try:
        import solaar.ui as ui
        import solaar.listener as listener
        listener.setup_scanner(ui.status_changed, ui.error_dialog)

        import solaar.upower as _upower
        if args.restart_on_wake_up:
            _upower.watch(listener.start_all, listener.stop_all)
        else:
            _upower.watch(listener.ping_all)

        # main UI event loop
        ui.run_loop(listener.start_all, listener.stop_all)
    except Exception as e:
        import sys
        sys.exit('%s: error: %s' % (NAME.lower(), e))
Example #15
0
def _parse_arguments():
    import argparse
    arg_parser = argparse.ArgumentParser(
        prog=NAME.lower(), epilog='For more information see https://pwr-solaar.github.io/Solaar'
    )
    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(
        '-D',
        '--hidraw',
        action='store',
        dest='hidraw_path',
        metavar='PATH',
        help='unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2'
    )
    arg_parser.add_argument('--restart-on-wake-up', action='store_true', help='restart Solaar on sleep wake-up (experimental)')
    arg_parser.add_argument(
        '-w', '--window', choices=('show', 'hide', 'only'), help='start with window showing / hidden / only (no tray icon)'
    )
    arg_parser.add_argument(
        '-b',
        '--battery-icons',
        choices=('regular', 'symbolic', 'solaar'),
        help='prefer regular battery / symbolic battery / solaar icons'
    )
    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()

    if args.help_actions:
        _cli.print_help()
        return

    if args.window is None:
        args.window = 'show'  # default behaviour is to show main window

    global battery_icons_style
    battery_icons_style = args.battery_icons if args.battery_icons is not None else 'regular'

    import logging
    if args.debug > 0:
        log_level = logging.WARNING - 10 * args.debug
        log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

    if not args.action:
        if logging.root.isEnabledFor(logging.INFO):
            logging.info('language %s (%s), translations path %s', _i18n.language, _i18n.encoding, _i18n.path)

    return args
Example #16
0
def main():
	_require('pyudev', 'python-pyudev')
	_require('gi.repository', 'python-gi')
	_require('gi.repository.Gtk', 'gir1.2-gtk-3.0')
	_parse_arguments()

	# handle ^C in console
	import signal
	signal.signal(signal.SIGINT, signal.SIG_DFL)

	try:
		import solaar.ui as ui
		ui.init()

		import solaar.listener as listener
		listener.setup_scanner(ui.status_changed, ui.error_dialog)
		listener.start_all()

		# main UI event loop
		ui.run_loop()

		listener.stop_all()
	except Exception as e:
		import sys
		sys.exit('%s: error: %s' % (NAME.lower(), e))
Example #17
0
def _parse_arguments():
    import argparse
    arg_parser = argparse.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(
        '-D',
        '--hidraw',
        action='store',
        dest='hidraw_path',
        metavar='PATH',
        help=
        'unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2'
    )
    arg_parser.add_argument(
        '--restart-on-wake-up',
        action='store_true',
        help='restart Solaar on sleep wake-up (experimental)')
    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()

    if args.help_actions:
        _cli.print_help()
        return

    import logging
    if args.debug > 0:
        log_level = logging.WARNING - 10 * args.debug
        log_format = '%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

    if not args.action:
        if logging.root.isEnabledFor(logging.INFO):
            logging.info("language %s (%s), translations path %s",
                         _i18n.language, _i18n.encoding, _i18n.path)

    return args
Example #18
0
def _create():
    about = Gtk.AboutDialog()

    about.set_program_name(NAME)
    about.set_version(__version__)
    about.set_comments(
        _("Shows status of devices connected\nthrough wireless Logitech receivers."
          ))

    about.set_logo_icon_name(NAME.lower())

    about.set_copyright('© 2012-2013 Daniel Pavel')
    about.set_license_type(Gtk.License.GPL_2_0)

    about.set_authors(('Daniel Pavel http://github.com/pwr', ))
    try:
        about.add_credit_section(_("GUI design"),
                                 ('Julien Gascard', 'Daniel Pavel'))
        about.add_credit_section(_("Testing"), (
            'Douglas Wagner',
            'Julien Gascard',
            'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html',
        ))
        about.add_credit_section(_("Logitech documentation"), (
            'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower',
            'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28',
        ))
    except TypeError:
        # gtk3 < ~3.6.4 has incorrect gi bindings
        import logging
        logging.exception("failed to fully create the about dialog")
    except:
        # the Gtk3 version may be too old, and the function does not exist
        import logging
        logging.exception("failed to fully create the about dialog")

    about.set_translator_credits('\n'.join((
        'gogo (croatian)',
        'Papoteur, David Geiger, Damien Lallement (français)',
        'Michele Olivo (italiano)',
        'Adrian Piotrowicz (polski)',
        'Drovetto, JrBenito (Portuguese-BR)',
        'Daniel Pavel (română)',
        'Daniel Zippert, Emelie Snecker (svensk)',
    )))

    about.set_website('http://pwr.github.io/Solaar/')
    about.set_website_label(NAME)

    about.connect('response', lambda x, y: x.hide())

    def _hide(dialog, event):
        dialog.hide()
        return True

    about.connect('delete-event', _hide)

    return about
Example #19
0
def _handlesigint(signal, stack):
    import signal
    import sys
    import faulthandler
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    if _log.isEnabledFor(_INFO):
        faulthandler.dump_traceback()

    sys.exit('%s: exit due to keyboard interrupt' % (NAME.lower()))
Example #20
0
def _create():
	about = Gtk.AboutDialog()

	about.set_program_name(NAME)
	about.set_version(__version__)
	about.set_comments(_("Shows status of devices connected\nthrough wireless Logitech receivers."))

	about.set_logo_icon_name(NAME.lower())

	about.set_copyright('© 2012-2013 Daniel Pavel')
	about.set_license_type(Gtk.License.GPL_2_0)

	about.set_authors(('Daniel Pavel http://github.com/pwr',))
	try:
		about.add_credit_section(_("GUI design"), ('Julien Gascard', 'Daniel Pavel'))
		about.add_credit_section(_("Testing"), (
						'Douglas Wagner',
						'Julien Gascard',
						'Peter Wu http://www.lekensteyn.nl/logitech-unifying.html',
						))
		about.add_credit_section(_("Logitech documentation"), (
						'Julien Danjou http://julien.danjou.info/blog/2012/logitech-unifying-upower',
						'Nestor Lopez Casado http://drive.google.com/folderview?id=0BxbRzx7vEV7eWmgwazJ3NUFfQ28',
						))
	except TypeError:
		# gtk3 < ~3.6.4 has incorrect gi bindings
		import logging
		logging.exception("failed to fully create the about dialog")
	except:
		# the Gtk3 version may be too old, and the function does not exist
		import logging
		logging.exception("failed to fully create the about dialog")

	about.set_translator_credits('\n'.join((
					'gogo (croatian)',
					'Papoteur, David Geiger, Damien Lallement (français)',
					'Michele Olivo (italiano)',
					'Adrian Piotrowicz (polski)',
					'Drovetto, JrBenito (Portuguese-BR)',
					'Daniel Pavel (română)',
					'Daniel Zippert, Emelie Snecker (svensk)',
					'Dimitriy Ryazantcev (Russian)',
					)))

	about.set_website('http://pwr.github.io/Solaar/')
	about.set_website_label(NAME)

	about.connect('response', lambda x, y: x.hide())

	def _hide(dialog, event):
		dialog.hide()
		return True
	about.connect('delete-event', _hide)

	return about
Example #21
0
    def alert(reason, icon=None):
        assert reason

        if available and Notify.is_initted():
            n = _notifications.get(NAME)
            if n is None:
                n = _notifications[NAME] = Notify.Notification()

            # we need to use the filename here because the notifications daemon
            # is an external application that does not know about our icon sets
            icon_file = _icons.icon_file(
                NAME.lower()) if icon is None else _icons.icon_file(icon)

            n.update(NAME, reason, icon_file)
            n.set_urgency(Notify.Urgency.NORMAL)
            n.set_hint('desktop-entry', GLib.Variant('s', NAME.lower()))

            try:
                # if _log.isEnabledFor(_DEBUG):
                #     _log.debug("showing %s", n)
                n.show()
            except Exception:
                _log.exception('showing %s', n)
Example #22
0
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.add_argument('--battery', action='store_true', default=False, help='show battery level only')
	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
Example #23
0
File: gtk.py Project: pwr/Solaar
def _parse_arguments():
    import argparse

    arg_parser = argparse.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(
        "-D",
        "--hidraw",
        action="store",
        dest="hidraw_path",
        metavar="PATH",
        help="unifying receiver to use; the first detected receiver if unspecified. Example: /dev/hidraw2",
    )
    arg_parser.add_argument(
        "--restart-on-wake-up", action="store_true", help="restart Solaar on sleep wake-up (experimental)"
    )
    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()

    if args.help_actions:
        _cli.print_help()
        return

    import logging

    if args.debug > 0:
        log_level = logging.WARNING - 10 * args.debug
        log_format = "%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

    if not args.action:
        if logging.root.isEnabledFor(logging.INFO):
            logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)

    return args
Example #24
0
def main():
    _require('pyudev', 'python3-pyudev')

    # handle ^C in console
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    signal.signal(signal.SIGINT, _handlesigint)

    args = _parse_arguments()
    if not args:
        return
    if args.action:
        # if any argument, run comandline and exit
        return _cli.run(args.action, args.hidraw_path)

    gi = _require('gi', 'python3-gi or python3-gobject')
    _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0')

    udev_file = '42-logitech-unify-permissions.rules'
    if not os.path.isfile('/etc/udev/rules.d/' +
                          udev_file) and not os.path.isfile(
                              '/lib/udev/rules.d/' + udev_file):
        print(_i18n._('ERROR: '), end='')
        print(_i18n._('Solaar depends on a udev file that is not present'),
              end='.\n')
        print(
            _i18n._(
                'For more information see the Solaar installation directions\n'
                'at https://pwr-solaar.github.io/Solaar/installation'))
    try:
        import solaar.ui as ui
        import solaar.listener as listener
        listener.setup_scanner(ui.status_changed, ui.error_dialog)

        import solaar.upower as _upower
        if args.restart_on_wake_up:
            _upower.watch(listener.start_all, listener.stop_all)
        else:
            _upower.watch(lambda: listener.ping_all(True))

        # main UI event loop
        ui.run_loop(listener.start_all, listener.stop_all,
                    args.window != 'only', args.window != 'hide')
    except Exception:
        import sys
        from traceback import format_exc
        sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
Example #25
0
def main():
    _require('pyudev', 'python3-pyudev')

    # handle ^C in console
    import signal
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    signal.signal(signal.SIGINT, _handlesigint)

    args = _parse_arguments()
    if not args:
        return
    if args.action:
        # if any argument, run comandline and exit
        return _cli.run(args.action, args.hidraw_path)

    gi = _require('gi',
                  'python3-gi (in Ubuntu) or python3-gobject (in Fedora)')
    _require('gi.repository.Gtk', 'gir1.2-gtk-3.0', gi, 'Gtk', '3.0')

    udev_file = '42-logitech-unify-permissions.rules'
    if _log.isEnabledFor(_WARNING) \
       and not os.path.isfile('/etc/udev/rules.d/' + udev_file) \
       and not os.path.isfile('/usr/lib/udev/rules.d/' + udev_file) \
       and not os.path.isfile('/usr/local/lib/udev/rules.d/' + udev_file):
        _log.warning('Solaar udev file not found in expected location')
        _log.warning(
            'See https://pwr-solaar.github.io/Solaar/installation for more information'
        )
    try:
        import solaar.ui as ui
        import solaar.listener as listener
        listener.setup_scanner(ui.status_changed, ui.error_dialog)

        import solaar.upower as _upower
        if args.restart_on_wake_up:
            _upower.watch(listener.start_all, listener.stop_all)
        else:
            _upower.watch(lambda: listener.ping_all(True))

        # main UI event loop
        ui.run_loop(listener.start_all, listener.stop_all,
                    args.window != 'only', args.window != 'hide')
    except Exception:
        import sys
        from traceback import format_exc
        sys.exit('%s: error: %s' % (NAME.lower(), format_exc()))
Example #26
0
def run(cli_args=None):
    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))
Example #27
0
def run(cli_args=None):
	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))
Example #28
0
def _parse_arguments():
	import argparse
	arg_parser = argparse.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__)
	args = arg_parser.parse_args()

	import logging
	if args.debug > 0:
		log_level = logging.WARNING - 10 * args.debug
		log_format='%(asctime)s,%(msecs)03d %(levelname)8s [%(threadName)s] %(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)

	if logging.root.isEnabledFor(logging.INFO):
		logging.info("language %s (%s), translations path %s", _i18n.language, _i18n.encoding, _i18n.path)

	return args
Example #29
0
	def alert(reason, icon=None):
		assert reason

		if available and Notify.is_initted():
			n = _notifications.get(NAME)
			if n is None:
				n = _notifications[NAME] = Notify.Notification()

			# we need to use the filename here because the notifications daemon
			# is an external application that does not know about our icon sets
			icon_file = _icons.icon_file(NAME.lower()) if icon is None \
						else _icons.icon_file(icon)

			n.update(NAME, reason, icon_file)
			n.set_urgency(Notify.Urgency.NORMAL)

			try:
				# if _log.isEnabledFor(_DEBUG):
				# 	_log.debug("showing %s", n)
				n.show()
			except Exception:
				_log.exception("showing %s", n)
Example #30
0
	from os.path import dirname as _dirname

	yield 'share/solaar/icons', _glob('share/solaar/icons/solaar*.svg')
	yield 'share/solaar/icons', _glob('share/solaar/icons/light_*.png')
	yield 'share/icons/hicolor/scalable/apps', ['share/solaar/icons/solaar.svg']

	for mo in _glob('share/locale/*/LC_MESSAGES/solaar.mo'):
		yield _dirname(mo), [mo]

	yield 'share/applications', ['share/applications/solaar.desktop']
	yield autostart_path, ['share/applications/solaar.desktop']

	del _dirname


setup(name=NAME.lower(),
		version=__version__,
		description='Linux devices manager for the Logitech Unifying Receiver.',
		long_description='''
Solaar is a Linux device manager for Logitech's Unifying Receiver peripherals.
It is able to pair/unpair devices to the receiver, and for some devices read
battery status.
'''.strip(),
		author='Daniel Pavel',
		author_email='*****@*****.**',
		license='GPLv2',
		url='http://pwr.github.io/Solaar/',
		classifiers=[
			'Development Status :: 4 - Beta',
			'Environment :: X11 Applications :: GTK',
			'Environment :: Console',
Example #31
0
File: i18n.py Project: saue0/Solaar
    del _sys

    from glob import glob as _glob

    for location in prefix_share, src_share:
        mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo'))
        if mo_files:
            return _path.join(location, 'locale')

    # del _path


locale.setlocale(locale.LC_ALL, '')
language, encoding = locale.getlocale()
del locale

_LOCALE_DOMAIN = _NAME.lower()
path = _find_locale_path(_LOCALE_DOMAIN)

_gettext.bindtextdomain(_LOCALE_DOMAIN, path)
_gettext.textdomain(_LOCALE_DOMAIN)
_gettext.install(_LOCALE_DOMAIN)

try:
    unicode  # noqa: F821
    _ = lambda x: _gettext.gettext(x).decode('UTF-8')
    ngettext = lambda *x: _gettext.ngettext(*x).decode('UTF-8')
except Exception:
    _ = _gettext.gettext
    ngettext = _gettext.ngettext
Example #32
0
File: i18n.py Project: 3v1n0/Solaar
	from glob import glob as _glob

	for location in prefix_share, src_share:
		mo_files = _glob(_path.join(location, 'locale', '*', 'LC_MESSAGES', lc_domain + '.mo'))
		if mo_files:
			return _path.join(location, 'locale')

	# del _path


import locale
locale.setlocale(locale.LC_ALL, '')
language, encoding = locale.getlocale()
del locale

_LOCALE_DOMAIN = _NAME.lower()
path = _find_locale_path(_LOCALE_DOMAIN)

import gettext as _gettext

_gettext.bindtextdomain(_LOCALE_DOMAIN, path)
_gettext.textdomain(_LOCALE_DOMAIN)
_gettext.install(_LOCALE_DOMAIN)

try:
	unicode
	_ = lambda x: _gettext.gettext(x).decode('UTF-8')
except:
	_ = _gettext.gettext
Example #33
0
    yield 'share/solaar/icons', _glob('share/solaar/icons/light_*.png')
    yield 'share/icons/hicolor/scalable/apps', [
        'share/solaar/icons/solaar.svg'
    ]

    for mo in _glob('share/locale/*/LC_MESSAGES/solaar.mo'):
        yield _dirname(mo), [mo]

    yield 'share/applications', ['share/applications/solaar.desktop']
    yield autostart_path, ['share/applications/solaar.desktop']

    del _dirname


setup(
    name=NAME.lower(),
    version=__version__,
    description='Linux devices manager for the Logitech Unifying Receiver.',
    long_description='''
Solaar is a Linux device manager for Logitech's Unifying Receiver peripherals.
It is able to pair/unpair devices to the receiver, and for some devices read
battery status.
'''.strip(),
    author='Daniel Pavel',
    author_email='*****@*****.**',
    license='GPLv2',
    url='http://pwr.github.io/Solaar/',
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: X11 Applications :: GTK',
        'Environment :: Console',
Example #34
0
						"because typed text can be sniffed inconspicuously by 3rd parties within range.")

_UNIFYING_RECEIVER_TEXT = (
		_("No device paired") + '.\n\n<small>' + _("Up to %d devices can be paired to this receiver") + '.</small>',
		'%d ' + _("paired devices") + '\n\n<small>' + _("Up to %d devices can be paired to this receiver") + '.</small>',
	)
_NANO_RECEIVER_TEXT = (
		_("No device paired") + '.\n\n<small> </small>',
		' \n\n<small>' + _("Only one device can be paired to this receiver") + '.</small>',
	)

#
# 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):
	if toggle:
		b = Gtk.ToggleButton()
	else:
		b = Gtk.Button(label) if label else Gtk.Button()

	if icon_name:
		image = Gtk.Image.new_from_icon_name(icon_name, icon_size)
		b.set_image(image)

	if tooltip:
		b.set_tooltip_text(tooltip)