root/trunk/libffado/src/motu/motu_controls.cpp

Revision 1003, 11.6 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
25 // This also includes motu_controls.h
26 #include "motu_avdevice.h"
27
28 namespace Motu {
29
30 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg)
31 : Control::Discrete()
32 , m_parent(parent)
33 , m_register(dev_reg)
34 {
35 }
36
37 MotuDiscreteCtrl::MotuDiscreteCtrl(MotuDevice &parent, unsigned int dev_reg,
38              std::string name, std::string label, std::string descr)
39 : Control::Discrete()
40 , m_parent(parent)
41 , m_register(dev_reg)
42 {
43     setName(name);
44     setLabel(label);
45     setDescription(descr);
46 }
47
48 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
49   unsigned int val_mask, unsigned int setenable_mask)
50 : MotuDiscreteCtrl(parent, dev_reg)
51 {
52     m_value_mask = val_mask;
53     /* If no "write enable" is implemented for a given switch it's safe to
54      * pass zero in to setenable_mask.
55      */
56     m_setenable_mask = setenable_mask;
57 }
58
59 MotuBinarySwitch::MotuBinarySwitch(MotuDevice &parent, unsigned int dev_reg,
60     unsigned int val_mask, unsigned int setenable_mask,
61     std::string name, std::string label, std::string descr)
62 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
63 {
64     m_value_mask = val_mask;
65     /* If no "write enable" is implemented for a given switch it's safe to
66      * pass zero in to setenable_mask.
67      */
68     m_setenable_mask = setenable_mask;
69 }
70              
71 bool
72 MotuBinarySwitch::setValue(int v)
73 {
74     unsigned int val;
75     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for switch %s (0x%04x) to %d\n",
76       getName().c_str(), m_register, v);
77
78     // Set the value
79     if (m_setenable_mask) {
80       val = (v==0)?0:m_value_mask;
81       // Set the "write enable" bit for the value being set
82       val |= m_setenable_mask;
83     } else {
84       // It would be good to utilise the cached value from the receive
85       // processor (if running) later on.  For now we'll just fetch the
86       // current register value directly when needed.
87       val = m_parent.ReadRegister(m_register);
88       if (v==0)
89         val &= ~m_value_mask;
90       else
91         val |= m_value_mask;
92     }
93     m_parent.WriteRegister(m_register, val);
94
95     return true;
96 }
97
98 int
99 MotuBinarySwitch::getValue()
100 {
101     unsigned int val;
102     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for switch %s (0x%04x)\n",
103       getName().c_str(), m_register);
104
105     // FIXME: we could just read the appropriate mixer status field from the
106     // receive stream processor once we work out an efficient way to do this.
107     val = m_parent.ReadRegister(m_register);
108     return (val & m_value_mask) != 0;
109 }
110
111 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg)
112 : MotuDiscreteCtrl(parent, dev_reg)
113 {
114 }
115
116 ChannelFader::ChannelFader(MotuDevice &parent, unsigned int dev_reg,
117              std::string name, std::string label, std::string descr)
118 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
119 {
120 }
121              
122 bool
123 ChannelFader::setValue(int v)
124 {
125     unsigned int val;
126     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel fader 0x%04x to %d\n", m_register, v);
127
128     val = v<0?0:v;
129     if (val > 0x80)
130       val = 0x80;
131     // Bit 30 indicates that the channel fader is being set
132     val |= 0x40000000;
133     m_parent.WriteRegister(m_register, val);
134
135     return true;
136 }
137
138 int
139 ChannelFader::getValue()
140 {
141     unsigned int val;
142     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel fader 0x%04x\n", m_register);
143
144     // FIXME: we could just read the appropriate mixer status field from the
145     // receive stream processor once we work out an efficient way to do this.
146     val = m_parent.ReadRegister(m_register);
147     return val & 0xff;
148 }
149
150 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg)
151 : MotuDiscreteCtrl(parent, dev_reg)
152 {
153 }
154
155 ChannelPan::ChannelPan(MotuDevice &parent, unsigned int dev_reg,
156              std::string name, std::string label, std::string descr)
157 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
158 {
159 }
160              
161 bool
162 ChannelPan::setValue(int v)
163 {
164     unsigned int val;
165     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for channel pan 0x%04x to %d\n", m_register, v);
166
167     val = ((v<-64?-64:v)+64) & 0xff;
168     if (val > 0x80)
169       val = 0x80;
170     // Bit 31 indicates that pan is being set
171     val = (val << 8) | 0x80000000;
172     m_parent.WriteRegister(m_register, val);
173
174     return true;
175 }
176
177 int
178 ChannelPan::getValue()
179 {
180     unsigned int val;
181     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for channel pan 0x%04x\n", m_register);
182
183     // FIXME: we could just read the appropriate mixer status field from the
184     // receive stream processor once we work out an efficient way to do this.
185     val = m_parent.ReadRegister(m_register);
186     return ((val >> 8) & 0xff) - 0x40;
187 }
188
189 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg)
190 : MotuDiscreteCtrl(parent, dev_reg)
191 {
192 }
193
194 MixFader::MixFader(MotuDevice &parent, unsigned int dev_reg,
195              std::string name, std::string label, std::string descr)
196 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
197 {
198 }
199              
200 bool
201 MixFader::setValue(int v)
202 {
203     unsigned int val;
204     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix fader 0x%04x to %d\n", m_register, v);
205
206     val = v<0?0:v;
207     if (val > 0x80)
208       val = 0x80;
209     // Bit 24 indicates that the mix fader is being set
210     val |= 0x01000000;
211     m_parent.WriteRegister(m_register, val);
212
213     return true;
214 }
215
216 int
217 MixFader::getValue()
218 {
219     unsigned int val;
220     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix fader 0x%04x\n", m_register);
221
222     // FIXME: we could just read the appropriate mixer status field from the
223     // receive stream processor once we work out an efficient way to do this.
224     val = m_parent.ReadRegister(m_register);
225     return val & 0xff;
226 }
227
228 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg)
229 : MotuDiscreteCtrl(parent, dev_reg)
230 {
231 }
232
233 MixMute::MixMute(MotuDevice &parent, unsigned int dev_reg,
234              std::string name, std::string label, std::string descr)
235 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
236 {
237 }
238              
239 bool
240 MixMute::setValue(int v)
241 {
242     unsigned int val, dest;
243     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix mute 0x%04x to %d\n", m_register, v);
244
245     // Need to read current destination so we can preserve that when setting
246     // mute status (mute and destination are always set together).
247     dest = m_parent.ReadRegister(m_register) & 0x00000f00;
248     // Mute status is bit 12
249     val = (v==0)?0:0x00001000;
250     // Bit 25 indicates that mute and destination are being set.  Also
251     // preserve the current destination.
252     val |= 0x02000000 | dest;
253     m_parent.WriteRegister(m_register, val);
254
255     return true;
256 }
257
258 int
259 MixMute::getValue()
260 {
261     unsigned int val;
262     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix mute 0x%04x\n", m_register);
263
264     // FIXME: we could just read the appropriate mixer status field from the
265     // receive stream processor once we work out an efficient way to do this.
266     val = m_parent.ReadRegister(m_register);
267     return (val & 0x00001000) != 0;
268 }
269
270 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg)
271 : MotuDiscreteCtrl(parent, dev_reg)
272 {
273 }
274
275 MixDest::MixDest(MotuDevice &parent, unsigned int dev_reg,
276              std::string name, std::string label, std::string descr)
277 : MotuDiscreteCtrl(parent, dev_reg, name, label, descr)
278 {
279 }
280              
281 bool
282 MixDest::setValue(int v)
283 {
284     unsigned int val, mute;
285     debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for mix destination 0x%04x to %d\n", m_register, v);
286
287     // Need to get current mute status so we can preserve it
288     mute = m_parent.ReadRegister(m_register) & 0x00001000;
289     val = v;
290     /* Currently destination values between 0 and 0x0b are accepted.
291      * Ultimately this will be device (and device configuration) dependent.
292      */
293     if (val<0 || val>0x0b)
294       val = 0;
295     /* Destination is given by bits 11-8.  Add in the current mute status so
296      * it can be preserved (it's set concurrently with the destination).
297      */
298     val = (val << 8) | mute;
299     // Bit 25 indicates that mute and destination are being set
300     val |= 0x02000000;
301     m_parent.WriteRegister(m_register, val);
302
303     return true;
304 }
305
306 int
307 MixDest::getValue()
308 {
309     unsigned int val;
310     debugOutput(DEBUG_LEVEL_VERBOSE, "getValue for mix destination 0x%04x\n", m_register);
311
312     // FIXME: we could just read the appropriate mixer status field from the
313     // receive stream processor once we work out an efficient way to do this.
314     val = m_parent.ReadRegister(m_register);
315     return (val >> 8) & 0x0f;
316 }
317
318 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype)
319 : MotuDiscreteCtrl(parent, infotype)
320 {
321 }
322
323 InfoElement::InfoElement(MotuDevice &parent, unsigned infotype,
324              std::string name, std::string label, std::string descr)
325 : MotuDiscreteCtrl(parent, infotype, name, label, descr)
326 {
327 }
328              
329 bool
330 InfoElement::setValue(int v)
331 {
332     /* This is a read-only field, so any call to setValue() is technically
333      * an error.
334      */
335     debugOutput(DEBUG_LEVEL_VERBOSE, "InfoElement (%d) is read-only\n", m_register);
336     return false;
337 }
338
339 int
340 InfoElement::getValue()
341 {
342     unsigned int val;
343     signed int res = 0;
344
345     switch (m_register) {
346         case MOTU_INFO_IS_STREAMING:
347             val = m_parent.ReadRegister(MOTU_REG_ISOCTRL);
348             /* Streaming is active if either bit 22 (Motu->PC streaming
349              * enable) or bit 30 (PC->Motu streaming enable) is set.
350              */
351             res = (val & 0x40400000) != 0;
352             debugOutput(DEBUG_LEVEL_VERBOSE, "IsStreaming: %d (reg=%08x)\n", res, val);
353             break;
354         case MOTU_INFO_SAMPLE_RATE:
355             res = m_parent.getSamplingFrequency();
356             debugOutput(DEBUG_LEVEL_VERBOSE, "SampleRate: %d\n", res);
357             break;
358         case MOTU_INFO_HAS_MIC_INPUTS:
359             /* Only the 828Mk2 has separate mic inputs.  In time this may be
360              * deduced by walking the port info array within the parent.
361              */
362             res = m_parent.m_motu_model == MOTU_MODEL_828mkII ? 1:0;
363             debugOutput(DEBUG_LEVEL_VERBOSE, "Has mic inputs: %d\n", res);
364             break;
365         case MOTU_INFO_HAS_AESEBU_INPUTS:
366             /* AES/EBU inputs are currently present on the Traveler and
367              * 896HD.  In time this may be deduced by walking the port info
368              * array within the parent.
369              */
370             val = m_parent.m_motu_model;
371             res = (val==MOTU_MODEL_TRAVELER || val==MOTU_MODEL_896HD);
372             debugOutput(DEBUG_LEVEL_VERBOSE, "HasAESEBUInputs: %d\n", res);
373             break;
374         case MOTU_INFO_HAS_SPDIF_INPUTS:
375             /* SPDIF inputs are present on all supported models except the
376              * 896HD and the 8pre.  In time this may be deduced by walking
377              * the port info array within the parent.
378              */
379             val = m_parent.m_motu_model;
380             res = (val!=MOTU_MODEL_8PRE && val!=MOTU_MODEL_896HD);
381             debugOutput(DEBUG_LEVEL_VERBOSE, "HasSPDIFInputs: %d\n", res);
382             break;
383     }
384     return res;
385 }
386
387 }
Note: See TracBrowser for help on using the browser.