Audio/AudioControl: Lots of fixes
[audiocontrol.git] / Metronome.py
1 import Actions, OSC, Events, Views, curses
2 import eci, time
3
4 class Metronome(Views.View):
5
6     def __init__(self, context, label, x, y, dx, dy, dispatcher):
7         Views.View.__init__(self, context, label, x, y, dx, dy)
8         self._dispatcher = dispatcher
9         self._eci = eci.ECI(1)
10         self._eci('-G:jack,metronome,notransport')
11         self._eci('ai-add null')
12         self._eci('ao-add jack_auto,system')
13         self._eci('cop-add -pn:metronome,120')
14         self._eci('cop-add -ea:1')
15         self._eci('engine-launch')
16         self._bpm = 120
17         self._volume = 1
18         self._running = False
19         self._tap = None
20
21     def updateView(self, bindings):
22         pass
23
24     def init(self):
25         Views.View.init(self)
26         self._redraw(0)
27
28     def _redraw(self, refresh=1):
29         self.win().addstr(1,2,'%3d bpm' % self._bpm)
30         if self._running:
31             self.win().addstr(1,10,'Running',curses.A_BOLD)
32         else:
33             self.win().addstr(1,10,'Off    ')
34         self.win().addstr(1,18,'%3.1f' % self._volume)
35         if refresh:
36             self.win().refresh()
37         
38     def toggle(self):
39         self._running = not self._running
40         if self._running:
41             self._eci('start')
42         else:
43             self._eci('stop')
44         self._redraw()
45
46     def tap(self):
47         t = time.time()
48         if self._tap and self._tap < t and self._tap > t-2:
49             self.setBPM(60.0 / (t - self._tap))
50         self._tap = t
51
52     def setVolume(self, value):
53         self._volume = value
54         self._eci('cop-select 2')
55         self._eci('copp-select 1')
56         self._eci('copp-set', self._volume)
57         self._redraw()
58
59     def setBPM(self, value):
60         self._bpm = int(value)
61         self._eci('cop-select 1')
62         self._eci('copp-select 1')
63         self._eci('copp-set', self._bpm)
64         self._redraw()
65
66     def stepBPM(self, dir, min=30, max=360):
67         step = abs(dir)
68         bpm = self._bpm/step * step
69         if self._bpm == bpm:
70             bpm += dir
71         elif dir>0:
72             bpm += 5
73         if bpm<min : bpm = min
74         if bpm>max : bpm = max
75         self.setBPM(bpm)
76
77     class VolumeSetter(object):
78
79         def __init__(self, metronome):
80             self._metronome = metronome
81
82         def __call__(self, value):
83             self._metronome.setVolume(value)
84
85     class VolumeGetter(object):
86
87         def __init__(self, metronome):
88             self._metronome = metronome
89
90         def __call__(self):
91             return self._metronome._volume
92             
93     def assignVolumeController(self, controller, title, min, max, steps=[]):
94         controller.assign(title,
95                           self.VolumeSetter(self),
96                           self.VolumeGetter(self),
97                           None,
98                           min, max, steps)
99
100     class BPMSetter(object):
101
102         def __init__(self, metronome):
103             self._metronome = metronome
104
105         def __call__(self, value):
106             self._metronome.setBPM(value)
107
108     class BPMGetter(object):
109
110         def __init__(self, metronome):
111             self._metronome = metronome
112
113         def __call__(self):
114             return self._metronome._bpm
115
116     def assignBPMController(self, controller, title, min, max, steps=[]):
117         controller.assign(title,
118                           self.BPMSetter(self),
119                           self.BPMGetter(self),
120                           None,
121                           min, max, steps)
122
123
124 class Toggle(Actions.Action):
125
126     def __init__(self, name, m):
127         Actions.Action.__init__(self, name)
128         self._m = m
129
130     def __call__(self, binding):
131         self._m.toggle()
132
133 class Tap(Actions.Action):
134
135     def __init__(self, name, m):
136         Actions.Action.__init__(self, name)
137         self._m = m
138
139     def __call__(self, binding):
140         self._m.tap()
141
142 class AssignVolumeController(Actions.Action):
143
144     def __init__(self, name, metronome, controller, title, min, max, steps=[]):
145         Actions.Action.__init__(self, name)
146         self._metronome = metronome
147         self._controller = controller
148         self._title = title
149         self._min = min
150         self._max = max
151         self._steps = steps
152
153     def __call__(self, binding):
154         self._metronome.assignVolumeController(self._controller,
155                                                self._title,
156                                                self._min,
157                                                self._max,
158                                                self._steps)
159
160 class AssignBPMController(Actions.Action):
161
162     def __init__(self, name, metronome, controller, title, min, max, steps=[]):
163         Actions.Action.__init__(self, name)
164         self._metronome = metronome
165         self._controller = controller
166         self._title = title
167         self._min = min
168         self._max = max
169         self._steps = steps
170
171     def __call__(self, binding):
172         self._metronome.assignBPMController(self._controller,
173                                             self._title,
174                                             self._min,
175                                             self._max,
176                                             self._steps)
177
178 class StepBPM(Actions.Action):
179
180     def __init__(self, name, m, dir):
181         Actions.Action.__init__(self, name)
182         self._m = m
183         self._dir = dir
184
185     def __call__(self, binding):
186         self._m.stepBPM(self._dir)
187
188 def register( viewmanager,
189               dispatcher,
190               context,
191               label,
192               x, y, dx, dy ):
193     metronome = Metronome(context, label, x, y, dx, dy, dispatcher)
194     viewmanager.registerView( metronome )
195     return metronome