2 * Copyright (C) 2005-2008 by Pieter Palmers
3 * Copyright (C) 2005-2009 by Jonathan Woithe
5 * This file is part of FFADO
6 * FFADO = Free Firewire (pro-)audio drivers for linux
8 * FFADO is based upon FreeBoB.
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.
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.
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/>.
25 /* This file collects together everything associated with the management
26 * of mixer controls in the MOTU device object.
29 #include "motu/motu_avdevice.h"
30 #include "motu/motu_mixerdefs.h"
31 #include "motu/motu_mark3_mixerdefs.h"
36 MotuDevice::buildMixerAudioControls(void) {
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
;
47 if (DevicesProperty
[m_motu_model
-1].mixer
== NULL
) {
48 debugOutput(DEBUG_LEVEL_INFO
, "No pre-Mark3 mixer defined for model %d\n", m_motu_model
);
51 buses
= DevicesProperty
[m_motu_model
-1].mixer
->mixer_buses
;
54 debugOutput(DEBUG_LEVEL_INFO
, "No mixer buses defined for model %d\n", m_motu_model
);
57 channels
= DevicesProperty
[m_motu_model
-1].mixer
->mixer_channels
;
58 if (channels
== NULL
) {
59 debugOutput(DEBUG_LEVEL_INFO
, "No mixer channels defined for model %d\n", m_motu_model
);
62 if (DevicesProperty
[m_motu_model
-1].mixer
->mixer_ctrl
== NULL
) {
63 debugOutput(DEBUG_LEVEL_INFO
, "No mixer device controls defined for model %d\n", m_motu_model
);
67 if (result
== false) {
71 /* Create the top-level matrix mixers */
72 fader_mmixer
= new ChannelFaderMatrixMixer(*this, "fader");
73 result
&= m_MixerContainer
->addElement(fader_mmixer
);
74 pan_mmixer
= new ChannelPanMatrixMixer(*this, "pan");
75 result
&= m_MixerContainer
->addElement(pan_mmixer
);
76 solo_mmixer
= new ChannelBinSwMatrixMixer(*this, "solo",
77 MOTU_CTRL_MASK_SOLO_VALUE
, MOTU_CTRL_MASK_SOLO_SETENABLE
);
78 result
&= m_MixerContainer
->addElement(solo_mmixer
);
79 mute_mmixer
= new ChannelBinSwMatrixMixer(*this, "mute",
80 MOTU_CTRL_MASK_MUTE_VALUE
, MOTU_CTRL_MASK_MUTE_SETENABLE
);
81 result
&= m_MixerContainer
->addElement(mute_mmixer
);
83 for (bus
=0; bus
<DevicesProperty
[m_motu_model
-1].mixer
->n_mixer_buses
; bus
++) {
84 fader_mmixer
->addRowInfo(buses
[bus
].name
, 0, buses
[bus
].address
);
85 pan_mmixer
->addRowInfo(buses
[bus
].name
, 0, buses
[bus
].address
);
86 solo_mmixer
->addRowInfo(buses
[bus
].name
, 0, buses
[bus
].address
);
87 mute_mmixer
->addRowInfo(buses
[bus
].name
, 0, buses
[bus
].address
);
90 for (ch
=0; ch
<DevicesProperty
[m_motu_model
-1].mixer
->n_mixer_channels
; ch
++) {
91 uint32_t flags
= channels
[ch
].flags
;
92 if (flags
& MOTU_CTRL_CHANNEL_FADER
)
93 fader_mmixer
->addColInfo(channels
[ch
].name
, 0, channels
[ch
].addr_ofs
);
94 if (flags
& MOTU_CTRL_CHANNEL_PAN
)
95 pan_mmixer
->addColInfo(channels
[ch
].name
, 0, channels
[ch
].addr_ofs
);
96 if (flags
& MOTU_CTRL_CHANNEL_SOLO
)
97 solo_mmixer
->addColInfo(channels
[ch
].name
, 0, channels
[ch
].addr_ofs
);
98 if (flags
& MOTU_CTRL_CHANNEL_MUTE
)
99 mute_mmixer
->addColInfo(channels
[ch
].name
, 0, channels
[ch
].addr_ofs
);
100 flags
&= ~(MOTU_CTRL_CHANNEL_FADER
|MOTU_CTRL_CHANNEL_PAN
|MOTU_CTRL_CHANNEL_SOLO
|MOTU_CTRL_CHANNEL_MUTE
);
102 debugOutput(DEBUG_LEVEL_WARNING
, "Control %s: unknown flag bits 0x%08x\n", channels
[ch
].name
, flags
);
106 // Single non-matrixed mixer controls get added here. Channel controls are supported
107 // here, but usually these will be a part of a matrix mixer.
108 for (i
=0; i
<DevicesProperty
[m_motu_model
-1].mixer
->n_mixer_ctrls
; i
++) {
109 const struct MixerCtrl
*ctrl
= &DevicesProperty
[m_motu_model
-1].mixer
->mixer_ctrl
[i
];
115 debugOutput(DEBUG_LEVEL_WARNING
, "NULL control at index %d for model %d\n", i
, m_motu_model
);
119 if (type
& MOTU_CTRL_CHANNEL_FADER
) {
120 snprintf(name
, 100, "%s%s", ctrl
->name
, "fader");
121 snprintf(label
,100, "%s%s", ctrl
->label
,"fader");
122 result
&= m_MixerContainer
->addElement(
123 new ChannelFader(*this, ctrl
->dev_register
, name
, label
, ctrl
->desc
));
124 type
&= ~MOTU_CTRL_CHANNEL_FADER
;
126 if (type
& MOTU_CTRL_CHANNEL_PAN
) {
127 snprintf(name
, 100, "%s%s", ctrl
->name
, "pan");
128 snprintf(label
,100, "%s%s", ctrl
->label
,"pan");
129 result
&= m_MixerContainer
->addElement(
130 new ChannelPan(*this,
134 type
&= ~MOTU_CTRL_CHANNEL_PAN
;
136 if (type
& MOTU_CTRL_CHANNEL_MUTE
) {
137 snprintf(name
, 100, "%s%s", ctrl
->name
, "mute");
138 snprintf(label
,100, "%s%s", ctrl
->label
,"mute");
139 result
&= m_MixerContainer
->addElement(
140 new MotuBinarySwitch(*this, ctrl
->dev_register
,
141 MOTU_CTRL_MASK_MUTE_VALUE
, MOTU_CTRL_MASK_MUTE_SETENABLE
,
142 name
, label
, ctrl
->desc
));
143 type
&= ~MOTU_CTRL_CHANNEL_MUTE
;
145 if (type
& MOTU_CTRL_CHANNEL_SOLO
) {
146 snprintf(name
, 100, "%s%s", ctrl
->name
, "solo");
147 snprintf(label
,100, "%s%s", ctrl
->label
,"solo");
148 result
&= m_MixerContainer
->addElement(
149 new MotuBinarySwitch(*this, ctrl
->dev_register
,
150 MOTU_CTRL_MASK_SOLO_VALUE
, MOTU_CTRL_MASK_SOLO_SETENABLE
,
151 name
, label
, ctrl
->desc
));
152 type
&= ~MOTU_CTRL_CHANNEL_SOLO
;
155 if (type
& MOTU_CTRL_MIX_FADER
) {
156 snprintf(name
, 100, "%s%s", ctrl
->name
, "fader");
157 snprintf(label
,100, "%s%s", ctrl
->label
,"fader");
158 result
&= m_MixerContainer
->addElement(
159 new MixFader(*this, ctrl
->dev_register
, name
, label
, ctrl
->desc
));
160 type
&= ~MOTU_CTRL_MIX_FADER
;
162 if (type
& MOTU_CTRL_MIX_MUTE
) {
163 snprintf(name
, 100, "%s%s", ctrl
->name
, "mute");
164 snprintf(label
,100, "%s%s", ctrl
->label
,"mute");
165 result
&= m_MixerContainer
->addElement(
166 new MixMute(*this, ctrl
->dev_register
, name
, label
, ctrl
->desc
));
167 type
&= ~MOTU_CTRL_MIX_MUTE
;
169 if (type
& MOTU_CTRL_MIX_DEST
) {
170 snprintf(name
, 100, "%s%s", ctrl
->name
, "dest");
171 snprintf(label
,100, "%s%s", ctrl
->label
,"dest");
172 result
&= m_MixerContainer
->addElement(
173 new MixDest(*this, ctrl
->dev_register
, name
, label
, ctrl
->desc
));
174 type
&= ~MOTU_CTRL_MIX_DEST
;
177 if (type
& MOTU_CTRL_INPUT_UL_GAIN
) {
178 snprintf(name
, 100, "%s%s", ctrl
->name
, "trimgain");
179 snprintf(label
,100, "%s%s", ctrl
->label
,"trimgain");
180 result
&= m_MixerContainer
->addElement(
181 new InputGainPadInv(*this, ctrl
->dev_register
, MOTU_CTRL_MODE_UL_GAIN
,
182 name
, label
, ctrl
->desc
));
183 type
&= ~MOTU_CTRL_INPUT_UL_GAIN
;
185 if (type
& MOTU_CTRL_INPUT_PHASE_INV
) {
186 snprintf(name
, 100, "%s%s", ctrl
->name
, "invert");
187 snprintf(label
,100, "%s%s", ctrl
->label
,"invert");
188 result
&= m_MixerContainer
->addElement(
189 new InputGainPadInv(*this, ctrl
->dev_register
, MOTU_CTRL_MODE_PHASE_INV
,
190 name
, label
, ctrl
->desc
));
191 type
&= ~MOTU_CTRL_INPUT_PHASE_INV
;
193 if (type
& MOTU_CTRL_INPUT_TRIMGAIN
) {
194 snprintf(name
, 100, "%s%s", ctrl
->name
, "trimgain");
195 snprintf(label
,100, "%s%s", ctrl
->label
,"trimgain");
196 result
&= m_MixerContainer
->addElement(
197 new InputGainPadInv(*this, ctrl
->dev_register
, MOTU_CTRL_MODE_TRIMGAIN
,
198 name
, label
, ctrl
->desc
));
199 type
&= ~MOTU_CTRL_INPUT_TRIMGAIN
;
201 if (type
& MOTU_CTRL_INPUT_PAD
) {
202 snprintf(name
, 100, "%s%s", ctrl
->name
, "pad");
203 snprintf(label
,100, "%s%s", ctrl
->label
,"pad");
204 result
&= m_MixerContainer
->addElement(
205 new InputGainPadInv(*this, ctrl
->dev_register
, MOTU_CTRL_MODE_PAD
,
206 name
, label
, ctrl
->desc
));
207 type
&= ~MOTU_CTRL_INPUT_PAD
;
210 if (type
& MOTU_CTRL_INPUT_LEVEL
) {
211 snprintf(name
, 100, "%s%s", ctrl
->name
, "level");
212 snprintf(label
,100, "%s%s", ctrl
->label
,"level");
213 result
&= m_MixerContainer
->addElement(
214 new MotuBinarySwitch(*this, MOTU_REG_INPUT_LEVEL
,
215 1<<ctrl
->dev_register
, 0, name
, label
, ctrl
->desc
));
216 type
&= ~MOTU_CTRL_INPUT_LEVEL
;
218 if (type
& MOTU_CTRL_INPUT_BOOST
) {
219 snprintf(name
, 100, "%s%s", ctrl
->name
, "boost");
220 snprintf(label
,100, "%s%s", ctrl
->label
,"boost");
221 result
&= m_MixerContainer
->addElement(
222 new MotuBinarySwitch(*this, MOTU_REG_INPUT_BOOST
,
223 1<<ctrl
->dev_register
, 0, name
, label
, ctrl
->desc
));
224 type
&= ~MOTU_CTRL_INPUT_BOOST
;
226 if (type
& MOTU_CTRL_PHONES_SRC
) {
227 snprintf(name
, 100, "%s%s", ctrl
->name
, "src");
228 snprintf(label
,100, "%s%s", ctrl
->label
,"src");
229 result
&= m_MixerContainer
->addElement(
230 new PhonesSrc(*this, name
, label
, ctrl
->desc
));
231 type
&= ~MOTU_CTRL_PHONES_SRC
;
233 if (type
& MOTU_CTRL_OPTICAL_MODE
) {
234 result
&= m_MixerContainer
->addElement(
235 new OpticalMode(*this, ctrl
->dev_register
,
236 ctrl
->name
, ctrl
->label
, ctrl
->desc
));
237 type
&= ~MOTU_CTRL_OPTICAL_MODE
;
239 if (type
& MOTU_CTRL_METER
) {
240 if (ctrl
->dev_register
& MOTU_CTRL_METER_PEAKHOLD
) {
241 snprintf(name
, 100, "%s%s", ctrl
->name
, "peakhold_time");
242 snprintf(label
,100, "%s%s", ctrl
->label
,"peakhold time");
243 result
&= m_MixerContainer
->addElement(
244 new MeterControl(*this, MOTU_METER_PEAKHOLD_MASK
,
245 MOTU_METER_PEAKHOLD_SHIFT
, name
, label
, ctrl
->desc
));
247 if (ctrl
->dev_register
& MOTU_CTRL_METER_CLIPHOLD
) {
248 snprintf(name
, 100, "%s%s", ctrl
->name
, "cliphold_time");
249 snprintf(label
,100, "%s%s", ctrl
->label
,"cliphold time");
250 result
&= m_MixerContainer
->addElement(
251 new MeterControl(*this, MOTU_METER_CLIPHOLD_MASK
,
252 MOTU_METER_CLIPHOLD_SHIFT
, name
, label
, ctrl
->desc
));
254 if (ctrl
->dev_register
& MOTU_CTRL_METER_AESEBU_SRC
) {
255 snprintf(name
, 100, "%s%s", ctrl
->name
, "aesebu_src");
256 snprintf(label
,100, "%s%s", ctrl
->label
,"AESEBU source");
257 result
&= m_MixerContainer
->addElement(
258 new MeterControl(*this, MOTU_METER_AESEBU_SRC_MASK
,
259 MOTU_METER_AESEBU_SRC_SHIFT
, name
, label
, ctrl
->desc
));
261 if (ctrl
->dev_register
& MOTU_CTRL_METER_PROG_SRC
) {
262 snprintf(name
, 100, "%s%s", ctrl
->name
, "src");
263 snprintf(label
,100, "%s%s", ctrl
->label
,"source");
264 result
&= m_MixerContainer
->addElement(
265 new MeterControl(*this, MOTU_METER_PROG_SRC_MASK
,
266 MOTU_METER_PROG_SRC_SHIFT
, name
, label
, ctrl
->desc
));
268 type
&= ~MOTU_CTRL_METER
;
272 debugOutput(DEBUG_LEVEL_WARNING
, "Unknown mixer control type flag bits 0x%08x\n", ctrl
->type
);
279 MotuDevice::buildMark3MixerAudioControls(void) {
283 if (DevicesProperty
[m_motu_model
-1].m3mixer
== NULL
) {
284 debugOutput(DEBUG_LEVEL_INFO
, "No Mark3 mixer controls defined for model %d\n", m_motu_model
);
288 // FIXME: Details to come
295 MotuDevice::buildMixer() {
297 debugOutput(DEBUG_LEVEL_VERBOSE
, "Building a MOTU mixer...\n");
301 // create the mixer object container
302 m_MixerContainer
= new Control::Container(this, "Mixer");
303 if (!m_MixerContainer
) {
304 debugError("Could not create mixer container...\n");
308 if (DevicesProperty
[m_motu_model
-1].mixer
!= NULL
&&
309 DevicesProperty
[m_motu_model
-1].m3mixer
!= NULL
) {
310 debugError("MOTU model %d has pre-Mark3 and Mark3 mixer descriptions\n", m_motu_model
);
314 // Create and populate the top-level matrix mixers
315 result
= buildMixerAudioControls() || buildMark3MixerAudioControls();
317 /* Now add some general device information controls. These may yet
318 * become device-specific if it turns out to be easier that way.
320 result
&= m_MixerContainer
->addElement(
321 new InfoElement(*this, MOTU_INFO_MODEL
, "Info/Model", "Model identifier", ""));
322 result
&= m_MixerContainer
->addElement(
323 new InfoElement(*this, MOTU_INFO_IS_STREAMING
, "Info/IsStreaming", "Is device streaming", ""));
324 result
&= m_MixerContainer
->addElement(
325 new InfoElement(*this, MOTU_INFO_SAMPLE_RATE
, "Info/SampleRate", "Device sample rate", ""));
327 if (!addElement(m_MixerContainer
)) {
328 debugWarning("Could not register mixer to device\n");
335 m_ControlContainer
= new Control::Container(this, "Control");
336 if (!m_ControlContainer
) {
337 debugError("Could not create control container...\n");
341 // Special controls get added here
344 debugWarning("One or more device control elements could not be created.");
345 // clean up those that couldn't be created
349 if (!addElement(m_ControlContainer
)) {
350 debugWarning("Could not register controls to device\n");
361 MotuDevice::destroyMixer() {
362 debugOutput(DEBUG_LEVEL_VERBOSE
, "destroy mixer...\n");
364 if (m_MixerContainer
== NULL
) {
365 debugOutput(DEBUG_LEVEL_VERBOSE
, "no mixer to destroy...\n");
369 if (!deleteElement(m_MixerContainer
)) {
370 debugError("Mixer present but not registered to the avdevice\n");
374 // remove and delete (as in free) child control elements
375 m_MixerContainer
->clearElements(true);
376 delete m_MixerContainer
;
377 m_MixerContainer
= NULL
;
379 // remove control container
380 if (m_ControlContainer
== NULL
) {
381 debugOutput(DEBUG_LEVEL_VERBOSE
, "no controls to destroy...\n");
385 if (!deleteElement(m_ControlContainer
)) {
386 debugError("Controls present but not registered to the avdevice\n");
390 // remove and delete (as in free) child control elements
391 m_ControlContainer
->clearElements(true);
392 delete m_ControlContainer
;
393 m_ControlContainer
= NULL
;