Audio/AudioControl: Commit loads of long uncommited changes
[audiocontrol.git] / Mixer.py
diff --git a/Mixer.py b/Mixer.py
new file mode 100644 (file)
index 0000000..264184d
--- /dev/null
+++ b/Mixer.py
@@ -0,0 +1,221 @@
+import Actions, OSC, Events, Views, curses
+
+class Mixer(Views.View):
+
+    def __init__(self, context, label, x, y, dx, dy, channels, oscserver, remote):
+        Views.View.__init__(self, context, label, x, y, dx, dy)
+        self._context = context
+        self._server = oscserver
+        self._remote = remote
+        self._server.registerHandler(self._remote, self._oscEvent)
+        self._server.command(self._remote,'/mixer/get_channel_count')
+        self._channelNames = channels
+        self._channels = None
+        self._volume = None
+        self._muteState = None
+
+    def updateView(self, bindings):
+        pass
+
+    def init(self):
+        Views.View.init(self)
+
+    def _redraw(self):
+        if not self._channels : return
+        for i in range(self._channels):
+            self.win().addstr(i+1,2,self._channelNames[i][:8])
+            self._redrawValue(i+1)
+        self.win().refresh()
+
+    def _redrawValue(self, channel):
+        if self._muteState[channel-1] == self.MUTED:
+            self.win().addstr(channel,11,'Muted',curses.A_BOLD)
+        elif self._volume[channel-1] is not None:
+            self.win().addstr(channel,11, '%5.1f dB' % self._volume[channel-1])
+        self.win().refresh()
+
+    ACTIVE = 0
+    PENDING = 1
+    MUTED = 2
+
+    def _oscEvent(self, path, data):
+        if path == '/mixer/channel/gain':
+            # channel, gain
+            if self._muteState[data[0]-1] != self.MUTED:
+                self._volume[data[0]-1] = data[1]
+            if self._muteState[data[0]-1] == self.PENDING:
+                self._muteState[data[0]-1] = self.MUTED
+                self._set(data[0],-90.0)
+            self._redrawValue(data[0])
+            return [ Events.ControlEvent(self._context, data[0], data[1]) ]
+        elif path == '/mixer/channel_count':
+            # channel_count
+            self._channels = int(data[0])
+            self._volume = [ None ] * self._channels
+            self._muteState = [ self.ACTIVE ] * self._channels
+            while  len(self._channelNames) < self._channels:
+                self._channelNames.append("Channel %d" % (len(self._channelNames)+1))
+            self._redraw()
+            for i in range(self._channels):
+                self._get(i+1)
+                
+        return []
+
+    def mute(self, channel):
+        if self._muteState[channel-1] == self.ACTIVE:
+            self._muteState[channel-1] = self.PENDING
+            self._get(channel)
+
+    def unmute(self, channel):
+        if self._muteState[channel-1] != self.ACTIVE:
+            if self._muteState[channel-1] == self.MUTED:
+                self._set(channel, self._volume[channel-1])
+            self._muteState[channel-1] = self.ACTIVE
+
+    def muteToggle(self, channel):
+        if self._muteState[channel-1] == self.ACTIVE:
+            self.mute(channel)
+        else:
+            self.unmute(channel)
+
+    def muteToggleAll(self):
+        if [ x for x in self._muteState if x is not self.MUTED ]:
+            for i in range(self._channels):
+                self.mute(i+1)
+        else:
+            for i in range(self._channels):
+                self.unmute(i+1)
+
+    def get(self, channel):
+        if self._muteState is None or self._muteState[channel-1] == self.ACTIVE:
+            self._get(channel)
+
+    def _get(self, channel):
+        self._server.command(self._remote,'/mixer/channel/get_gain', channel)
+
+    def set(self, channel, value):
+        if self._muteState is None or self._muteState[channel-1] == self.ACTIVE:
+            self._set(channel, value)
+
+    def _set(self, channel, value):
+        self._server.command(self._remote,'/mixer/channel/set_gain', channel, value)
+
+    def cycleVolume(self, channel, volumes):
+        if self._muteState is None or self._muteState[channel-1] != self.ACTIVE:
+            return
+        elif self._volume[channel-1] is not None:
+            for i in range(len(volumes)):
+                if not volumes[i]-0.01 < self._volume[channel-1]:
+                    self._set(channel,volumes[i])
+                    return
+            self._set(channel, volumes[0])
+
+    class ParamGetter(object):
+
+        def __init__(self, mixer, channel):
+            self._mixer = mixer
+            self._channel = channel
+
+        def __call__(self):
+            self._mixer.get(self._channel)
+
+    class ParamSetter(object):
+
+        def __init__(self, mixer, channel):
+            self._mixer = mixer
+            self._channel = channel
+
+        def __call__(self, value):
+            self._mixer.set(self._channel, value)
+
+    def assignController(self, controller, title, channel, min=-12.0, max=6.0):
+        controller.assign(title,
+                          self.ParamSetter(self, channel),
+                          self.ParamGetter(self, channel),
+                          Events.Event(self._context, channel),
+                          min, max, [ 0.0 ])
+
+
+
+class AssignController(Actions.Action):
+
+    def __init__(self, name, mixer, controller, title, channel, min=-12.0, max=6.0):
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+        self._controller = controller
+        self._title = title
+        self._channel = channel
+        self._min = min
+        self._max = max
+
+    def __call__(self, binding):
+        self._mixer.assignController(self._controller,
+                                     self._title,
+                                     self._channel,
+                                     self._min,
+                                     self._max)
+
+
+class MuteChannel(Actions.Action):
+
+    def __init__(self, name, mixer, channel):
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+        self._channel = channel
+
+    def __call__(self, binding):
+        self._mixer.mute(self._channel)
+
+
+class UnmuteChannel(Actions.Action):
+
+    def __init__(self, name, mixer, channel):
+        Actions.Action.__init__(self, name, mixer, channel)
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+        self._channel = channel
+        
+    def __call__(self, binding):
+        self._mixer.unmute(self._channel)
+        
+
+class ToggleMuteChannel(Actions.Action):
+
+    def __init__(self, name, mixer, channel):
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+        self._channel = channel
+
+    def __call__(self, binding):
+        self._mixer.muteToggle(self._channel)
+
+class ToggleMuteAll(Actions.Action):
+
+    def __init__(self, name, mixer):
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+
+    def __call__(self, binding):
+        self._mixer.muteToggleAll()
+
+class CycleVolume(Actions.Action):
+
+    def __init__(self, name, mixer, channel, volumes):
+        Actions.Action.__init__(self, name)
+        self._mixer = mixer
+        self._channel = channel
+        self._volumes = volumes
+
+    def __call__(self, binding):
+        self._mixer.cycleVolume(self._channel, self._volumes)
+
+def register( viewmanager,
+              oscserver,
+              context,
+              label,
+              x, y, dx, dy,
+              channels, 
+              remote ):
+    mixer = Mixer(context, label, x, y, dx, dy, channels, oscserver, remote)
+    viewmanager.registerView( mixer )
+    return mixer