root/trunk/libffado/support/mixer/mixer_motu.py

Revision 1003, 9.4 kB (checked in by jwoithe, 13 years ago)

MOTU updates:

  • cleanup of "define" namespace. All MOTU-related defines now start with "MOTU_" rather than a mix of this and "MOTUFW_".
  • Significant cleanup of motu mixer UI definition and python code. Far less glue code is now needed.
  • Use generic binary switch control in mixer dbus interface where possibe.
  • Implement proof-of-concept input level/boost switches.
  • Provide mechanism to feed some device status back to the mixer application. Currently this is done only at startup but in time we'll need a way to poll for some of it as the mixer runs.
  • When streaming is active, disable controls whose operation is incompatible with an active streaming system.
  • Adapt active channels in the mixer to the current device state. The handling of optical input mode is still to be done.
  • Minor updates to MOTU protocol documentation.
  • Whitespace cleanup in mixer_motu.py for consistency with the "tab is 4 spaces" rule used elsewhere in FFADO's source code.
Line 
1 #
2 # Copyright (C) 2005-2008 by Pieter Palmers
3 # Copyright (C) 2008 by Jonathan Woithe
4 #
5 # This file is part of FFADO
6 # FFADO = Free Firewire (pro-)audio drivers for linux
7 #
8 # FFADO is based upon FreeBoB.
9 #
10 # This program is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 2 of the License, or
13 # (at your option) version 3 of the License.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 #
23
24 from qt import *
25 from mixer_motuui import *
26
27 class MotuMixer(MotuMixerUI):
28     def __init__(self,parent = None,name = None,modal = 0,fl = 0):
29         MotuMixerUI.__init__(self,parent,name,modal,fl)
30
31     # public slot: channel/mix faders
32     def updateFader(self, a0):
33         sender = self.sender()
34         vol = 128-a0
35         print "setting %s channel/mix fader to %d" % (self.ChannelFaders[sender][0], vol)
36         self.hw.setDiscrete(self.ChannelFaders[sender][0], vol)
37
38     # public slot: channel pan
39     def updatePan(self, a0):
40         sender = self.sender()
41         pan = a0
42         print "setting %s channel pan to %d" % (self.ChannelPans[sender][0], pan)
43         self.hw.setDiscrete(self.ChannelPans[sender][0], pan)
44
45     # public slot: generic binary switch
46     def updateBinarySwitch(self, a0):
47         sender = self.sender()
48         val=a0
49         print "setting %s switch to %d" % (self.BinarySwitches[sender][0], val)
50         self.hw.setDiscrete(self.BinarySwitches[sender][0], val)
51
52     # public slot: mix destination control
53     def updateMixDest(self, a0):
54         sender = self.sender()
55         dest=a0
56         print "setting %s mix destination to %d" % (self.MixDests[sender][0], dest)
57         self.hw.setDiscrete(self.MixDests[sender][0], dest)
58
59     # public slots: mix output controls
60     def set_mix1_dest(self,a0):
61         self.setMixDest('mix1', a0)
62
63     def setSelector(self,a0,a1):
64         name=a0
65         state = a1
66         print "setting %s state to %d" % (name, state)
67         self.hw.setDiscrete(self.SelectorControls[name][0], state)
68
69     def init(self):
70         print "Init MOTU mixer window"
71
72         self.ChannelFaders={
73             self.mix1ana1_fader: ['/Mixer/Mix1/Ana1_fader'],
74             self.mix1ana2_fader: ['/Mixer/Mix1/Ana2_fader'],
75             self.mix1ana3_fader: ['/Mixer/Mix1/Ana3_fader'],
76             self.mix1ana4_fader: ['/Mixer/Mix1/Ana4_fader'],
77             self.mix1ana5_fader: ['/Mixer/Mix1/Ana5_fader'],
78             self.mix1ana6_fader: ['/Mixer/Mix1/Ana6_fader'],
79             self.mix1ana7_fader: ['/Mixer/Mix1/Ana7_fader'],
80             self.mix1ana8_fader: ['/Mixer/Mix1/Ana8_fader'],
81             self.mix1_fader: ['/Mixer/Mix1/Mix_fader'],
82             }
83
84         self.ChannelPans={
85             self.mix1ana1_pan:   ['/Mixer/Mix1/Ana1_pan'],
86             self.mix1ana2_pan:   ['/Mixer/Mix1/Ana2_pan'],
87             self.mix1ana3_pan:   ['/Mixer/Mix1/Ana3_pan'],
88             self.mix1ana4_pan:   ['/Mixer/Mix1/Ana4_pan'],
89             self.mix1ana5_pan:   ['/Mixer/Mix1/Ana5_pan'],
90             self.mix1ana6_pan:   ['/Mixer/Mix1/Ana6_pan'],
91             self.mix1ana7_pan:   ['/Mixer/Mix1/Ana7_pan'],
92             self.mix1ana8_pan:   ['/Mixer/Mix1/Ana8_pan'],
93         }
94
95         self.BinarySwitches={
96             self.mix1ana1_mute:  ['/Mixer/Mix1/Ana1_mute'],
97             self.mix1ana2_mute:  ['/Mixer/Mix1/Ana2_mute'],
98             self.mix1ana3_mute:  ['/Mixer/Mix1/Ana3_mute'],
99             self.mix1ana4_mute:  ['/Mixer/Mix1/Ana4_mute'],
100             self.mix1ana5_mute:  ['/Mixer/Mix1/Ana5_mute'],
101             self.mix1ana6_mute:  ['/Mixer/Mix1/Ana6_mute'],
102             self.mix1ana7_mute:  ['/Mixer/Mix1/Ana7_mute'],
103             self.mix1ana8_mute:  ['/Mixer/Mix1/Ana8_mute'],
104             self.mix1_mute:  ['/Mixer/Mix1/Mix_mute'],
105             self.mix1ana1_solo:  ['/Mixer/Mix1/Ana1_solo'],
106             self.mix1ana2_solo:  ['/Mixer/Mix1/Ana2_solo'],
107             self.mix1ana3_solo:  ['/Mixer/Mix1/Ana3_solo'],
108             self.mix1ana4_solo:  ['/Mixer/Mix1/Ana4_solo'],
109             self.mix1ana5_solo:  ['/Mixer/Mix1/Ana5_solo'],
110             self.mix1ana6_solo:  ['/Mixer/Mix1/Ana6_solo'],
111             self.mix1ana7_solo:  ['/Mixer/Mix1/Ana7_solo'],
112             self.mix1ana8_solo:  ['/Mixer/Mix1/Ana8_solo'],
113             self.ana5_level:     ['/Mixer/Control/Ana5_level'],
114             self.ana6_level:     ['/Mixer/Control/Ana6_level'],
115             self.ana7_level:     ['/Mixer/Control/Ana7_level'],
116             self.ana8_level:     ['/Mixer/Control/Ana8_level'],
117             self.ana5_boost:     ['/Mixer/Control/Ana5_boost'],
118             self.ana6_boost:     ['/Mixer/Control/Ana6_boost'],
119             self.ana7_boost:     ['/Mixer/Control/Ana7_boost'],
120             self.ana8_boost:     ['/Mixer/Control/Ana8_boost'],
121         }
122
123         self.MixDests={
124             self.mix1_dest:      ['/Mixer/Mix1/Mix_dest'],
125         }
126
127         self.SelectorControls={
128
129         }
130
131         # Other mixer variables
132         self.is_streaming = 0
133         self.sample_rate = 0
134
135     def initValues(self):
136         # Is the device streaming?
137         self.is_streaming = self.hw.getDiscrete('/Mixer/Info/IsStreaming')
138         print "device streaming flag: %d" % (self.is_streaming)
139
140         # Retrieve other device settings as needed
141         self.sample_rate = self.hw.getDiscrete('/Mixer/Info/SampleRate')
142         print "device sample rate: %d" % (self.sample_rate)
143         self.has_mic_inputs = self.hw.getDiscrete('/Mixer/Info/HasMicInputs')
144         print "device has mic inputs: %d" % (self.has_mic_inputs)
145         self.has_aesebu_inputs = self.hw.getDiscrete('/Mixer/Info/HasAESEBUInputs')
146         print "device has AES/EBU inputs: %d" % (self.has_aesebu_inputs)
147         self.has_spdif_inputs = self.hw.getDiscrete('/Mixer/Info/HasSPDIFInputs')
148         print "device has SPDIF inputs: %d" % (self.has_spdif_inputs)
149
150         # Customise the UI based on device options retrieved
151         if (self.has_mic_inputs):
152             # Mic input controls displace AES/EBU since no current device
153             # has both.
154             self.mix1_aes_group.setTitle("Mic inputs")
155             # FIXME: when implmented, will mic channels just reuse the AES/EBU
156             # dbus path?  If not we'll have to reset the respective values in
157             # the control arrays (self.ChannelFaders etc).
158         else:
159             if (not(self.has_aesebu_inputs)):
160                 self.mix1_aes_group.setEnabled(False)
161         if (not(self.has_spdif_inputs)):
162             self.mix1_spdif_group.setEnabled(False)
163
164         # Some controls must be disabled if the device is streaming
165         if (self.is_streaming):
166             print "Disabling controls which require inactive streaming"
167             self.optical_in_mode.setEnabled(False)
168             self.optical_out_mode.setEnabled(False)
169
170         # Some channels aren't available at higher sampling rates
171         if (self.sample_rate > 96000):
172             print "Disabling controls not present above 96 kHz"
173             self.mix1_adat_group.setEnabled(False)
174             self.mix1_aes_group.setEnabled(False)
175             self.mix1_spdif_group.setEnabled(False)
176         if (self.sample_rate > 48000):
177             print "Disabling controls not present above 48 kHz"
178             self.mix1_adat58_group.setEnabled(False)
179
180         # Now fetch the current values into the respective controls.  Don't
181         # bother fetching controls which are disabled.
182         for ctrl, info in self.ChannelFaders.iteritems():
183             if (not(ctrl.isEnabled())):
184                 continue
185             vol = 128-self.hw.getDiscrete(info[0])
186             print "%s channel fader is %d" % (info[0] , vol)
187             ctrl.setValue(vol)
188             QObject.connect(ctrl, SIGNAL('valueChanged(int)'), self.updateFader)
189
190         for ctrl, info in self.ChannelPans.iteritems():
191             if (not(ctrl.isEnabled())):
192                 continue
193             pan = self.hw.getDiscrete(info[0])
194             print "%s channel pan is %d" % (info[0] , pan)
195             ctrl.setValue(pan)
196             QObject.connect(ctrl, SIGNAL('valueChanged(int)'), self.updatePan)
197
198         for ctrl, info in self.BinarySwitches.iteritems():
199             if (not(ctrl.isEnabled())):
200                 continue
201             val = self.hw.getDiscrete(info[0])
202             print "%s switch is %d" % (info[0] , val)
203             ctrl.setChecked(val)
204             QObject.connect(ctrl, SIGNAL('toggled(bool)'), self.updateBinarySwitch)
205
206         for ctrl, info in self.MixDests.iteritems():
207             if (not(ctrl.isEnabled())):
208                 continue
209             dest = self.hw.getDiscrete(info[0])
210             print "%s mix destination is %d" % (info[0] , dest)
211             ctrl.setCurrentItem(dest)
212             QObject.connect(ctrl, SIGNAL('activated(int)'), self.updateMixDest)
213
214         for name, ctrl in self.SelectorControls.iteritems():
215             state = self.hw.getDiscrete(ctrl[0])
216             print "%s state is %d" % (name , state)
217             ctrl[1].setCurrentItem(state)   
218
219         # FIXME: If optical mode is not ADAT, disable ADAT controls here.
220         # It can't be done earlier because we need the current values of the
221         # ADAT channel controls in case the user goes ahead and enables the
222         # ADAT optical mode.
Note: See TracBrowser for help on using the browser.