| #!/usr/bin/env python |
| # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| # Description: |
| # |
| # Class for injecting input events to linux 'evdev' input devices. |
| # |
| # Provides evemu-play-like functionality if run from the command line: |
| # $ input_event_player.py -d /dev/input/event6 |
| |
| """ Playback input events on a linux input device. """ |
| |
| import glob |
| import os.path |
| import re |
| import time |
| |
| from input_device import InputDevice, InputEvent |
| from optparse import OptionParser |
| |
| |
| class InputEventPlayer: |
| """ Linux evdev input event player. |
| |
| An "evdev" input event player injects a stream of "input events" to kernel |
| evdev driver. With this player, we could easily playback an input event file |
| which was recorded with the tool evemu-record previously. |
| |
| """ |
| |
| def __init__(self): |
| self.tv_sec = None |
| self.tv_usec = None |
| |
| def playback(self, device, gesture_file): |
| """ Play the events in gesture_file on device. |
| |
| Keyword arguments: |
| device -- the InputDevice device object |
| gesture_file -- the name of the event file recorded previously |
| """ |
| if not device: |
| raise |
| event_str = 'E: (\d+)\.(\d+) ([0-9a-f]{4}) ([0-9a-f]{4}) ([-]?\d+)' |
| event_pattern = re.compile(event_str) |
| for line in open(gesture_file, 'rt'): |
| m = event_pattern.match(line) |
| if not m: |
| raise |
| event = InputEvent(int(m.group(1)), |
| int(m.group(2)), |
| int(m.group(3), 16), |
| int(m.group(4), 16), |
| int(m.group(5))) |
| if not self.tv_sec: |
| self.tv_sec = event.tv_sec |
| self.tv_usec = event.tv_usec |
| delta = event.tv_sec - self.tv_sec |
| delta += ((event.tv_usec - self.tv_usec) / 1000000.0) |
| # Sleep only if the event is 0.05 ms later than the previous one |
| if delta > 0.0000500: |
| time.sleep(delta) |
| self.tv_sec = event.tv_sec |
| self.tv_usec = event.tv_usec |
| event.write(device.f) |
| |
| |
| if __name__ == '__main__': |
| parser = OptionParser() |
| |
| parser.add_option('-d', '--devpath', dest='devpath', default='', |
| help='device path (/dev/input/event0)') |
| parser.add_option('-t', '--touchpad', action='store_true', dest='touchpad', |
| default=False, help='Find and use first touchpad device') |
| parser.add_option('-f', '--file', action='store', dest='gesture_file', |
| help='Event file to playback') |
| (options, args) = parser.parse_args() |
| |
| if options.touchpad: |
| for evdev in glob.glob('/dev/input/event*'): |
| device = InputDevice(evdev) |
| if device.is_touchpad(): |
| break |
| else: |
| print 'Can not find a touchpad device' |
| exit() |
| elif not os.path.exists(options.devpath): |
| print 'Can not find the input device "%s".' % options.devpath |
| exit() |
| else: |
| device = InputDevice(options.devpath) |
| if not options.gesture_file: |
| print 'Gesture file is not specified.' |
| exit() |
| if not os.path.exists(options.gesture_file): |
| print 'Can not find the gesture file %s.' % options.gesture_file |
| exit() |
| |
| InputEventPlayer().playback(device, options.gesture_file) |
| print 'Gesture file %s has been played.' % options.gesture_file |