root/trunk/libffado/src/bebob/bebob_mixer.cpp

Revision 824, 11.9 kB (checked in by wagi, 16 years ago)

- moved cmd_serialize.h Util:: namespace to Util::Cmd:: in order to avoid ambiguities with serialize.h
- bebob: enhanced mixer stuff added (not finished)

Line 
1 /*
2  * Copyright (C) 2005-2007 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 3 of the License, or
12  * (at your option) any later version.
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()
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_NORMAL,"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 bool
111 Mixer::addElementForFunctionBlock(FunctionBlock& b) {
112     bool retval=true;
113    
114     std::ostringstream ostrm;
115     ostrm << b.getName() << "_" << (int)(b.getId());
116    
117     debugOutput(DEBUG_LEVEL_NORMAL,"Adding element for functionblock %s...\n",
118         ostrm.str().c_str());
119
120     Control::Element *e=NULL;
121    
122     if (dynamic_cast<FunctionBlockSelector *>(&b) != NULL) {
123         FunctionBlockSelector *bf=dynamic_cast<FunctionBlockSelector *>(&b);
124         debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a SelectorFunctionBlock\n");
125         e=new MixerFBSelector(*this, *bf);
126         if (e) {
127             e->setVerboseLevel(getDebugLevel());
128             retval &= Control::Container::addElement(e);
129         } else {
130             debugError("Control element creation failed\n");
131             retval &= false;
132         }
133     }
134     if (dynamic_cast<FunctionBlockFeature *>(&b) != NULL) {
135         FunctionBlockFeature *bf=dynamic_cast<FunctionBlockFeature *>(&b);
136         debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a FeatureFunctionBlock\n");
137         e=new MixerFBFeature(*this, *bf);
138         if (e) {
139             e->setVerboseLevel(getDebugLevel());
140             retval &= Control::Container::addElement(e);
141         } else {
142             debugError("Control element creation failed\n");
143             retval &= false;
144         }
145     }
146
147     if (dynamic_cast<FunctionBlockEnhancedMixer *>(&b) != NULL) {
148         FunctionBlockEnhancedMixer *bf=dynamic_cast<FunctionBlockEnhancedMixer *>(&b);
149         debugOutput( DEBUG_LEVEL_VERBOSE, "FB is a FunctionBlockEnhancedMixer\n");
150         e=new EnhancedMixerFBFeature(*this, *bf);
151         if (e) {
152             e->setVerboseLevel(getDebugLevel());
153             retval &= Control::Container::addElement(e);
154         } else {
155             debugError("Control element creation failed\n");
156             retval &= false;
157         }
158     }
159    
160     if (!e) {
161         debugError("No control element created\n");
162         return false;
163     }
164
165     return retval;
166 }
167
168 bool
169 Mixer::addElementForAllFunctionBlocks() {
170     debugOutput(DEBUG_LEVEL_NORMAL,"Adding elements for functionblocks...\n");
171
172     BeBoB::SubunitAudio *asu =
173         dynamic_cast<BeBoB::SubunitAudio *>(m_device.getAudioSubunit(0));
174
175     if(asu == NULL) {
176         debugWarning("No BeBoB audio subunit found\n");
177         return false;
178     }
179     FunctionBlockVector functions=asu->getFunctionBlocks();
180
181     for ( FunctionBlockVector::iterator it = functions.begin();
182           it != functions.end();
183           ++it )
184     {
185         if (!addElementForFunctionBlock(*(*it))) {
186             std::ostringstream ostrm;
187             ostrm << (*it)->getName() << " " << (int)((*it)->getId());
188            
189             debugWarning("Failed to add element for function block %s\n",
190                 ostrm.str().c_str());
191         };
192     }
193     return true;
194 }
195
196 // --- element implementation classes
197
198 MixerFBFeature::MixerFBFeature(Mixer& parent, FunctionBlockFeature& s)
199 : Control::Continuous()
200 , m_Parent(parent)
201 , m_Slave(s)
202 {
203     std::ostringstream ostrm;
204     ostrm << s.getName() << "_" << (int)(s.getId());
205    
206     Control::Continuous::setName(ostrm.str());
207    
208     ostrm.str("");
209     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
210     setLabel(ostrm.str());
211    
212     ostrm.str("");
213     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
214     setDescription(ostrm.str());
215 }
216
217 bool
218 MixerFBFeature::setValue(double v)
219 {
220     int volume=(int)v;
221     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d to %d...\n",
222         m_Slave.getId(), volume);
223
224     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
225                             FunctionBlockCmd::eFBT_Feature,
226                             m_Slave.getId(),
227                             FunctionBlockCmd::eCA_Current );
228     fbCmd.setNodeId( m_Parent.getParent().getNodeId() );
229     fbCmd.setSubunitId( 0x00 );
230     fbCmd.setCommandType( AVCCommand::eCT_Control );
231     fbCmd.m_pFBFeature->m_audioChannelNumber=0; // m_channel
232     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
233     fbCmd.m_pFBFeature->m_pVolume->m_volume=volume;
234     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
235
236     if ( !fbCmd.fire() ) {
237         debugError( "cmd failed\n" );
238         return false;
239     }
240
241 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
242 //         Util::CoutSerializer se;
243 //         fbCmd.serialize( se );
244 //     }
245    
246     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
247         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
248     }
249
250     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
251 }
252
253 double
254 MixerFBFeature::getValue()
255 {
256     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d...\n",
257         m_Slave.getId());
258
259     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
260                             FunctionBlockCmd::eFBT_Feature,
261                             m_Slave.getId(),
262                             FunctionBlockCmd::eCA_Current );
263     fbCmd.setNodeId( m_Parent.getParent().getNodeId() );
264     fbCmd.setSubunitId( 0x00 );
265     fbCmd.setCommandType( AVCCommand::eCT_Status );
266     fbCmd.m_pFBFeature->m_audioChannelNumber=0;
267     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume; // FIXME
268     fbCmd.m_pFBFeature->m_pVolume->m_volume=0;
269     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
270
271     if ( !fbCmd.fire() ) {
272         debugError( "cmd failed\n" );
273         return 0;
274     }
275    
276 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
277 //         Util::CoutSerializer se;
278 //         fbCmd.serialize( se );
279 //     }
280
281     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
282         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
283     }
284    
285     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
286    
287     return volume;
288 }
289
290 // --- element implementation classes
291
292 EnhancedMixerFBFeature::EnhancedMixerFBFeature(Mixer& parent, FunctionBlockEnhancedMixer& s)
293 : Control::Continuous()
294 , m_Parent(parent)
295 , m_Slave(s)
296 {
297     std::ostringstream ostrm;
298     ostrm << s.getName() << "_" << (int)(s.getId());
299    
300     Control::Continuous::setName(ostrm.str());
301    
302     ostrm.str("");
303     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
304     setLabel(ostrm.str());
305    
306     ostrm.str("");
307     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
308     setDescription(ostrm.str());
309 }
310
311 bool
312 EnhancedMixerFBFeature::setValue(double v)
313 {
314     int volume=(int)v;
315     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d to %d...\n",
316                 m_Slave.getId(), volume);
317
318     return true;
319 }
320
321 double
322 EnhancedMixerFBFeature::getValue()
323 {
324     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d...\n",
325                 m_Slave.getId());
326
327     return 0;
328 }
329
330 // --- element implementation classes
331
332 MixerFBSelector::MixerFBSelector(Mixer& parent, FunctionBlockSelector& s)
333 : Control::Discrete()
334 , m_Parent(parent)
335 , m_Slave(s)
336 {
337     std::ostringstream ostrm;
338     ostrm << s.getName() << "_" << (int)(s.getId());
339    
340     Control::Discrete::setName(ostrm.str());
341    
342     ostrm.str("");
343     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
344     setLabel(ostrm.str());
345    
346     ostrm.str("");
347     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
348     setDescription(ostrm.str());
349 }
350
351 bool
352 MixerFBSelector::setValue(int v)
353 {
354     debugOutput(DEBUG_LEVEL_NORMAL,"Set selector %d to %d...\n",
355         m_Slave.getId(), v);
356
357     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
358                             FunctionBlockCmd::eFBT_Selector,
359                             m_Slave.getId(),
360                             FunctionBlockCmd::eCA_Current );
361     fbCmd.setNodeId( m_Parent.getParent().getNodeId() );
362     fbCmd.setSubunitId( 0x00 );
363     fbCmd.setCommandType( AVCCommand::eCT_Control );
364     fbCmd.m_pFBSelector->m_inputFbPlugNumber=(v & 0xFF);
365     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
366
367     if ( !fbCmd.fire() ) {
368         debugError( "cmd failed\n" );
369         return false;
370     }
371
372 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
373 //         Util::CoutSerializer se;
374 //         fbCmd.serialize( se );
375 //     }
376 //     
377     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
378         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
379     }
380
381     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
382 }
383
384 int
385 MixerFBSelector::getValue()
386 {
387     debugOutput(DEBUG_LEVEL_NORMAL,"Get selector %d...\n",
388         m_Slave.getId());
389
390     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
391                             FunctionBlockCmd::eFBT_Selector,
392                             m_Slave.getId(),
393                             FunctionBlockCmd::eCA_Current );
394     fbCmd.setNodeId( m_Parent.getParent().getNodeId()  );
395     fbCmd.setSubunitId( 0x00 );
396     fbCmd.setCommandType( AVCCommand::eCT_Status );
397     fbCmd.m_pFBSelector->m_inputFbPlugNumber=0;
398     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
399
400     if ( !fbCmd.fire() ) {
401         debugError( "cmd failed\n" );
402         return 0;
403     }
404    
405 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
406 //         Util::CoutSerializer se;
407 //         fbCmd.serialize( se );
408 //     }
409
410     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
411         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
412     }
413    
414     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
415 }
416
417
418 } // end of namespace BeBoB
Note: See TracBrowser for help on using the browser.