--- /dev/null
+import Actions, OSC, Events, Views, curses
+import eci, time
+
+class Metronome(Views.View):
+
+ def __init__(self, context, label, x, y, dx, dy, dispatcher):
+ Views.View.__init__(self, context, label, x, y, dx, dy)
+ self._dispatcher = dispatcher
+ self._eci = eci.ECI(1)
+ self._eci('-G:jack,metronome,notransport')
+ self._eci('ai-add null')
+ self._eci('ao-add jack_auto,alsa_pcm')
+ self._eci('cop-add -pn:metronome,120')
+ self._eci('cop-add -ea:1')
+ self._eci('engine-launch')
+ self._bpm = 120
+ self._volume = 1
+ self._running = False
+ self._tap = None
+
+ def updateView(self, bindings):
+ pass
+
+ def init(self):
+ Views.View.init(self)
+ self._redraw(0)
+
+ def _redraw(self, refresh=1):
+ self.win().addstr(1,2,'%3d bpm' % self._bpm)
+ if self._running:
+ self.win().addstr(1,10,'Running',curses.A_BOLD)
+ else:
+ self.win().addstr(1,10,'Off ')
+ self.win().addstr(1,18,'%3.1f' % self._volume)
+ if refresh:
+ self.win().refresh()
+
+ def toggle(self):
+ self._running = not self._running
+ if self._running:
+ self._eci('start')
+ else:
+ self._eci('stop')
+ self._redraw()
+
+ def tap(self):
+ t = time.time()
+ if self._tap and self._tap < t and self._tap > t-2:
+ self.setBPM(60.0 / (t - self._tap))
+ self._tap = t
+
+ def setVolume(self, value):
+ self._volume = value
+ self._eci('cop-select 2')
+ self._eci('copp-select 1')
+ self._eci('copp-set', self._volume)
+ self._redraw()
+
+ def setBPM(self, value):
+ self._bpm = int(value)
+ self._eci('cop-select 1')
+ self._eci('copp-select 1')
+ self._eci('copp-set', self._bpm)
+ self._redraw()
+
+ def stepBPM(self, dir, min=30, max=360):
+ step = abs(dir)
+ bpm = self._bpm/step * step
+ if self._bpm == bpm:
+ bpm += dir
+ elif dir>0:
+ bpm += 5
+ if bpm<min : bpm = min
+ if bpm>max : bpm = max
+ self.setBPM(bpm)
+
+ class VolumeSetter(object):
+
+ def __init__(self, metronome):
+ self._metronome = metronome
+
+ def __call__(self, value):
+ self._metronome.setVolume(value)
+
+ class VolumeGetter(object):
+
+ def __init__(self, metronome):
+ self._metronome = metronome
+
+ def __call__(self):
+ return self._metronome._volume
+
+ def assignVolumeController(self, controller, title, min, max, steps=[]):
+ controller.assign(title,
+ self.VolumeSetter(self),
+ self.VolumeGetter(self),
+ None,
+ min, max, steps)
+
+ class BPMSetter(object):
+
+ def __init__(self, metronome):
+ self._metronome = metronome
+
+ def __call__(self, value):
+ self._metronome.setBPM(value)
+
+ class BPMGetter(object):
+
+ def __init__(self, metronome):
+ self._metronome = metronome
+
+ def __call__(self):
+ return self._metronome._bpm
+
+ def assignBPMController(self, controller, title, min, max, steps=[]):
+ controller.assign(title,
+ self.BPMSetter(self),
+ self.BPMGetter(self),
+ None,
+ min, max, steps)
+
+
+class Toggle(Actions.Action):
+
+ def __init__(self, name, m):
+ Actions.Action.__init__(self, name)
+ self._m = m
+
+ def __call__(self, binding):
+ self._m.toggle()
+
+class Tap(Actions.Action):
+
+ def __init__(self, name, m):
+ Actions.Action.__init__(self, name)
+ self._m = m
+
+ def __call__(self, binding):
+ self._m.tap()
+
+class AssignVolumeController(Actions.Action):
+
+ def __init__(self, name, metronome, controller, title, min, max, steps=[]):
+ Actions.Action.__init__(self, name)
+ self._metronome = metronome
+ self._controller = controller
+ self._title = title
+ self._min = min
+ self._max = max
+ self._steps = steps
+
+ def __call__(self, binding):
+ self._metronome.assignVolumeController(self._controller,
+ self._title,
+ self._min,
+ self._max,
+ self._steps)
+
+class AssignBPMController(Actions.Action):
+
+ def __init__(self, name, metronome, controller, title, min, max, steps=[]):
+ Actions.Action.__init__(self, name)
+ self._metronome = metronome
+ self._controller = controller
+ self._title = title
+ self._min = min
+ self._max = max
+ self._steps = steps
+
+ def __call__(self, binding):
+ self._metronome.assignBPMController(self._controller,
+ self._title,
+ self._min,
+ self._max,
+ self._steps)
+
+class StepBPM(Actions.Action):
+
+ def __init__(self, name, m, dir):
+ Actions.Action.__init__(self, name)
+ self._m = m
+ self._dir = dir
+
+ def __call__(self, binding):
+ self._m.stepBPM(self._dir)
+
+def register( viewmanager,
+ dispatcher,
+ context,
+ label,
+ x, y, dx, dy ):
+ metronome = Metronome(context, label, x, y, dx, dy, dispatcher)
+ viewmanager.registerView( metronome )
+ return metronome