Skip to content

Instantly share code, notes, and snippets.

@SergKolo
Last active August 8, 2016 19:57
Show Gist options
  • Save SergKolo/6b2b2cccb1653d316ac831bec26ba975 to your computer and use it in GitHub Desktop.
Save SergKolo/6b2b2cccb1653d316ac831bec26ba975 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Author: Sergiy Kolodyazhnyy
Date: August 2nd, 2016
Written for: http://askubuntu.com/q/806212/295286
Tested on Ubuntu 16.04 LTS
usage: xinput_monitor.py [-h] [-q] -d DEVICE
Script that waits for presence of user device
and sets preferences as defined
in ~/.xinputmonrc file
optional arguments:
-h, --help show this help message and exit
-q, --quiet Blocks on-screen notifications
-d DEVICE, --device DEVICE
device name
"""
from __future__ import print_function
import gi
gi.require_version('Notify', '0.7')
from gi.repository import Notify
import subprocess
import argparse
import time
import json
import os
def send_notif(n,title, text):
try:
if Notify.init(__file__):
# n = Notify.Notification.new("Notify")
n.update(title, text)
n.set_urgency(2)
if not n.show():
raise SyntaxError("sending notification failed!")
else:
raise SyntaxError("can't initialize notification!")
except SyntaxError as error:
print(error)
if error == "sending notification failed!":
Notify.uninit()
else:
Notify.uninit()
def run_cmd(cmdlist):
""" Reusable function for running shell commands"""
try:
stdout = subprocess.check_output(cmdlist)
except subprocess.CalledProcessError as pserror:
return pserror.output.decode().strip()
#sys.exit(1)
else:
if stdout:
return stdout.decode().strip()
def list_ids(mouse_name):
""" Returns list of ids for the same device"""
#while True:
mouse_ids = []
for dev_id in run_cmd(['xinput','list','--id-only']).split('\n'):
if mouse_name in run_cmd(['xinput','list','--name-only',dev_id]):
mouse_ids.append(dev_id)
return mouse_ids
def read_config_file(notif):
""" reads ~/.xinputmonrc file """
rcfile = os.path.join( os.path.expanduser('~'),'.xinputmonrc')
try:
with open(rcfile) as config_file:
config_data = json.load(config_file)
except IOError as error:
send_notif(notif, __file__ , error.__repr__() )
else:
if config_data:
return config_data
def set_props(notif,device):
"""Sets properties per each device is
given by list_ids() function"""
props = read_config_file(notif)
# Thiscan also be set manually as in
# commented-out example below
#props = { 'Device Accel Profile':'-1',
# 'Device Accel Constant Deceleration':'3.5',
# 'Device Accel Velocity Scaling':'1.0' }
if not props:
send_notif(notif,'Reading ~/.xinputmonrc failed',
'Please write proper rc file.')
return None
""" set all property-value pair per each device id
Uncomment the print function if you wish to know
which ids have been altered for double-checking
with xinput list-props"""
for dev_id in list_ids(device):
# print(dev_id)
for prop,value in props.items():
if type(value) is not list:
value = [value]
run_cmd(['xinput','set-prop',dev_id,prop] +
[str(item) for item in value ])
def parse_args():
""" Parse command line arguments"""
arg_parser = argparse.ArgumentParser(
description="""Script that waits for """ +
"""presence of user device """+
"""and sets preferences as """ +
"""defined in ~/.xinputmonrc file""")
arg_parser.add_argument(
'-q','--quiet', action='store_true',
help='Blocks on-screen notifications',
required=False)
arg_parser.add_argument(
'-d','--device',
help='device name',
type=str,
required=True)
return arg_parser.parse_args()
def main():
notif = Notify.Notification.new("Notify")
args = parse_args()
while True:
if not args.quiet:
send_notif(notif, __file__ ,
'Wating for ' + args.device )
while args.device not in run_cmd(['xinput','list','--name-only']):
time.sleep(0.25)
pass
time.sleep(0.25) # let xinput catch up
if not args.quiet:
send_notif(notif, __file__,
args.device + ' connected. Setting values')
# set props here
set_props(notif,args.device)
while args.device in run_cmd(['xinput','list','--name-only']):
time.sleep(0.25)
pass
if not args.quiet:
send_notif( notif , __file__ , args.device +
' disconnected. Resuming monitoring' )
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment