source: rgbkbd/trunk/rgbkbd_controller.py @ 72

Revision 71, 4.4 KB checked in by retracile, 6 years ago (diff)

Initial import of source code

  • Property svn:executable set to *
Line 
1#!/usr/bin/python
2# expects ckb-daemon to be running, but the ckb user interface (including the
3# icon in the tray) to not be running.
4
5import sys
6import optparse
7import select
8import re
9
10from rgbkbd.manager import KeyboardManager
11
12
13class Controller(object):
14    def __init__(self, keyboard=None):
15        self.keyboards = {}
16
17    def open_keyboard(self, device):
18        self.keyboards[device] = KeyboardManager(device)
19
20    def run(self):
21        """Primary event loop"""
22        try:
23            main_notifier = open('/dev/input/ckb0/notify0', 'r')
24        except IOError, error:
25            sys.stderr.write("The ckb-daemon must be running before starting "
26                "this application.\n")
27            sys.stderr.flush()
28            return
29
30        key_event_re = re.compile('key (?P<state>[-+])(?P<key>.*)', re.M)
31
32        for n in range(1,10):
33            try:
34                self.open_keyboard(device='/dev/input/ckb%s' % n)
35                #sys.stderr.write("Keyboard %s found\n" % n) # DEBUG
36            except Exception, error:
37                pass
38                #sys.stderr.write("Keyboard %s not found (%s)\n" % (n, error)) # DEBUG
39            #sys.stderr.flush() # DEBUG
40
41        notifiers = [main_notifier]
42        notifiers.extend(x.notifier for x in self.keyboards.values())
43
44        try:
45            while True:
46                read_events, write_events, err_events = \
47                    select.select(notifiers, [], notifiers, self.tick_rate())
48                if err_events:
49                    print "Error events %s" % err_events
50                for read_event in read_events:
51                    if read_event == main_notifier:
52                        event = main_notifier.readline()
53                        # print "Event on ckb0/notify0: %s" % event # DEBUG
54                        words = event.split()
55                        if words[0] == 'device' and words[2] == 'added':
56                            # print "connecting new keyboard" # DEBUG
57                            new_kbd = words[-1]
58                            self.open_keyboard(new_kbd)
59                            notifiers.append(self.keyboards[new_kbd].notifier)
60                        elif words[0] == 'device' and words[2] == 'removed':
61                            kbd = words[-1]
62                            old_keyboard_manager = self.keyboards[kbd]
63                            del self.keyboards[kbd]
64                            notifiers.remove(old_keyboard_manager.notifier)
65                    else:
66                        keyboard_manager_matched = [x for x in self.keyboards.values()
67                            if x.notifier == read_event]
68                        if keyboard_manager_matched:
69                            # We could get an event on a keyboard at the same
70                            # time we get a notification of its removal.
71                            keyboard_manager = keyboard_manager_matched[0]
72
73                            line = read_event.readline()
74                            key_match = key_event_re.match(line)
75                            if key_match:
76                                keyboard_manager.key_event(**key_match.groupdict())
77                        else:
78                            print "Read event on %r does not match a keyboard" % read_event
79
80                # Send tick events to all keyboard managers
81                for keyboard_manager in self.keyboards.values():
82                    keyboard_manager.current_mode().tick()
83        except KeyboardInterrupt:
84            # Exit cleanly on ^C
85            pass
86        finally:
87            self.shutdown()
88        return
89
90    def tick_rate(self):
91        """Calculate a tick rate to use to meet the requirements across all
92        attached keyboards.
93        """
94        tick_rates = [km.current_mode().tick_rate for km in self.keyboards.values()]
95        tick_rates = [x for x in tick_rates if x]
96        if tick_rates:
97            return min(tick_rates)
98        return None
99
100    def shutdown(self):
101        for keyboard_manager in self.keyboards.values():
102            keyboard_manager.shutdown()
103
104
105def main(argv):
106    """Run the keyboard manager"""
107    parser = optparse.OptionParser("Usage: %s [options]" % argv[0])
108    parser.add_option('-k', '--keyboard', type="int", default=1,
109        help="Keyboard number to manipulate")
110
111    (options, args) = parser.parse_args(argv[1:])
112
113    manager = Controller()
114    manager.run()
115    return 0
116
117
118if __name__ == '__main__':
119    sys.exit(main(sys.argv))
Note: See TracBrowser for help on using the repository browser.