Add new project 'AudioControl'
[audiocontrol.git] / Joyboard.py
1 import Views, Events, Logger
2 from Views import EventWidget
3 import time, os, struct
4
5 class View(Views.WidgetView):
6
7     def __init__(self, context, label, numeric_switches, alpha_switches, x, y, size=11):
8         size += 1
9         Views.WidgetView.__init__(self, context, label, x, y,size*numeric_switches+3,7)
10
11         split = numeric_switches // 2
12         for i in range(split):
13             self.add( EventWidget(i,str(i),size*i+1,4,size) )
14         for i in range(split,numeric_switches):
15             self.add( EventWidget(i,str(i),size*i+3,4,size) )
16         split = max(0,alpha_switches-(numeric_switches-split))
17         offset = size//2+(numeric_switches-alpha_switches-1)*size
18         for i in range(split):
19             self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+1+offset,1,size) )
20         for i in range(split, alpha_switches):
21             self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+3+offset,1,size) )
22
23
24 class JSEvent:
25
26     STRUCT = "IhBB"
27     STRUCT_len = struct.calcsize(STRUCT)
28
29     TYPE_BUTTON = 0x01
30     TYPE_AXIS = 0x02
31     TYPE_INIT = 0x80
32     
33     def __init__(self, data):
34         self.time, self.value, self.type, self.number = struct.unpack(self.STRUCT,data)
35
36     def __str__(self):
37         return "%s(time=%d, value=%d,type=%d (%s)), number=%d)" % (
38             str(self.__class__),self.time, self.value, self.type, self.decode_type(), self.number)
39
40     def decode_type(self):
41         return ('','INIT|')[(self.type & self.TYPE_INIT) and 1 or 0] \
42                + ('','BUTTON','AXIS')[self.type & ~self.TYPE_INIT]
43
44     def readFrom(klass,f):
45         return klass(os.read(f.fileno(),klass.STRUCT_len))
46     readFrom=classmethod(readFrom)
47
48     def readMultipleFrom(klass,f,maxevents=256):
49         data = os.read(f.fileno(),maxevents*klass.STRUCT_len)
50         rv = []
51         while data:
52             rv.append(klass(data[:klass.STRUCT_len]))
53             data = data[klass.STRUCT_len:]
54         return rv
55     readMultipleFrom=classmethod(readMultipleFrom)
56
57 class Source(Events.EventSource):
58
59     def __init__(self, joydev, context, bits=None, mindelay=100):
60         Events.EventSource.__init__(self, file(joydev), context)
61         self._bits = bits
62         self._lastevent = 0
63         self._mindelay = mindelay
64
65     def readEvents(self):
66         n = 0
67         lev = self._lastevent
68         if self._bits:
69             time.sleep(0.0005)
70             jsevents = JSEvent.readMultipleFrom(self.fd())
71             for event in jsevents:
72                 if event.type == JSEvent.TYPE_BUTTON and event.value == 1:
73                     self._lastevent = event.time
74                     if event.time - lev < self._mindelay : return []
75                     n = n | self._bits[event.number]
76             if n == 0 : return []
77             n -= 1
78         else:
79             event = JSEvent.readFrom(self.fd())
80             if event.type == JSEvent.TYPE_BUTTON and event.value == 1:
81                 self._lastevent = event.time
82                 if event.time - lev < self._mindelay : return []
83                 n = event.number
84             else:
85                 return []
86         return [Events.Event(self.context(), n)]
87     
88 def register( viewmanager,
89               dispatcher,
90               context,
91               label,
92               numeric_switches,
93               alpha_switches,
94               x,
95               y,
96               size,
97               device,
98               bits = None ):
99     viewmanager.registerView( View(context, label, numeric_switches, alpha_switches, x, y, size) )
100     dispatcher.registerSource( Source(device, context, bits) )