root/branches/libffado-2.0-with-panning/src/bebob/bebob_mixer.cpp

Revision 1338, 10.8 kB (checked in by wagi, 12 years ago)

- Add AV/C command for LRBalance feature function block
- Expose for each found feature function block one level feature

function mixer element and one left right balance feature
function mixer element.

- Add 'Volume' or 'LRBalance' as dbus

Line 
1 /*
2  * Copyright (C) 2005-2008 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "bebob/bebob_mixer.h"
25
26 #include "bebob/bebob_avdevice.h"
27 #include "bebob/bebob_avdevice_subunit.h"
28
29 #include "libavc/audiosubunit/avc_function_block.h"
30 #include "libutil/cmd_serialize.h"
31
32 #include "libcontrol/BasicElements.h"
33
34 #include "libieee1394/ieee1394service.h"
35 #include "libieee1394/configrom.h"
36
37 #include <string>
38 #include <sstream>
39 #include <iostream>
40
41 #include <assert.h>
42
43 using namespace AVC;
44
45 namespace BeBoB {
46
47 template <class T>
48 bool from_string(T& t,
49                  const std::string& s,
50                  std::ios_base& (*f)(std::ios_base&))
51 {
52   std::istringstream iss(s);
53   return !(iss >> f >> t).fail();
54 }
55
56 IMPL_DEBUG_MODULE( Mixer, Mixer, DEBUG_LEVEL_NORMAL );
57
58 Mixer::Mixer(AvDevice &d)
59     : Control::Container(&d)
60     , m_device(d)
61 {
62     addElementForAllFunctionBlocks();
63     if (!d.addElement(this)) {
64         debugWarning("Could not add myself to Control::Container\n");
65     }
66 }
67
68 Mixer::~Mixer() {
69    
70     debugOutput(DEBUG_LEVEL_VERBOSE,"Unregistering from Control::Container...\n");
71     if (!m_device.deleteElement(this)) {
72         debugWarning("Could not delete myself from Control::Container\n");
73     }
74    
75     // delete all our elements since we should have created
76     // them ourselves.
77     for ( Control::ElementVectorIterator it = m_Children.begin();
78       it != m_Children.end();
79       ++it )
80     {
81         debugOutput(DEBUG_LEVEL_NORMAL,"deleting %s...\n", (*it)->getName().c_str());
82         delete *it;
83     }
84 }
85
86 bool
87 Mixer::deleteElement(Element *e)
88 {
89     if (Control::Container::deleteElement(e)) {
90         delete e;
91         return true;
92     } else return false;
93 }
94
95 bool
96 Mixer::clearElements() {
97     // delete all our elements since we should have created
98     // them ourselves.
99     for ( Control::ElementVectorIterator it = m_Children.begin();
100       it != m_Children.end();
101       ++it )
102     {
103         delete *it;
104     }
105     m_Children.clear();
106    
107     return true;
108 }
109
110 template<typename FBType, typename MixerType>
111 bool
112 Mixer::addElementForFunctionBlock(FBType& b)
113 {
114     Control::Element *e = new MixerType(*this, b);
115     if (!e) {
116         debugError("Control element creation failed\n");
117         return false;
118     }
119
120     e->setVerboseLevel(getDebugLevel());
121     return Control::Container::addElement(e);
122 }
123
124 bool
125 Mixer::addElementForAllFunctionBlocks() {
126     debugOutput(DEBUG_LEVEL_NORMAL,"Adding elements for functionblocks...\n");
127
128     bool retval = true;
129
130     BeBoB::SubunitAudio *asu =
131         dynamic_cast<BeBoB::SubunitAudio *>(m_device.getAudioSubunit(0));
132
133     if(asu == NULL) {
134         debugWarning("No BeBoB audio subunit found\n");
135         return false;
136     }
137     FunctionBlockVector functions=asu->getFunctionBlocks();
138
139     for ( FunctionBlockVector::iterator it = functions.begin();
140           it != functions.end();
141           ++it )
142     {
143         FunctionBlock *pfb = *it;
144         FunctionBlockSelector *ps;
145         FunctionBlockFeature *pf;
146         FunctionBlockEnhancedMixer *pm;
147
148         if ((ps = dynamic_cast<FunctionBlockSelector *>(pfb))) {
149             debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a SelectorFunctionBlock\n");
150             retval = addElementForFunctionBlock<FunctionBlockSelector, MixerFBSelector>(*ps);
151         } else if ((pf = dynamic_cast<FunctionBlockFeature *>(pfb))) {
152             // We might should check if really both feature function
153             // blocks exists and only then announce them. The FA-101,
154             // FA-66 and the Ref BCO Audio5 do have both.
155             debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a FeatureFunctionBlock\n");
156             retval  = addElementForFunctionBlock<FunctionBlockFeature, MixerFBFeatureVolume>(*pf);
157             retval &= addElementForFunctionBlock<FunctionBlockFeature, MixerFBFeatureLRBalance>(*pf);
158         } else if ((pm = dynamic_cast<FunctionBlockEnhancedMixer *>(pfb))) {
159             // All BeBoB devices lock the mixer feature function
160             // block. The AV/C model for this mixer is just to
161             // complex and the BridgeCo guys decided to use the above
162             // function feature blocks (level and balance) to achive
163             // the same.
164             debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a FunctionBlockEnhancedMixer\n");
165             retval = addElementForFunctionBlock<FunctionBlockEnhancedMixer, EnhancedMixerFBFeature>(*pm);
166         }
167
168         if (!retval) {
169             std::ostringstream ostrm;
170             ostrm << (*it)->getName() << " " << (int)((*it)->getId());
171            
172             debugWarning("Failed to add element for function block %s\n",
173                 ostrm.str().c_str());
174         };
175     }
176     return retval;
177 }
178
179 // --- element implementation classes
180
181 MixerFBFeatureVolume::MixerFBFeatureVolume(Mixer& parent, FunctionBlockFeature& s)
182 : Control::Continuous(&parent)
183 , m_Parent(parent)
184 , m_Slave(s)
185 {
186     std::ostringstream ostrm;
187     ostrm << s.getName() << "_Volume_" << (int)(s.getId());
188    
189     Control::Continuous::setName(ostrm.str());
190    
191     ostrm.str("");
192     ostrm << "Label for " << s.getName() << "_Volume " << (int)(s.getId());
193     setLabel(ostrm.str());
194    
195     ostrm.str("");
196     ostrm << "Description for " << s.getName() << "_Volume " << (int)(s.getId());
197     setDescription(ostrm.str());
198 }
199
200 MixerFBFeatureVolume::~MixerFBFeatureVolume()
201 {
202 }
203
204 bool
205 MixerFBFeatureVolume::setValue(double v)
206 {
207     return setValue(0, v);
208 }
209
210 bool
211 MixerFBFeatureVolume::setValue(int idx, double v)
212 {
213     int volume=(int)v;
214     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d to %d...\n",
215         m_Slave.getId(), volume);
216     return m_Parent.getParent().setFeatureFBVolumeCurrent(m_Slave.getId(), idx, volume);
217 }
218
219 double
220 MixerFBFeatureVolume::getValue()
221 {
222     return getValue(0);
223 }
224
225 double
226 MixerFBFeatureVolume::getValue(int idx)
227 {
228     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d...\n",
229         m_Slave.getId());
230
231     return m_Parent.getParent().getFeatureFBVolumeCurrent(m_Slave.getId(), idx);
232 }
233
234 double
235 MixerFBFeatureVolume::getMinimum()
236 {
237     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature minimum volume %d...\n",
238         m_Slave.getId());
239
240     return m_Parent.getParent().getFeatureFBVolumeMinimum(m_Slave.getId(), 0);
241 }
242
243 double
244 MixerFBFeatureVolume::getMaximum()
245 {
246     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature maximum volume %d...\n",
247         m_Slave.getId());
248
249     return m_Parent.getParent().getFeatureFBVolumeMaximum(m_Slave.getId(), 0);
250 }
251
252 // --- element implementation classes
253
254 MixerFBFeatureLRBalance::MixerFBFeatureLRBalance(Mixer& parent, FunctionBlockFeature& s)
255 : Control::Continuous(&parent)
256 , m_Parent(parent)
257 , m_Slave(s)
258 {
259     std::ostringstream ostrm;
260     ostrm << s.getName() << "_LRBalance_" << (int)(s.getId());
261    
262     Control::Continuous::setName(ostrm.str());
263    
264     ostrm.str("");
265     ostrm << "Label for " << s.getName() << "_LRBalance " << (int)(s.getId());
266     setLabel(ostrm.str());
267    
268     ostrm.str("");
269     ostrm << "Description for " << s.getName() << "_LRBalance " << (int)(s.getId());
270     setDescription(ostrm.str());
271 }
272
273 MixerFBFeatureLRBalance::~MixerFBFeatureLRBalance()
274 {
275 }
276
277 bool
278 MixerFBFeatureLRBalance::setValue(double v)
279 {
280     return setValue(0, v);
281 }
282
283 bool
284 MixerFBFeatureLRBalance::setValue(int idx, double v)
285 {
286     int volume=(int)v;
287     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature balance %d to %d...\n",
288         m_Slave.getId(), volume);
289     return m_Parent.getParent().setFeatureFBLRBalanceCurrent(m_Slave.getId(), idx, volume);
290 }
291
292 double
293 MixerFBFeatureLRBalance::getValue()
294 {
295     return getValue(0);
296 }
297
298 double
299 MixerFBFeatureLRBalance::getValue(int idx)
300 {
301     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature balance %d...\n",
302         m_Slave.getId());
303
304     return m_Parent.getParent().getFeatureFBLRBalanceCurrent(m_Slave.getId(), idx);
305 }
306
307 double
308 MixerFBFeatureLRBalance::getMinimum()
309 {
310     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature balance volume %d...\n",
311         m_Slave.getId());
312
313     return m_Parent.getParent().getFeatureFBLRBalanceMinimum(m_Slave.getId(), 0);
314 }
315
316 double
317 MixerFBFeatureLRBalance::getMaximum()
318 {
319     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature maximum balance %d...\n",
320         m_Slave.getId());
321
322     return m_Parent.getParent().getFeatureFBLRBalanceMaximum(m_Slave.getId(), 0);
323 }
324
325 // --- element implementation classes
326
327 EnhancedMixerFBFeature::EnhancedMixerFBFeature(Mixer& parent, FunctionBlockEnhancedMixer& s)
328 : Control::Continuous(&parent)
329 , m_Parent(parent)
330 , m_Slave(s)
331 {
332     std::ostringstream ostrm;
333     ostrm << s.getName() << "_" << (int)(s.getId());
334    
335     Control::Continuous::setName(ostrm.str());
336    
337     ostrm.str("");
338     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
339     setLabel(ostrm.str());
340    
341     ostrm.str("");
342     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
343     setDescription(ostrm.str());
344 }
345
346 EnhancedMixerFBFeature::~EnhancedMixerFBFeature()
347 {
348 }
349
350 bool
351 EnhancedMixerFBFeature::setValue(double v)
352 {
353     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d to %d...\n",
354                 m_Slave.getId(), (int)v);
355
356     return true;
357 }
358
359 double
360 EnhancedMixerFBFeature::getValue()
361 {
362     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d...\n",
363                 m_Slave.getId());
364
365     return 0;
366 }
367
368 // --- element implementation classes
369
370 MixerFBSelector::MixerFBSelector(Mixer& parent, FunctionBlockSelector& s)
371 : Control::Discrete(&parent)
372 , m_Parent(parent)
373 , m_Slave(s)
374 {
375     std::ostringstream ostrm;
376     ostrm << s.getName() << "_" << (int)(s.getId());
377    
378     Control::Discrete::setName(ostrm.str());
379    
380     ostrm.str("");
381     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
382     setLabel(ostrm.str());
383    
384     ostrm.str("");
385     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
386     setDescription(ostrm.str());
387 }
388
389 MixerFBSelector::~MixerFBSelector()
390 {
391 }
392
393 bool
394 MixerFBSelector::setValue(int v)
395 {
396     debugOutput(DEBUG_LEVEL_NORMAL,"Set selector %d to %d...\n",
397         m_Slave.getId(), v);
398     return m_Parent.getParent().setSelectorFBValue(m_Slave.getId(), v);
399 }
400
401 int
402 MixerFBSelector::getValue()
403 {
404     debugOutput(DEBUG_LEVEL_NORMAL,"Get selector %d...\n",
405         m_Slave.getId());
406     return m_Parent.getParent().getSelectorFBValue(m_Slave.getId());
407 }
408
409
410 } // end of namespace BeBoB
Note: See TracBrowser for help on using the browser.