• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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