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

Revision 644, 10.5 kB (checked in by ppalmers, 16 years ago)

- Adapt the phase 88 mixer control application to the new DBUS control interface

Line 
1 /*
2  * Copyright (C) 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 library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
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 (!e) {
148         debugError("No control element created\n");
149         return false;
150     }
151
152     return retval;
153 }
154
155 bool
156 Mixer::addElementForAllFunctionBlocks() {
157     debugOutput(DEBUG_LEVEL_NORMAL,"Adding elements for functionblocks...\n");
158
159     BeBoB::SubunitAudio *asu =
160         dynamic_cast<BeBoB::SubunitAudio *>(m_device.getAudioSubunit(0));
161
162     if(asu == NULL) {
163         debugWarning("No BeBoB audio subunit found\n");
164         return false;
165     }
166     FunctionBlockVector functions=asu->getFunctionBlocks();
167
168     for ( FunctionBlockVector::iterator it = functions.begin();
169           it != functions.end();
170           ++it )
171     {
172         if (!addElementForFunctionBlock(*(*it))) {
173             std::ostringstream ostrm;
174             ostrm << (*it)->getName() << " " << (int)((*it)->getId());
175            
176             debugWarning("Failed to add element for function block %s\n",
177                 ostrm.str().c_str());
178         };
179     }
180     return true;
181 }
182
183 // --- element implementation classes
184
185 MixerFBFeature::MixerFBFeature(Mixer& parent, FunctionBlockFeature& s)
186 : Control::Continuous()
187 , m_Parent(parent)
188 , m_Slave(s)
189 {
190     std::ostringstream ostrm;
191     ostrm << s.getName() << "_" << (int)(s.getId());
192    
193     Control::Continuous::setName(ostrm.str());
194    
195     ostrm.str("");
196     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
197     setLabel(ostrm.str());
198    
199     ostrm.str("");
200     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
201     setDescription(ostrm.str());
202 }
203
204 bool
205 MixerFBFeature::setValue(double v)
206 {
207     int volume=(int)v;
208     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d to %d...\n",
209         m_Slave.getId(), volume);
210
211     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
212                             FunctionBlockCmd::eFBT_Feature,
213                             m_Slave.getId(),
214                             FunctionBlockCmd::eCA_Current );
215     fbCmd.setNodeId( m_Parent.getParent().getNodeId() );
216     fbCmd.setSubunitId( 0x00 );
217     fbCmd.setCommandType( AVCCommand::eCT_Control );
218     fbCmd.m_pFBFeature->m_audioChannelNumber=0; // m_channel
219     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
220     fbCmd.m_pFBFeature->m_pVolume->m_volume=volume;
221     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
222
223     if ( !fbCmd.fire() ) {
224         debugError( "cmd failed\n" );
225         return false;
226     }
227
228 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
229 //         Util::CoutSerializer se;
230 //         fbCmd.serialize( se );
231 //     }
232    
233     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
234         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
235     }
236
237     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
238 }
239
240 double
241 MixerFBFeature::getValue()
242 {
243     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d...\n",
244         m_Slave.getId());
245
246     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
247                             FunctionBlockCmd::eFBT_Feature,
248                             m_Slave.getId(),
249                             FunctionBlockCmd::eCA_Current );
250     fbCmd.setNodeId( m_Parent.getParent().getNodeId()  );
251     fbCmd.setSubunitId( 0x00 );
252     fbCmd.setCommandType( AVCCommand::eCT_Status );
253     fbCmd.m_pFBFeature->m_audioChannelNumber=0;
254     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume; // FIXME
255     fbCmd.m_pFBFeature->m_pVolume->m_volume=0;
256     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
257
258     if ( !fbCmd.fire() ) {
259         debugError( "cmd failed\n" );
260         return 0;
261     }
262    
263 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
264 //         Util::CoutSerializer se;
265 //         fbCmd.serialize( se );
266 //     }
267
268     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
269         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
270     }
271    
272     int16_t volume=(int16_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume);
273    
274     return volume;
275 }
276
277 // --- element implementation classes
278
279 MixerFBSelector::MixerFBSelector(Mixer& parent, FunctionBlockSelector& s)
280 : Control::Discrete()
281 , m_Parent(parent)
282 , m_Slave(s)
283 {
284     std::ostringstream ostrm;
285     ostrm << s.getName() << "_" << (int)(s.getId());
286    
287     Control::Discrete::setName(ostrm.str());
288    
289     ostrm.str("");
290     ostrm << "Label for " << s.getName() << " " << (int)(s.getId());
291     setLabel(ostrm.str());
292    
293     ostrm.str("");
294     ostrm << "Description for " << s.getName() << " " << (int)(s.getId());
295     setDescription(ostrm.str());
296 }
297
298 bool
299 MixerFBSelector::setValue(int v)
300 {
301     debugOutput(DEBUG_LEVEL_NORMAL,"Set selector %d to %d...\n",
302         m_Slave.getId(), v);
303
304     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
305                             FunctionBlockCmd::eFBT_Selector,
306                             m_Slave.getId(),
307                             FunctionBlockCmd::eCA_Current );
308     fbCmd.setNodeId( m_Parent.getParent().getNodeId() );
309     fbCmd.setSubunitId( 0x00 );
310     fbCmd.setCommandType( AVCCommand::eCT_Control );
311     fbCmd.m_pFBSelector->m_inputFbPlugNumber=(v & 0xFF);
312     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
313
314     if ( !fbCmd.fire() ) {
315         debugError( "cmd failed\n" );
316         return false;
317     }
318
319 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
320 //         Util::CoutSerializer se;
321 //         fbCmd.serialize( se );
322 //     }
323 //     
324     if((fbCmd.getResponse() != AVCCommand::eR_Accepted)) {
325         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Accepted\n");
326     }
327
328     return (fbCmd.getResponse() == AVCCommand::eR_Accepted);
329 }
330
331 int
332 MixerFBSelector::getValue()
333 {
334     debugOutput(DEBUG_LEVEL_NORMAL,"Get selector %d...\n",
335         m_Slave.getId());
336
337     FunctionBlockCmd fbCmd( m_Parent.getParent().get1394Service(),
338                             FunctionBlockCmd::eFBT_Selector,
339                             m_Slave.getId(),
340                             FunctionBlockCmd::eCA_Current );
341     fbCmd.setNodeId( m_Parent.getParent().getNodeId()  );
342     fbCmd.setSubunitId( 0x00 );
343     fbCmd.setCommandType( AVCCommand::eCT_Status );
344     fbCmd.m_pFBSelector->m_inputFbPlugNumber=0;
345     fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
346
347     if ( !fbCmd.fire() ) {
348         debugError( "cmd failed\n" );
349         return 0;
350     }
351    
352 //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
353 //         Util::CoutSerializer se;
354 //         fbCmd.serialize( se );
355 //     }
356
357     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
358         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
359     }
360    
361     return fbCmd.m_pFBSelector->m_inputFbPlugNumber;
362 }
363
364 } // end of namespace BeBoB
Note: See TracBrowser for help on using the browser.