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

Revision 455, 9.8 kB (checked in by ppalmers, 16 years ago)

- test-mixer volume control works (tested on phase88 only)
- volume control is exposed to the outside

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==7)) {
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                 return OscResponse(OscResponse::eError);
144
145             }
146         }
147     }
148     debugWarning("Unhandled OSC message!\n");
149     // default action: don't change response
150     return OscResponse(OscResponse::eUnhandled);
151 }
152
153 OscMessage
154 GenericMixer::mixerListChildren() {
155     OscMessage m;
156
157     debugOutput(DEBUG_LEVEL_NORMAL,"Listing mixer elements...\n");
158
159     assert(m_device.getAudioSubunit(0)); // FIXME!!
160     FunctionBlockVector functions=m_device.getAudioSubunit(0)->getFunctionBlocks();
161
162     for ( FunctionBlockVector::iterator it = functions.begin();
163           it != functions.end();
164           ++it )
165     {
166         std::ostringstream ostrm;
167         ostrm << (*it)->getName() << "/" << (int)((*it)->getId());
168         m.addArgument(ostrm.str());
169     }
170
171     m.print();
172     return m;
173 }
174
175 OscResponse
176 GenericMixer::mixerGetSelectorValue(int fb_id) {
177     OscMessage m;
178    
179     debugOutput(DEBUG_LEVEL_NORMAL,"Get selector %d value...\n",
180         fb_id);
181
182     FunctionBlockCmd fbCmd( m_p1394Service,
183                             FunctionBlockCmd::eFBT_Selector,
184                             fb_id,
185                             FunctionBlockCmd::eCA_Current );
186     fbCmd.setNodeId( m_device.getNodeId() );
187     fbCmd.setSubunitId( 0x00 );
188     fbCmd.setCommandType( AVCCommand::eCT_Status );
189     fbCmd.m_pFBSelector->m_inputFbPlugNumber=0xFF;
190
191     fbCmd.setVerbose( getDebugLevel() );
192    
193     if ( !fbCmd.fire() ) {
194         debugError( "FunctionBlockCmd failed\n" );
195         return OscResponse(OscResponse::eError);
196     }
197
198     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
199         CoutSerializer se;
200         fbCmd.serialize( se );
201     }
202    
203     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
204         return OscResponse(OscResponse::eError);
205     }
206    
207     m.addArgument((int32_t)(fbCmd.m_pFBSelector->m_inputFbPlugNumber));
208
209     return OscResponse(m);
210 }
211
212 OscResponse
213 GenericMixer::mixerSetSelectorValue(int fb_id, int value) {
214     OscMessage m;
215    
216     debugOutput(DEBUG_LEVEL_NORMAL,"Set selector %d to %d...\n",
217         fb_id, value);
218
219     FunctionBlockCmd fbCmd( m_p1394Service,
220                             FunctionBlockCmd::eFBT_Selector,
221                             fb_id,
222                             FunctionBlockCmd::eCA_Current );
223     fbCmd.setNodeId( m_device.getNodeId() );
224     fbCmd.setSubunitId( 0x00 );
225     fbCmd.setCommandType( AVCCommand::eCT_Control );
226     fbCmd.m_pFBSelector->m_inputFbPlugNumber=(value & 0xFF);
227
228     fbCmd.setVerbose( getDebugLevel() );
229    
230     if ( !fbCmd.fire() ) {
231         debugError( "FunctionBlockCmd failed\n" );
232         return OscResponse(OscResponse::eError);
233     }
234
235     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
236         CoutSerializer se;
237         fbCmd.serialize( se );
238     }
239
240     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
241         return OscResponse(OscResponse::eError);
242     }
243    
244     return OscResponse(m);
245 }
246
247 OscResponse
248 GenericMixer::mixerSetFeatureVolumeValue(int fb_id, int channel,
249                                         int volume) {
250     OscMessage m;
251    
252     debugOutput(DEBUG_LEVEL_NORMAL,"Set feature volume %d channel %d to %d...\n",
253         fb_id, channel, volume);
254
255     FunctionBlockCmd fbCmd( m_p1394Service,
256                             FunctionBlockCmd::eFBT_Feature,
257                             fb_id,
258                             FunctionBlockCmd::eCA_Current );
259     fbCmd.setNodeId( m_device.getNodeId()  );
260     fbCmd.setSubunitId( 0x00 );
261     fbCmd.setCommandType( AVCCommand::eCT_Control );
262     fbCmd.m_pFBFeature->m_audioChannelNumber=channel;
263     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
264     fbCmd.m_pFBFeature->m_pVolume->m_volume=volume;
265
266     if ( !fbCmd.fire() ) {
267         debugError( "cmd failed\n" );
268     }
269
270     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
271         return OscResponse(OscResponse::eError);
272     }
273
274     return OscResponse(m);
275 }
276
277 OscResponse
278 GenericMixer::mixerGetFeatureVolumeValue(int fb_id, int channel) {
279     OscMessage m;
280    
281     debugOutput(DEBUG_LEVEL_NORMAL,"Get feature volume %d channel %d...\n",
282         fb_id, channel);
283
284     FunctionBlockCmd fbCmd( m_p1394Service,
285                             FunctionBlockCmd::eFBT_Feature,
286                             fb_id,
287                             FunctionBlockCmd::eCA_Current );
288     fbCmd.setNodeId( m_device.getNodeId()  );
289     fbCmd.setSubunitId( 0x00 );
290     fbCmd.setCommandType( AVCCommand::eCT_Status );
291     fbCmd.m_pFBFeature->m_audioChannelNumber=channel;
292     fbCmd.m_pFBFeature->m_controlSelector=FunctionBlockFeature::eCSE_Feature_Volume;
293     fbCmd.m_pFBFeature->m_pVolume->m_volume=0;
294
295     if ( !fbCmd.fire() ) {
296         debugError( "cmd failed\n" );
297     }
298
299     if (fbCmd.getResponse() != AVCCommand::eR_Accepted) {
300         return OscResponse(OscResponse::eError);
301     }
302    
303     m.addArgument((int32_t)(fbCmd.m_pFBFeature->m_pVolume->m_volume));
304
305     return OscResponse(m);
306 }
307
308 } // end of namespace BeBoB
Note: See TracBrowser for help on using the browser.