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

Revision 1763, 15.8 kB (checked in by ppalmers, 13 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  * Copyright (C) 2005-2009 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 file collects together everything associated with the management
26  * of mixer controls in the MOTU device object.
27  */
28
29 #include "motu/motu_avdevice.h"
30 #include "motu/motu_mixerdefs.h"
31 #include "motu/motu_mark3_mixerdefs.h"
32
33 namespace Motu {
34
35 bool
36 MotuDevice::buildMixerAudioControls(void) {
37
38     bool result = true;
39     MotuMatrixMixer *fader_mmixer = NULL;
40     MotuMatrixMixer *pan_mmixer = NULL;
41     MotuMatrixMixer *solo_mmixer = NULL;
42     MotuMatrixMixer *mute_mmixer = NULL;
43     const struct MatrixMixBus *buses = NULL;
44     const struct MatrixMixChannel *channels = NULL;
45     unsigned int bus, ch, i;
46
47     if (DevicesProperty[m_motu_model-1].mixer == NULL) {
48         debugOutput(DEBUG_LEVEL_INFO, "No pre-Mark3 mixer controls defined for model %d\n", m_motu_model);
49         result = false;
50     } else {
51         buses = DevicesProperty[m_motu_model-1].mixer->mixer_buses;
52         if (buses == NULL) {
53             debugOutput(DEBUG_LEVEL_WARNING, "No buses defined for model %d\n", m_motu_model);
54             result = false;
55         }
56         channels = DevicesProperty[m_motu_model-1].mixer->mixer_channels;
57         if (channels == NULL) {
58             debugOutput(DEBUG_LEVEL_WARNING, "No channels defined for model %d\n", m_motu_model);
59             result = false;
60         }
61     }
62     if (result == false) {
63         return true;
64     }
65
66     /* Create the top-level matrix mixers */
67     fader_mmixer = new ChannelFaderMatrixMixer(*this, "fader");
68     result &= m_MixerContainer->addElement(fader_mmixer);
69     pan_mmixer = new ChannelPanMatrixMixer(*this, "pan");
70     result &= m_MixerContainer->addElement(pan_mmixer);
71     solo_mmixer = new ChannelBinSwMatrixMixer(*this, "solo",
72         MOTU_CTRL_MASK_SOLO_VALUE, MOTU_CTRL_MASK_SOLO_SETENABLE);
73     result &= m_MixerContainer->addElement(solo_mmixer);
74     mute_mmixer = new ChannelBinSwMatrixMixer(*this, "mute",
75         MOTU_CTRL_MASK_MUTE_VALUE, MOTU_CTRL_MASK_MUTE_SETENABLE);
76     result &= m_MixerContainer->addElement(mute_mmixer);
77
78     for (bus=0; bus<DevicesProperty[m_motu_model-1].mixer->n_mixer_buses; bus++) {
79         fader_mmixer->addRowInfo(buses[bus].name, 0, buses[bus].address);
80         pan_mmixer->addRowInfo(buses[bus].name, 0, buses[bus].address);
81         solo_mmixer->addRowInfo(buses[bus].name, 0, buses[bus].address);
82         mute_mmixer->addRowInfo(buses[bus].name, 0, buses[bus].address);
83     }
84
85     for (ch=0; ch<DevicesProperty[m_motu_model-1].mixer->n_mixer_channels; ch++) {
86         uint32_t flags = channels[ch].flags;
87         if (flags & MOTU_CTRL_CHANNEL_FADER)
88             fader_mmixer->addColInfo(channels[ch].name, 0, channels[ch].addr_ofs);
89         if (flags & MOTU_CTRL_CHANNEL_PAN)
90             pan_mmixer->addColInfo(channels[ch].name, 0, channels[ch].addr_ofs);
91         if (flags & MOTU_CTRL_CHANNEL_SOLO)
92             solo_mmixer->addColInfo(channels[ch].name, 0, channels[ch].addr_ofs);
93         if (flags & MOTU_CTRL_CHANNEL_MUTE)
94             mute_mmixer->addColInfo(channels[ch].name, 0, channels[ch].addr_ofs);
95         flags &= ~(MOTU_CTRL_CHANNEL_FADER|MOTU_CTRL_CHANNEL_PAN|MOTU_CTRL_CHANNEL_SOLO|MOTU_CTRL_CHANNEL_MUTE);
96         if (flags) {
97             debugOutput(DEBUG_LEVEL_WARNING, "Control %s: unknown flag bits 0x%08x\n", channels[ch].name, flags);
98         }
99     }
100
101     // Single non-matrixed mixer controls get added here.  Channel controls are supported
102     // here, but usually these will be a part of a matrix mixer.
103     for (i=0; i<DevicesProperty[m_motu_model-1].mixer->n_mixer_ctrls; i++) {
104         const struct MixerCtrl *ctrl = &DevicesProperty[m_motu_model-1].mixer->mixer_ctrl[i];
105         unsigned int type;
106         char name[100];
107         char label[100];
108
109         if (ctrl == NULL) {
110             debugOutput(DEBUG_LEVEL_WARNING, "NULL control at index %d for model %d\n", i, m_motu_model);
111             continue;
112         }
113         type = ctrl->type;
114         if (type & MOTU_CTRL_CHANNEL_FADER) {
115             snprintf(name, 100, "%s%s", ctrl->name, "fader");
116             snprintf(label,100, "%s%s", ctrl->label,"fader");
117             result &= m_MixerContainer->addElement(
118                 new ChannelFader(*this, ctrl->dev_register, name, label, ctrl->desc));
119             type &= ~MOTU_CTRL_CHANNEL_FADER;
120         }
121         if (type & MOTU_CTRL_CHANNEL_PAN) {
122             snprintf(name, 100, "%s%s", ctrl->name, "pan");
123             snprintf(label,100, "%s%s", ctrl->label,"pan");
124             result &= m_MixerContainer->addElement(
125                 new ChannelPan(*this,
126                     ctrl->dev_register,
127                     name, label,
128                     ctrl->desc));
129             type &= ~MOTU_CTRL_CHANNEL_PAN;
130         }
131         if (type & MOTU_CTRL_CHANNEL_MUTE) {
132             snprintf(name, 100, "%s%s", ctrl->name, "mute");
133             snprintf(label,100, "%s%s", ctrl->label,"mute");
134             result &= m_MixerContainer->addElement(
135                 new MotuBinarySwitch(*this, ctrl->dev_register,
136                     MOTU_CTRL_MASK_MUTE_VALUE, MOTU_CTRL_MASK_MUTE_SETENABLE,
137                     name, label, ctrl->desc));
138             type &= ~MOTU_CTRL_CHANNEL_MUTE;
139         }
140         if (type & MOTU_CTRL_CHANNEL_SOLO) {
141             snprintf(name, 100, "%s%s", ctrl->name, "solo");
142             snprintf(label,100, "%s%s", ctrl->label,"solo");
143             result &= m_MixerContainer->addElement(
144                 new MotuBinarySwitch(*this, ctrl->dev_register,
145                     MOTU_CTRL_MASK_SOLO_VALUE, MOTU_CTRL_MASK_SOLO_SETENABLE,
146                     name, label, ctrl->desc));
147             type &= ~MOTU_CTRL_CHANNEL_SOLO;
148         }
149
150         if (type & MOTU_CTRL_MIX_FADER) {
151             snprintf(name, 100, "%s%s", ctrl->name, "fader");
152             snprintf(label,100, "%s%s", ctrl->label,"fader");
153             result &= m_MixerContainer->addElement(
154                 new MixFader(*this, ctrl->dev_register, name, label, ctrl->desc));
155             type &= ~MOTU_CTRL_MIX_FADER;
156         }
157         if (type & MOTU_CTRL_MIX_MUTE) {
158             snprintf(name, 100, "%s%s", ctrl->name, "mute");
159             snprintf(label,100, "%s%s", ctrl->label,"mute");
160             result &= m_MixerContainer->addElement(
161                 new MixMute(*this, ctrl->dev_register, name, label, ctrl->desc));
162             type &= ~MOTU_CTRL_MIX_MUTE;
163         }
164         if (type & MOTU_CTRL_MIX_DEST) {
165             snprintf(name, 100, "%s%s", ctrl->name, "dest");
166             snprintf(label,100, "%s%s", ctrl->label,"dest");
167             result &= m_MixerContainer->addElement(
168                 new MixDest(*this, ctrl->dev_register, name, label, ctrl->desc));
169             type &= ~MOTU_CTRL_MIX_DEST;
170         }
171
172         if (type & MOTU_CTRL_INPUT_UL_GAIN) {
173             snprintf(name, 100, "%s%s", ctrl->name, "trimgain");
174             snprintf(label,100, "%s%s", ctrl->label,"trimgain");
175             result &= m_MixerContainer->addElement(
176                 new InputGainPadInv(*this, ctrl->dev_register, MOTU_CTRL_MODE_UL_GAIN,
177                     name, label, ctrl->desc));
178             type &= ~MOTU_CTRL_INPUT_UL_GAIN;
179         }
180         if (type & MOTU_CTRL_INPUT_PHASE_INV) {
181             snprintf(name, 100, "%s%s", ctrl->name, "invert");
182             snprintf(label,100, "%s%s", ctrl->label,"invert");
183             result &= m_MixerContainer->addElement(
184                 new InputGainPadInv(*this, ctrl->dev_register, MOTU_CTRL_MODE_PHASE_INV,
185                     name, label, ctrl->desc));
186             type &= ~MOTU_CTRL_INPUT_PHASE_INV;
187         }
188         if (type & MOTU_CTRL_INPUT_TRIMGAIN) {
189             snprintf(name, 100, "%s%s", ctrl->name, "trimgain");
190             snprintf(label,100, "%s%s", ctrl->label,"trimgain");
191             result &= m_MixerContainer->addElement(
192                 new InputGainPadInv(*this, ctrl->dev_register, MOTU_CTRL_MODE_TRIMGAIN,
193                     name, label, ctrl->desc));
194             type &= ~MOTU_CTRL_INPUT_TRIMGAIN;
195         }
196         if (type & MOTU_CTRL_INPUT_PAD) {
197             snprintf(name, 100, "%s%s", ctrl->name, "pad");
198             snprintf(label,100, "%s%s", ctrl->label,"pad");
199             result &= m_MixerContainer->addElement(
200                 new InputGainPadInv(*this, ctrl->dev_register, MOTU_CTRL_MODE_PAD,
201                     name, label, ctrl->desc));
202             type &= ~MOTU_CTRL_INPUT_PAD;
203         }
204
205         if (type & MOTU_CTRL_INPUT_LEVEL) {
206             snprintf(name, 100, "%s%s", ctrl->name, "level");
207             snprintf(label,100, "%s%s", ctrl->label,"level");
208             result &= m_MixerContainer->addElement(
209                 new MotuBinarySwitch(*this, MOTU_REG_INPUT_LEVEL,
210                     1<<ctrl->dev_register, 0, name, label, ctrl->desc));
211             type &= ~MOTU_CTRL_INPUT_LEVEL;
212         }
213         if (type & MOTU_CTRL_INPUT_BOOST) {
214             snprintf(name, 100, "%s%s", ctrl->name, "boost");
215             snprintf(label,100, "%s%s", ctrl->label,"boost");
216             result &= m_MixerContainer->addElement(
217                 new MotuBinarySwitch(*this, MOTU_REG_INPUT_BOOST,
218                     1<<ctrl->dev_register, 0, name, label, ctrl->desc));
219             type &= ~MOTU_CTRL_INPUT_BOOST;
220         }
221         if (type & MOTU_CTRL_PHONES_SRC) {
222             snprintf(name, 100, "%s%s", ctrl->name, "src");
223             snprintf(label,100, "%s%s", ctrl->label,"src");
224             result &= m_MixerContainer->addElement(
225                 new PhonesSrc(*this, name, label, ctrl->desc));
226             type &= ~MOTU_CTRL_PHONES_SRC;
227         }
228         if (type & MOTU_CTRL_OPTICAL_MODE) {
229             result &= m_MixerContainer->addElement(
230                 new OpticalMode(*this, ctrl->dev_register,
231                     ctrl->name, ctrl->label, ctrl->desc));
232             type &= ~MOTU_CTRL_OPTICAL_MODE;
233         }
234         if (type & MOTU_CTRL_METER) {
235             if (ctrl->dev_register & MOTU_CTRL_METER_PEAKHOLD) {
236                 snprintf(name, 100, "%s%s", ctrl->name, "peakhold_time");
237                 snprintf(label,100, "%s%s", ctrl->label,"peakhold time");
238                 result &= m_MixerContainer->addElement(
239                     new MeterControl(*this, MOTU_METER_PEAKHOLD_MASK,
240                         MOTU_METER_PEAKHOLD_SHIFT, name, label, ctrl->desc));
241             }
242             if (ctrl->dev_register & MOTU_CTRL_METER_CLIPHOLD) {
243                 snprintf(name, 100, "%s%s", ctrl->name, "cliphold_time");
244                 snprintf(label,100, "%s%s", ctrl->label,"cliphold time");
245                 result &= m_MixerContainer->addElement(
246                     new MeterControl(*this, MOTU_METER_CLIPHOLD_MASK,
247                         MOTU_METER_CLIPHOLD_SHIFT, name, label, ctrl->desc));
248             }
249             if (ctrl->dev_register & MOTU_CTRL_METER_AESEBU_SRC) {
250                 snprintf(name, 100, "%s%s", ctrl->name, "aesebu_src");
251                 snprintf(label,100, "%s%s", ctrl->label,"AESEBU source");
252                 result &= m_MixerContainer->addElement(
253                     new MeterControl(*this, MOTU_METER_AESEBU_SRC_MASK,
254                         MOTU_METER_AESEBU_SRC_SHIFT, name, label, ctrl->desc));
255             }
256             if (ctrl->dev_register & MOTU_CTRL_METER_PROG_SRC) {
257                 snprintf(name, 100, "%s%s", ctrl->name, "src");
258                 snprintf(label,100, "%s%s", ctrl->label,"source");
259                 result &= m_MixerContainer->addElement(
260                     new MeterControl(*this, MOTU_METER_PROG_SRC_MASK,
261                         MOTU_METER_PROG_SRC_SHIFT, name, label, ctrl->desc));
262             }
263             type &= ~MOTU_CTRL_METER;
264         }
265
266         if (type) {
267             debugOutput(DEBUG_LEVEL_WARNING, "Unknown mixer control type flag bits 0x%08x\n", ctrl->type);
268         }
269     }
270     return result;
271 }
272
273 bool
274 MotuDevice::buildMark3MixerAudioControls(void) {
275
276     bool result = true;
277
278     if (DevicesProperty[m_motu_model-1].m3mixer == NULL) {
279         debugOutput(DEBUG_LEVEL_INFO, "No Mark3 mixer controls defined for model %d\n", m_motu_model);
280         return false;
281     }
282
283     // FIXME: Details to come
284     result = false;
285
286     return result;
287 }
288
289 bool
290 MotuDevice::buildMixer() {
291     bool result = true;
292     debugOutput(DEBUG_LEVEL_VERBOSE, "Building a MOTU mixer...\n");
293
294     destroyMixer();
295        
296     // create the mixer object container
297     m_MixerContainer = new Control::Container(this, "Mixer");
298     if (!m_MixerContainer) {
299         debugError("Could not create mixer container...\n");
300         return false;
301     }
302
303     if (DevicesProperty[m_motu_model-1].mixer != NULL &&
304         DevicesProperty[m_motu_model-1].m3mixer != NULL) {
305         debugError("MOTU model %d has pre-Mark3 and Mark3 mixer descriptions\n", m_motu_model);
306         return false;
307     }
308
309     // Create and populate the top-level matrix mixers
310     result = buildMixerAudioControls() || buildMark3MixerAudioControls();
311
312     /* Now add some general device information controls.  These may yet
313      * become device-specific if it turns out to be easier that way.
314      */
315     result &= m_MixerContainer->addElement(
316         new InfoElement(*this, MOTU_INFO_MODEL, "Info/Model", "Model identifier", ""));
317     result &= m_MixerContainer->addElement(
318         new InfoElement(*this, MOTU_INFO_IS_STREAMING, "Info/IsStreaming", "Is device streaming", ""));
319     result &= m_MixerContainer->addElement(
320         new InfoElement(*this, MOTU_INFO_SAMPLE_RATE, "Info/SampleRate", "Device sample rate", ""));
321
322     if (!addElement(m_MixerContainer)) {
323         debugWarning("Could not register mixer to device\n");
324         // clean up
325         destroyMixer();
326         return false;
327     }
328
329     // Special controls
330     m_ControlContainer = new Control::Container(this, "Control");
331     if (!m_ControlContainer) {
332         debugError("Could not create control container...\n");
333         return false;
334     }
335
336     // Special controls get added here
337
338     if (!result) {
339         debugWarning("One or more device control elements could not be created.");
340         // clean up those that couldn't be created
341         destroyMixer();
342         return false;
343     }
344     if (!addElement(m_ControlContainer)) {
345         debugWarning("Could not register controls to device\n");
346         // clean up
347         destroyMixer();
348         return false;
349     }
350
351     return true;
352 }
353
354
355 bool
356 MotuDevice::destroyMixer() {
357     debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
358
359     if (m_MixerContainer == NULL) {
360         debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
361         return true;
362     }
363    
364     if (!deleteElement(m_MixerContainer)) {
365         debugError("Mixer present but not registered to the avdevice\n");
366         return false;
367     }
368
369     // remove and delete (as in free) child control elements
370     m_MixerContainer->clearElements(true);
371     delete m_MixerContainer;
372     m_MixerContainer = NULL;
373
374     // remove control container
375     if (m_ControlContainer == NULL) {
376         debugOutput(DEBUG_LEVEL_VERBOSE, "no controls to destroy...\n");
377         return true;
378     }
379    
380     if (!deleteElement(m_ControlContainer)) {
381         debugError("Controls present but not registered to the avdevice\n");
382         return false;
383     }
384    
385     // remove and delete (as in free) child control elements
386     m_ControlContainer->clearElements(true);
387     delete m_ControlContainer;
388     m_ControlContainer = NULL;
389
390     return true;
391 }
392
393 }
Note: See TracBrowser for help on using the browser.