-import Views, Events, Logger
+import Views, Events, Logger, Bindings, Actions
from Views import EventWidget
-import time, os, struct
+import time, os, struct, curses
class View(Views.WidgetView):
- def __init__(self, context, label, numeric_switches, alpha_switches, x, y, size=11):
+ def __init__(self, context, label, numeric_switches, alpha_switches, x, y, dx=0, size=11):
size += 1
- Views.WidgetView.__init__(self, context, label, x, y,size*numeric_switches+3,7)
+ dx = max(dx,size*numeric_switches+3)
+ delta = dx - size*numeric_switches - 3
+ shift = delta / 2
+ delta = dx - size*numeric_switches - 2*shift
+ Views.WidgetView.__init__(self, context, label, x, y, dx, 7)
split = numeric_switches // 2
for i in range(split):
- self.add( EventWidget(i,str(i),size*i+1,4,size) )
+ self.add( EventWidget(i,str(i+1)[-1:],size*i+1+shift,4,size) )
for i in range(split,numeric_switches):
- self.add( EventWidget(i,str(i),size*i+3,4,size) )
+ self.add( EventWidget(i,str(i+1)[-1:],size*i+shift+delta,4,size) )
split = max(0,alpha_switches-(numeric_switches-split))
offset = size//2+(numeric_switches-alpha_switches-1)*size
for i in range(split):
- self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+1+offset,1,size) )
+ self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+1+offset+shift,1,size) )
for i in range(split, alpha_switches):
- self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+3+offset,1,size) )
+ self.add( EventWidget(i+numeric_switches, chr(ord('A')+i), size*i+delta+offset+shift,1,size) )
class JSEvent:
return rv
readMultipleFrom=classmethod(readMultipleFrom)
+
class Source(Events.EventSource):
def __init__(self, joydev, context, bits=None, mindelay=100):
self._bits = bits
self._lastevent = 0
self._mindelay = mindelay
+ self._controllers = {}
def readEvents(self):
n = 0
time.sleep(0.0005)
jsevents = JSEvent.readMultipleFrom(self.fd())
for event in jsevents:
+ if event.type == JSEvent.TYPE_AXIS:
+ return self._controller(event.number, event.value)
if event.type == JSEvent.TYPE_BUTTON and event.value == 1:
self._lastevent = event.time
if event.time - lev < self._mindelay : return []
n -= 1
else:
event = JSEvent.readFrom(self.fd())
+ if event.type == JSEvent.TYPE_AXIS:
+ return self._controller(event.number, event.value)
if event.type == JSEvent.TYPE_BUTTON and event.value == 1:
self._lastevent = event.time
if event.time - lev < self._mindelay : return []
else:
return []
return [Events.Event(self.context(), n)]
+
+ def registerController(self, controller, low, high):
+ self._controllers[controller] = { 'low': low, 'high': high }
+
+ def _controller(self, number, value):
+ controller = self._controllers.get(number)
+ if controller:
+ value = (value - controller['low']) * 1000 / (controller['high']-controller['low'])
+ value = max(min(value,1000),0)
+ return [Events.ControlEvent(self.context(), 'p%d' % number, value)]
+ return []
+
+
+class Controller(Views.View):
+
+ def __init__(self, context, name, x, y, dx, dy, keylist, dispatcher,
+ controller, source, low, high):
+ Views.View.__init__(self, context, name, x, y, dx, dy)
+ self._valueEvent = None
+ self._setCommand = None
+ self._valueCommand = None
+ self._parameter = None
+ self._keylist = keylist
+ self._keymap = Bindings.KeyMap()
+ self._keymap.add( Bindings.Binding(Events.Event(source.context(), 'p%d' % controller), '',
+ Actions.Command('controllerChanged',
+ self._controllerChanged)) )
+ self._keylist.prepend(self._keymap)
+ source.registerController(controller, low, high)
+ self._dispatcher = dispatcher
+ self._min = None
+ self._max = None
+ self._stops = None
+ self._value = None
+ self._controlValue = None
+
+ def updateView(self, bindings):
+ pass
+
+ def init(self):
+ Views.View.init(self)
+ self._redraw()
+
+ def assign(self, parameter, setCommand, valueCommand, valueEvent, min, max, stops=[]):
+ self._keylist.removeMap(self._keymap)
+ if self._valueEvent is not None:
+ self._keymap.unbind(self._valueEvent)
+ self._parameter = parameter
+ self._valueEvent = valueEvent
+ self._setCommand = setCommand
+ self._valueCommand = valueCommand
+ self._min = min
+ self._max = max
+ self._stops = stops
+ self._keymap.add( Bindings.Binding( self._valueEvent, '',
+ Actions.Command('updateValue',
+ self._updateValue)) )
+ self._keylist.prepend(self._keymap)
+ self._value = None
+ self._valueCommand()
+ self._redraw()
+
+ def _updateValue(self, binding):
+ event = self._dispatcher.currentEvent()
+ self._value = event.value
+ self._redrawValue()
+
+ def _controllerChanged(self, binding):
+ event = self._dispatcher.currentEvent()
+ Logger.log('ctl',"value = %d" % event.value)
+ self._controlValue = event.value
+ if self._controlValue >= 999 or self._controlValue <= 1:
+ self._dispatcher.setIdleCallback(self._changeValue,50)
+ else:
+ self._dispatcher.unsetIdleCallback()
+ self._redrawController()
+
+ def _changeValue(self):
+ if self._value is None: return
+ if self._controlValue >= 999:
+ self.stepValue(+1)
+ elif self._controlValue <= 1:
+ self.stepValue(-1)
+
+ def stepValue(self, direction):
+ if direction > 0:
+ newValue = self._value + (self._max - self._min) / (3000/50)
+ crossed = [ x for x in self._stops if x > self._value*1.0001 and x <= newValue ]
+ elif direction < 0:
+ newValue = self._value - (self._max - self._min) / (3000/50)
+ crossed = [ x for x in self._stops if x < self._value/1.0001 and x >= newValue ]
+ if newValue >= self._max:
+ crossed = [ self._max ]
+ elif newValue <= self._min:
+ crossed = [ self._min ]
+ if crossed:
+ newValue = crossed[0]
+ self._dispatcher.unsetIdleCallback()
+ self._setCommand(newValue)
+ # Hmm ... why does value_command not work sometimes ??
+ self._value = newValue
+ self._redrawValue()
+ else:
+ self._setCommand(newValue)
+ self._valueCommand()
+
+ def _redraw(self):
+ height, width = self.win().getmaxyx()
+ if self._parameter is not None:
+ self.win().addstr(1,2,self._parameter[:width-4].ljust(width-4), curses.A_BOLD)
+ self._redrawValue(False)
+ self._redrawController()
+
+ def _flt(self, value, width):
+ return ('%.3f' % value)[:width].ljust(width)
+
+ def _redrawValue(self, refresh=True):
+ height, width = self.win().getmaxyx()
+ pos = None
+ if self._value is not None:
+ pos = height - 3 - int( (self._value - self._min) * (height-6)
+ / (self._max - self._min) + .5 )
+ if self._max is not None:
+ self.win().addstr(2,2, self._flt(self._max,width-7))
+ if pos is not None and pos == 3:
+ self.win().addstr(pos, 5, self._flt(self._value,width-7), curses.A_BOLD)
+ else:
+ self.win().addstr(3, 5, "".ljust(width-7))
+ for row in range(4,height-3):
+ if pos is not None and row == pos:
+ self.win().addch(pos,3,curses.ACS_PLUS)
+ self.win().addstr(pos, 5, self._flt(self._value,width-7), curses.A_BOLD)
+ else:
+ self.win().addch(row,3,curses.ACS_VLINE)
+ self.win().addstr(row, 5, "".ljust(width-7))
+ if pos is not None and pos == height-3:
+ self.win().addstr(pos, 5, self._flt(self._value,width-7), curses.A_BOLD)
+ else:
+ self.win().addstr(height-3, 5, "".ljust(width-7))
+ if self._min is not None:
+ self.win().addstr(height-2,2,self._flt(self._min,width-7))
+
+ if refresh:
+ self.win().refresh()
+
+ def _redrawController(self, refresh=True):
+ height, width = self.win().getmaxyx()
+ if self._controlValue is not None and self._controlValue >= 999:
+ self.win().addch(3,3,curses.ACS_UARROW)
+ else:
+ self.win().addch(3,3,curses.ACS_TTEE)
+ if self._controlValue is not None and self._controlValue <= 1:
+ self.win().addch(height-3,3,curses.ACS_DARROW)
+ else:
+ self.win().addch(height-3,3,curses.ACS_BTEE)
+
+ if refresh:
+ self.win().refresh()
+
+class StepController(Actions.Action):
+
+ def __init__(self, name, controller, direction):
+ Actions.Action.__init__(self, name)
+ self._controller = controller
+ self._direction = direction
+
+ def __call__(self, binding):
+ self._controller.stepValue(self._direction)
+
+
def register( viewmanager,
dispatcher,
context,
alpha_switches,
x,
y,
+ dx,
size,
device,
- bits = None ):
- viewmanager.registerView( View(context, label, numeric_switches, alpha_switches, x, y, size) )
- dispatcher.registerSource( Source(device, context, bits) )
+ bits = None,
+ controllers = []):
+ viewmanager.registerView( View(context, label, numeric_switches, alpha_switches, x, y, dx, size) )
+ source = Source(device, context, bits)
+ dispatcher.registerSource( source )
+ return source
+
+def registerController( viewmanager, dispatcher, keylist, source, context, name, x, y, dx, dy,
+ controller, low, high ):
+ controller = Controller(context, name, x, y, dx, dy, keylist, dispatcher,
+ controller, source, low, high)
+ viewmanager.registerView( controller )
+ return controller