1#!/usr/bin/env python 2# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6# Description: 7# 8# Class for injecting input events to linux 'evdev' input devices. 9# 10# Provides evemu-play-like functionality if run from the command line: 11# $ input_event_player.py -d /dev/input/event6 12 13""" Playback input events on a linux input device. """ 14 15import glob 16import os.path 17import re 18import time 19 20from input_device import InputDevice, InputEvent 21from optparse import OptionParser 22 23 24class InputEventPlayer: 25 """ Linux evdev input event player. 26 27 An "evdev" input event player injects a stream of "input events" to kernel 28 evdev driver. With this player, we could easily playback an input event file 29 which was recorded with the tool evemu-record previously. 30 31 """ 32 33 def __init__(self): 34 self.tv_sec = None 35 self.tv_usec = None 36 37 def playback(self, device, gesture_file): 38 """ Play the events in gesture_file on device. 39 40 Keyword arguments: 41 device -- the InputDevice device object 42 gesture_file -- the name of the event file recorded previously 43 """ 44 if not device: 45 raise 46 event_str = 'E: (\d+)\.(\d+) ([0-9a-f]{4}) ([0-9a-f]{4}) ([-]?\d+)' 47 event_pattern = re.compile(event_str) 48 for line in open(gesture_file, 'rt'): 49 m = event_pattern.match(line) 50 if not m: 51 raise 52 event = InputEvent(int(m.group(1)), 53 int(m.group(2)), 54 int(m.group(3), 16), 55 int(m.group(4), 16), 56 int(m.group(5))) 57 if not self.tv_sec: 58 self.tv_sec = event.tv_sec 59 self.tv_usec = event.tv_usec 60 delta = event.tv_sec - self.tv_sec 61 delta += ((event.tv_usec - self.tv_usec) / 1000000.0) 62 # Sleep only if the event is 0.05 ms later than the previous one 63 if delta > 0.0000500: 64 time.sleep(delta) 65 self.tv_sec = event.tv_sec 66 self.tv_usec = event.tv_usec 67 event.write(device.f) 68 69 70if __name__ == '__main__': 71 parser = OptionParser() 72 73 parser.add_option('-d', '--devpath', dest='devpath', default='', 74 help='device path (/dev/input/event0)') 75 parser.add_option('-t', '--touchpad', action='store_true', dest='touchpad', 76 default=False, help='Find and use first touchpad device') 77 parser.add_option('-f', '--file', action='store', dest='gesture_file', 78 help='Event file to playback') 79 (options, args) = parser.parse_args() 80 81 if options.touchpad: 82 for evdev in glob.glob('/dev/input/event*'): 83 device = InputDevice(evdev) 84 if device.is_touchpad(): 85 break 86 else: 87 print 'Can not find a touchpad device' 88 exit() 89 elif not os.path.exists(options.devpath): 90 print 'Can not find the input device "%s".' % options.devpath 91 exit() 92 else: 93 device = InputDevice(options.devpath) 94 if not options.gesture_file: 95 print 'Gesture file is not specified.' 96 exit() 97 if not os.path.exists(options.gesture_file): 98 print 'Can not find the gesture file %s.' % options.gesture_file 99 exit() 100 101 InputEventPlayer().playback(device, options.gesture_file) 102 print 'Gesture file %s has been played.' % options.gesture_file 103