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

Revision 458, 10.4 kB (checked in by ppalmers, 17 years ago)

fix small bug in OSC set volume message parsing

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/GenericMixer.h"
25
26 #include "bebob/bebob_avdevice.h"
27 #include "bebob/bebob_avdevice_subunit.h"
28
29 #include "libosc/OscNode.h"
30 #include "libosc/OscMessage.h"
31 #include "libosc/OscResponse.h"
32
33 #include "libavc/avc_function_block.h"
34 #include "libavc/avc_serialize.h"
35
36 #include "libieee1394/ieee1394service.h"
37
38 #include <sstream>
39 #include <assert.h>
40
41 using namespace OSC;
42
43 namespace BeBoB {
44
45 IMPL_DEBUG_MODULE( GenericMixer, GenericMixer, DEBUG_LEVEL_NORMAL );
46
47 GenericMixer::GenericMixer(
48                 Ieee1394Service& ieee1394service,
49                 AvDevice &d)
50     : OSC::OscNode("GenericMixer")
51     , m_p1394Service( ieee1394service )
52     , m_device(d)
53 {
54
55 }
56
57 GenericMixer::~GenericMixer() {
58
59 }
60
61 OscResponse
62 GenericMixer::processOscMessage(OscMessage *m) {
63     debugOutput(DEBUG_LEVEL_NORMAL, "Message\n");
64    
65     unsigned int nbArgs=m->nbArguments();
66     if (nbArgs>=1) {
67         OscArgument arg0=m->getArgument(0);
68         if(arg0.isString()) { // first argument should be a string command
69             string cmd=arg0.getString();
70             debugOutput( DEBUG_LEVEL_NORMAL, "(%p) CMD? %s\n", this, cmd.c_str());
71             if(cmd == "list") {
72                 debugOutput( DEBUG_LEVEL_NORMAL, "Listing mixer elements...\n");
73                 OscMessage rm=mixerListChildren();
74                 return OscResponse(rm);
75             }
76             if(cmd == "set") {
77                 debugOutput( DEBUG_LEVEL_NORMAL, "setting mixer element...\n");
78                 bool args_ok=true;
79                 args_ok &= (nbArgs>=3);
80                 args_ok &= (m->getArgument(1).isString());
81                 args_ok &= (m->getArgument(2).isInt());
82
83                 if (!args_ok) {
84                     debugWarning("set: Wrong nb of arguments\n");
85                     return OscResponse(OscResponse::eError);
86                 }
87
88                 string type=m->getArgument(1).getString();
89                 int id=m->getArgument(2).getInt();
90                
91                 if (type == "selector") {
92                     if ( !(nbArgs==4)) {
93                         debugWarning("set selector: Wrong nb of arguments\n");
94                         return OscResponse(OscResponse::eError);
95                     }
96                     if(!m->getArgument(3).isNumeric()) {
97                         debugWarning("set selector: Wrong argument type\n");
98                         return OscResponse(OscResponse::eError);
99                     }
100                     int value=m->getArgument(3).toInt();
101                    
102                     return mixerSetSelectorValue(id, value);
103                 }
104                
105                 if (type == "volume") {
106                     if ( !(nbArgs>=5)) {
107                         debugWarning("set volume: Wrong nb of arguments\n");
108                         return OscResponse(OscResponse::eError);
109                     }
110                     if(!m->getArgument(3).isNumeric()) {
111                         debugWarning("set volume: Wrong argument (3) type\n");
112                         return OscResponse(OscResponse::eError);
113                     }
114                     if(!m->getArgument(4).isNumeric()) {
115                         debugWarning("set volume: Wrong argument (4) type\n");
116                         return OscResponse(OscResponse::eError);
117                     }
118                    
119                     int channel=m->getArgument(3).toInt();
120                     int volume=m->getArgument(4).toInt();
121                    
122                     return mixerSetFeatureVolumeValue(id, channel, volume);
123                 }
124
125                 return OscResponse(OscResponse::eError);
126             }
127             if(cmd == "get") {
128                 debugOutput( DEBUG_LEVEL_NORMAL, "getting mixer element...\n");
129                 bool args_ok=true;
130                 args_ok &= (nbArgs>=3);
131                 args_ok &= (m->getArgument(1).isString());
132                 args_ok &= (m->getArgument(2).isInt());
133
134                 if (!args_ok) return OscResponse(OscResponse::eError);
135
136                 string type=m->getArgument(1).getString();
137                 int id=m->getArgument(2).getInt();
138                
139                 if (type == "selector") {
140                     return mixerGetSelectorValue(id);
141                 }
142                
143                 if (type == "volume") {
144                     if ( !(nbArgs==6)) {
145                         debugWarning("set volume: Wrong nb of arguments\n");
146                         return OscResponse(OscResponse::eError);
147                     }
148                     if(!m->getArgument(3).isNumeric()) {
149                         debugWarning("set volume: Wrong argument (3) type\n");
150                         return OscResponse(OscResponse::eError);
151                     }
152
153                     int channel=m->getArgument(3).toInt();
154                    
155                     return mixerGetFeatureVolumeValue(id, channel);
156                 }
157                
158                 return OscResponse(OscResponse::eError);
159
160             }
161         }
162     }
163     debugWarning("Unhandled OSC message!\n");
164     // default action: don't change response
165     return OscResponse(OscResponse::eUnhandled);
166 }
167
168 OscMessage
169 GenericMixer::mixerListChildren() {
170     OscMessage m;
171
172     debugOutput(DEBUG_LEVEL_NORMAL,"Listing mixer elements...\n");
173
174     assert(m_device.getAudioSubunit(0)); // FIXME!!
175     FunctionBlockVector functions=m_device.getAudioSubunit(0)->getFunctionBlocks();
176
177     for ( FunctionBlockVector::iterator it = functions.begin();
178           it != functions.end();
179           ++it )
180     {
181         std::ostringstream ostrm;
182         ostrm << (*it)->getName() << "/" << (int)((*it)->getId());
183         m.addArgument(ostrm.str());
184     }
185
186     m.print();
187     return m;
188 }
189
190 OscResponse
191 GenericMixer::mixerGetSelectorValue(int fb_id) {
192     OscMessage m;
193    
194     debugOutput(DEBUG_LEVEL_NORMAL,"Get selector %d value...\n",
195         fb_id);
196
197     FunctionBlockCmd fbCmd( m_p1394Service,
198                             FunctionBlockCmd::eFBT_Selector,
199                             fb_id,
200                             FunctionBlockCmd::eCA_Current );
201     fbCmd.setNodeId( m_device.getNodeId() );
202     fbCmd.setSubunitId( 0x00 );
203     fbCmd.setCommandType( AVCCommand::eCT_Status );
204     fbCmd.m_pFBSelector->m_inputFbPlugNumber=0xFF;
205
206     fbCmd.setVerbose( getDebugLevel() );
207    
208     if ( !fbCmd.fire() ) {
209         debugError( "FunctionBlockCmd failed\n" );
210         return OscResponse(OscResponse::eError);
211     }
212
213     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
214         CoutSerializer se;
215         fbCmd.serialize( se );
216     }
217    
218     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
219         return OscResponse(OscResponse::eError);
220     }
221    
222     m.addArgument((int32_t)(fbCmd.m_pFBSelector->m_inputFbPlugNumber));
223
224     return OscResponse(m);
225 }
226
227 OscResponse
228 GenericMixer::mixerSetSelectorValue(int fb_id, int value) {
229     OscMessage m;
230    
231     debugOutput(DEBUG_LEVEL_NORMAL,"Set selector %d to %d...\n",
232         fb_id, value);
233
234     FunctionBlockCmd fbCmd( m_p1394Service,
235                             FunctionBlockCmd::eFBT_Selector,
236                             fb_id,
237                             FunctionBlockCmd::eCA_Current );
238     fbCmd.setNodeId( m_device.getNodeId() );
239     fbCmd.setSubunitId( 0x00 );
240     fbCmd.setCommandType( AVCCommand::eCT_Control );
241     fbCmd.m_pFBSelector->m_inputFbPlugNumber=(value & 0xFF);
242
243     fbCmd.setVerbose( getDebugLevel() );
244    
245     if ( !fbCmd.fire() ) {
246         debugError( "FunctionBlockCmd failed\n" );
247         return OscResponse(OscResponse::eError);
248     }
249
250     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
251         CoutSerializer se;
252         fbCmd.serialize( se );
253     }
254
255     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
256         return OscResponse(OscResponse::eError);
257     }
258    
259     return OscResponse(m);
260 }
261
262 OscResponse
263 GenericMixer::mixerSetFeatureVolumeValue(int fb_id, int channel,
264                                         int volume) {
265     OscMessage m;
266    
267     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d channel %d to %d...\n",
268         fb_id, channel, volume);
269
270     FunctionBlockCmd fbCmd( m_p1394Service,
271                             FunctionBlockCmd::eFBT_Feature,
272                             fb_id,
273                             FunctionBlockCmd::eCA_Current );
274     fbCmd.setNodeId( m_device.getNodeId()  );
275     fbCmd.setSubunitId( 0x00 );
276     fbCmd.setCommandType( AVCCommand::eCT_Control );
277     fbCmd.m_pFBFeature->m_audioChannelNumber=channel;
278     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
279     fbCmd.m_pFBFeature->m_pVolume->m_volume=volume;
280
281     if ( !fbCmd.fire() ) {
282         debugError( "cmd failed\n" );
283     }
284
285     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
286         return OscResponse(OscResponse::eError);
287     }
288
289     return OscResponse(m);
290 }
291
292 OscResponse
293 GenericMixer::mixerGetFeatureVolumeValue(int fb_id, int channel) {
294     OscMessage m;
295    
296     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d channel %d...\n",
297         fb_id, channel);
298
299     FunctionBlockCmd fbCmd( m_p1394Service,
300                             FunctionBlockCmd::eFBT_Feature,
301                             fb_id,
302                             FunctionBlockCmd::eCA_Current );
303     fbCmd.setNodeId( m_device.getNodeId()  );
304     fbCmd.setSubunitId( 0x00 );
305     fbCmd.setCommandType( AVCCommand::eCT_Status );
306     fbCmd.m_pFBFeature->m_audioChannelNumber=channel;
307     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
308     fbCmd.m_pFBFeature->m_pVolume->m_volume=0;
309
310     if ( !fbCmd.fire() ) {
311         debugError( "cmd failed\n" );
312     }
313
314     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
315         return OscResponse(OscResponse::eError);
316     }
317    
318     m.addArgument((int32_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume));
319
320     return OscResponse(m);
321 }
322
323 } // end of namespace BeBoB
Note: See TracBrowser for help on using the browser.