input-remapper/bin/key-mapper-control
2021-02-07 15:00:36 +01:00

180 lines
5.3 KiB
Python
Executable File

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# key-mapper - GUI for device specific keyboard mappings
# Copyright (C) 2020 sezanzeb <proxima@hip70890b.de>
#
# This file is part of key-mapper.
#
# key-mapper 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 3 of the License, or
# (at your option) any later version.
#
# key-mapper 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 key-mapper. If not, see <https://www.gnu.org/licenses/>.
"""Control the dbus service from the command line."""
import os
import grp
import sys
from argparse import ArgumentParser
from keymapper.logger import logger
from keymapper.config import config
from keymapper.daemon import get_dbus_interface
from keymapper.state import system_mapping
from keymapper.getdevices import get_devices
from keymapper.paths import USER
AUTOLOAD = 'autoload'
START = 'start'
STOP = 'stop'
STOP_ALL = 'stop-all'
HELLO = 'hello'
def run(cmd):
"""Run and log a command."""
logger.info('Running `%s`...', cmd)
code = os.system(cmd)
if code != 0:
logger.error('Failed. exit code %d', code)
def group_exists(name):
"""Check if a group with that name exists."""
try:
grp.getgrnam(name)
return True
except KeyError:
return False
def main(options, daemon):
"""Do the stuff that the executable is supposed to do."""
# `main` is a function so that I can import it and test it
if options.config_dir is not None:
path = os.path.abspath(os.path.expanduser(os.path.join(
options.config_dir,
'config.json'
)))
if not os.path.exists(path):
logger.error('"%s" does not exist', path)
sys.exit(1)
logger.info('Using config from "%s" instead', path)
config.load_config(path)
# this is either the user-provided path or the default path in home
config_dir = os.path.dirname(config.path)
if options.list_devices:
get_devices()
sys.exit(0)
if options.key_names:
print('\n'.join(system_mapping.list_names()))
sys.exit(0)
if options.command not in [AUTOLOAD, START, STOP, HELLO, STOP_ALL]:
logger.error('Unknown command "%s"', options.command)
if daemon is None:
sys.exit(0)
if USER != 'root':
# might be triggered by udev, so skip the root user.
# this will also refresh the config of the daemon if the user changed
# it in the meantime.
daemon.set_config_dir(config_dir)
if options.command == AUTOLOAD:
# if device was specified, autoload for that one. if None autoload
# for all devices.
if options.device is None:
daemon.autoload()
else:
daemon.autoload_single(options.device)
if options.command == START:
if options.device is None:
logger.error('--device missing')
sys.exit(1)
if options.preset is None:
logger.error('--preset missing')
sys.exit(1)
logger.info('Starting injection: "%s", "%s"', options.device, options.preset)
daemon.start_injecting(options.device, options.preset)
if options.command == STOP:
if options.device is None:
logger.error('--device missing')
sys.exit(1)
daemon.stop_injecting(options.device)
if options.command == STOP_ALL:
daemon.stop_all()
if options.command == HELLO:
response = daemon.hello('hello')
logger.info('Daemon answered with "%s"', response)
if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument(
'--command', action='store', dest='command',
help='start, stop, autoload, hello or stop-all',
default=None, metavar='NAME'
)
parser.add_argument(
'--config-dir', action='store', dest='config_dir',
help=(
'path to the config directory containing config.json, '
'xmodmap.json and the presets folder. '
'defaults to ~/.config/key-mapper/'
),
default=None, metavar='PATH',
)
parser.add_argument(
'--preset', action='store', dest='preset',
help='The filename of the preset without the .json extension.',
default=None, metavar='NAME',
)
parser.add_argument(
'--device', action='store', dest='device',
help=(
'The device name which is used for subfolders in the '
'presets directory'
),
default=None, metavar='NAME'
)
parser.add_argument(
'--list-devices', action='store_true', dest='list_devices',
help='List available device names and exit',
default=False
)
parser.add_argument(
'-n', '--key-names', action='store_true', dest='key_names',
help='Print all available names for the mapping',
default=False
)
options = parser.parse_args(sys.argv[1:])
daemon = get_dbus_interface(fallback=False)
main(options, daemon)