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

Revision 844, 14.1 kB (checked in by wagi, 15 years ago)

FunctionBlockEnhancedMixer::discover:
Disable discovering of enhanced mixer because all
device out there do not use, and all implementations
are buggy. So there is no point to use it.
All 'mixer' functions are implemented with selector function blocks

Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
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_functionblock.h"
25 #include "bebob/bebob_avdevice_subunit.h"
26 #include "bebob/bebob_avdevice.h"
27 #include "libieee1394/configrom.h"
28
29 #include "libutil/cmd_serialize.h"
30
31 using namespace AVC;
32
33 namespace BeBoB {
34
35 IMPL_DEBUG_MODULE( FunctionBlock, FunctionBlock, DEBUG_LEVEL_NORMAL );
36
37 FunctionBlock::FunctionBlock(
38     AVC::Subunit& subunit,
39     function_block_type_t type,
40     function_block_type_t subtype,
41     function_block_id_t id,
42     ESpecialPurpose purpose,
43     no_of_input_plugs_t nrOfInputPlugs,
44     no_of_output_plugs_t nrOfOutputPlugs,
45     int verbose )
46     : m_subunit( &subunit )
47     , m_type( type )
48     , m_subtype( subtype )
49     , m_id( id )
50     , m_purpose( purpose )
51     , m_nrOfInputPlugs( nrOfInputPlugs )
52     , m_nrOfOutputPlugs( nrOfOutputPlugs )
53     , m_verbose( verbose )
54 {
55     setDebugLevel( verbose );
56 }
57
58 FunctionBlock::FunctionBlock( const FunctionBlock& rhs )
59     : m_subunit( rhs.m_subunit )
60     , m_type( rhs.m_type )
61     , m_subtype( rhs.m_subtype )
62     , m_id( rhs.m_id )
63     , m_purpose( rhs.m_purpose )
64     , m_nrOfInputPlugs( rhs.m_nrOfInputPlugs )
65     , m_nrOfOutputPlugs( rhs.m_nrOfOutputPlugs )
66     , m_verbose( rhs.m_verbose )
67 {
68 }
69
70 FunctionBlock::FunctionBlock()
71 {
72 }
73
74 FunctionBlock::~FunctionBlock()
75 {
76     for ( PlugVector::iterator it = m_plugs.begin();
77           it != m_plugs.end();
78           ++it )
79     {
80         delete *it;
81     }
82
83 }
84
85 bool
86 FunctionBlock::discover()
87 {
88     debugOutput( DEBUG_LEVEL_NORMAL,
89                  "discover function block %s (nr of input plugs = %d, "
90                  "nr of output plugs = %d)\n",
91                  getName(),
92                  m_nrOfInputPlugs,
93                  m_nrOfOutputPlugs );
94
95     if ( !discoverPlugs( AVC::Plug::eAPD_Input, m_nrOfInputPlugs ) ) {
96         debugError( "Could not discover input plug for '%s'\n",
97                     getName() );
98         return false;
99     }
100
101     if ( !discoverPlugs( AVC::Plug::eAPD_Output, m_nrOfOutputPlugs ) ) {
102         debugError( "Could not discover output plugs for '%s'\n",
103                     getName() );
104         return false;
105     }
106
107     return true;
108 }
109
110 bool
111 FunctionBlock::discoverPlugs( AVC::Plug::EPlugDirection plugDirection,
112                               plug_id_t plugMaxId )
113 {
114     for ( int plugId = 0; plugId < plugMaxId; ++plugId ) {
115         AVC::Plug* plug = new BeBoB::Plug(
116             &m_subunit->getUnit(),
117             m_subunit,
118             m_type,
119             m_id,
120             AVC::Plug::eAPA_FunctionBlockPlug,
121             plugDirection,
122             plugId);
123
124         if ( !plug || !plug->discover() ) {
125             debugError( "plug discovering failed for plug %d\n",
126                         plugId );
127             delete plug;
128             return false;
129         }
130
131         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
132                      plug->getName() );
133         m_plugs.push_back( plug );
134     }
135
136     return true;
137 }
138
139 bool
140 FunctionBlock::discoverConnections()
141 {
142     debugOutput( DEBUG_LEVEL_VERBOSE,
143                  "discover connections function block %s\n",
144                  getName() );
145
146     for ( PlugVector::iterator it = m_plugs.begin();
147           it != m_plugs.end();
148           ++it )
149     {
150         BeBoB::Plug* plug = dynamic_cast<BeBoB::Plug*>(*it);
151         if(!plug) {
152             debugError("BUG: not a bebob plug\n");
153             return false;
154         }
155         if ( !plug->discoverConnections() ) {
156             debugError( "Could not discover plug connections\n" );
157             return false;
158         }
159     }
160     return true;
161 }
162
163 bool
164 FunctionBlock::serialize( Glib::ustring basePath, Util::IOSerialize& ser ) const
165 {
166     bool result;
167
168     result  = ser.write( basePath + "m_type", m_type );
169     result &= ser.write( basePath + "m_subtype", m_subtype );
170     result &= ser.write( basePath + "m_id", m_id );
171     result &= ser.write( basePath + "m_purpose", m_purpose );
172     result &= ser.write( basePath + "m_nrOfInputPlugs", m_nrOfInputPlugs );
173     result &= ser.write( basePath + "m_nrOfOutputPlugs", m_nrOfOutputPlugs );
174     result &= serializePlugVector( basePath + "m_plugs", ser, m_plugs );
175
176     return result;
177 }
178
179 FunctionBlock*
180 FunctionBlock::deserialize( Glib::ustring basePath,
181                             Util::IODeserialize& deser,
182                             AVC::Unit& unit,
183                             AVC::Subunit& subunit )
184 {
185     bool result;
186     function_block_type_t type;
187     function_block_type_t subtype;
188     FunctionBlock* pFB = 0;
189
190     result  = deser.read( basePath + "m_type", type );
191     result &= deser.read( basePath + "m_subtype", subtype );
192     if ( !result ) {
193         return 0;
194     }
195
196     switch ( type ) {
197     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector:
198         pFB = new FunctionBlockSelector;
199         break;
200     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature:
201         pFB = new FunctionBlockFeature;
202         break;
203     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing:
204         if ( subtype == ExtendedSubunitInfoCmd::ePT_EnhancedMixer ) {
205             pFB = new FunctionBlockEnhancedMixer;
206         } else {
207             pFB = new FunctionBlockProcessing;
208         }
209         break;
210     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec:
211         pFB = new FunctionBlockCodec;
212         break;
213     default:
214         pFB = 0;
215     }
216
217     if ( !pFB ) {
218         return 0;
219     }
220
221     pFB->m_subunit = &subunit;
222     pFB->m_type = type;
223     pFB->m_subtype = subtype;
224
225     result &= deser.read( basePath + "m_id", pFB->m_id );
226     result &= deser.read( basePath + "m_purpose", pFB->m_purpose );
227     result &= deser.read( basePath + "m_nrOfInputPlugs", pFB->m_nrOfInputPlugs );
228     result &= deser.read( basePath + "m_nrOfOutputPlugs", pFB->m_nrOfOutputPlugs );
229     result &= deserializePlugVector( basePath + "m_plugs", deser,
230                                      unit.getPlugManager(), pFB->m_plugs );
231
232     return 0;
233 }
234
235 ///////////////////////
236
237 FunctionBlockSelector::FunctionBlockSelector(
238     AVC::Subunit& subunit,
239     function_block_id_t id,
240     ESpecialPurpose purpose,
241     no_of_input_plugs_t nrOfInputPlugs,
242     no_of_output_plugs_t nrOfOutputPlugs,
243     int verbose )
244     : FunctionBlock( subunit,
245                      eFBT_AudioSubunitSelector,
246                      0,
247                      id,
248                      purpose,
249                      nrOfInputPlugs,
250                      nrOfOutputPlugs,
251                      verbose )
252 {
253 }
254
255 FunctionBlockSelector::FunctionBlockSelector(
256     const FunctionBlockSelector& rhs )
257     : FunctionBlock( rhs )
258 {
259 }
260
261 FunctionBlockSelector::FunctionBlockSelector()
262     : FunctionBlock()
263 {
264 }
265
266 FunctionBlockSelector::~FunctionBlockSelector()
267 {
268 }
269
270 const char*
271 FunctionBlockSelector::getName()
272 {
273     return "Selector";
274 }
275
276 bool
277 FunctionBlockSelector::serializeChild( Glib::ustring basePath,
278                                        Util::IOSerialize& ser ) const
279 {
280     return true;
281 }
282
283 bool
284 FunctionBlockSelector::deserializeChild( Glib::ustring basePath,
285                                          Util::IODeserialize& deser,
286                                          AvDevice& unit )
287 {
288     return true;
289 }
290
291 ///////////////////////
292
293 FunctionBlockFeature::FunctionBlockFeature(
294     AVC::Subunit& subunit,
295     function_block_id_t id,
296     ESpecialPurpose purpose,
297     no_of_input_plugs_t nrOfInputPlugs,
298     no_of_output_plugs_t nrOfOutputPlugs,
299     int verbose )
300     : FunctionBlock( subunit,
301                      eFBT_AudioSubunitFeature,
302                      0,
303                      id,
304                      purpose,
305                      nrOfInputPlugs,
306                      nrOfOutputPlugs,
307                      verbose )
308 {
309 }
310
311 FunctionBlockFeature::FunctionBlockFeature(
312     const FunctionBlockFeature& rhs )
313     : FunctionBlock( rhs )
314 {
315 }
316
317 FunctionBlockFeature::FunctionBlockFeature()
318     : FunctionBlock()
319 {
320 }
321
322 FunctionBlockFeature::~FunctionBlockFeature()
323 {
324 }
325
326 const char*
327 FunctionBlockFeature::getName()
328 {
329     return "Feature";
330 }
331
332 bool
333 FunctionBlockFeature::serializeChild( Glib::ustring basePath,
334                                       Util::IOSerialize& ser ) const
335 {
336     return true;
337 }
338
339 bool
340 FunctionBlockFeature::deserializeChild( Glib::ustring basePath,
341                                         Util::IODeserialize& deser,
342                                         AvDevice& unit )
343 {
344     return true;
345 }
346
347 ///////////////////////
348
349 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer(
350     AVC::Subunit& subunit,
351     function_block_id_t id,
352     ESpecialPurpose purpose,
353     no_of_input_plugs_t nrOfInputPlugs,
354     no_of_output_plugs_t nrOfOutputPlugs,
355     int verbose )
356     : FunctionBlock( subunit,
357                      eFBT_AudioSubunitProcessing,
358                      ExtendedSubunitInfoCmd::ePT_EnhancedMixer,
359                      id,
360                      purpose,
361                      nrOfInputPlugs,
362                      nrOfOutputPlugs,
363                      verbose )
364 {
365 }
366
367 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer(
368     const FunctionBlockEnhancedMixer& rhs )
369     : FunctionBlock( rhs )
370 {
371 }
372
373 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer()
374     : FunctionBlock()
375 {
376 }
377
378 FunctionBlockEnhancedMixer::~FunctionBlockEnhancedMixer()
379 {
380 }
381
382 bool
383 FunctionBlockEnhancedMixer::discover()
384 {
385     if (!FunctionBlock::discover())
386         return false;
387
388     /*
389      * Disable discovering of enhanced mixer because all
390      * device out there do not use, and all implementations
391      * are buggy. So there is no point to use it.
392      * All 'mixer' functions are implemented with selector function blocks
393
394     AVC::FunctionBlockCmd fbCmd( m_subunit->getUnit().get1394Service(),
395                                  FunctionBlockCmd::eFBT_Processing,
396                                  m_id,
397                                  FunctionBlockCmd::eCA_Current);
398     fbCmd.setNodeId( m_subunit->getUnit().getConfigRom().getNodeId() );
399     fbCmd.setSubunitId( 0x00 );
400     fbCmd.setCommandType( AVCCommand::eCT_Status );
401     // fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
402
403     // Ok, this enhanced  mixer setting here is just a hack, we need
404     // a sane way to set processing features (read pointer management)
405     AVC::FunctionBlockProcessingEnhancedMixer em;
406     delete fbCmd.m_pFBProcessing->m_pMixer;
407     fbCmd.m_pFBProcessing->m_pMixer = 0;
408     fbCmd.m_pFBProcessing->m_pEnhancedMixer = em.clone();
409    
410     if ( !fbCmd.fire() ) {
411         debugError( "cmd failed\n" );
412         return false;
413     }
414    
415     //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
416     //         Util::Cmd::CoutSerializer se;
417     //         fbCmd.serialize( se );
418     //     }
419
420     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
421         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
422     }
423     */
424    
425     return true;
426 }
427
428
429 const char*
430 FunctionBlockEnhancedMixer::getName()
431 {
432     return "EnhancedMixer";
433 }
434
435 bool
436 FunctionBlockEnhancedMixer::serializeChild( Glib::ustring basePath,
437                                             Util::IOSerialize& ser ) const
438 {
439     return true;
440 }
441
442 bool
443 FunctionBlockEnhancedMixer::deserializeChild( Glib::ustring basePath,
444                                               Util::IODeserialize& deser,
445                                               AvDevice& unit )
446 {
447     return true;
448 }
449
450 ///////////////////////
451
452 FunctionBlockProcessing::FunctionBlockProcessing(
453     AVC::Subunit& subunit,
454     function_block_id_t id,
455     ESpecialPurpose purpose,
456     no_of_input_plugs_t nrOfInputPlugs,
457     no_of_output_plugs_t nrOfOutputPlugs,
458     int verbose )
459     : FunctionBlock( subunit,
460                      eFBT_AudioSubunitProcessing,
461                      0,
462                      id,
463                      purpose,
464                      nrOfInputPlugs,
465                      nrOfOutputPlugs,
466                      verbose )
467 {
468 }
469
470 FunctionBlockProcessing::FunctionBlockProcessing(
471     const FunctionBlockProcessing& rhs )
472     : FunctionBlock( rhs )
473 {
474 }
475
476 FunctionBlockProcessing::FunctionBlockProcessing()
477     : FunctionBlock()
478 {
479 }
480
481 FunctionBlockProcessing::~FunctionBlockProcessing()
482 {
483 }
484
485 const char*
486 FunctionBlockProcessing::getName()
487 {
488     return "Dummy Processing";
489 }
490
491 bool
492 FunctionBlockProcessing::serializeChild( Glib::ustring basePath,
493                                          Util::IOSerialize& ser ) const
494 {
495     return true;
496 }
497
498 bool
499 FunctionBlockProcessing::deserializeChild( Glib::ustring basePath,
500                                            Util::IODeserialize& deser,
501                                            AvDevice& unit )
502 {
503     return true;
504 }
505
506 ///////////////////////
507
508 FunctionBlockCodec::FunctionBlockCodec(
509     AVC::Subunit& subunit,
510     function_block_id_t id,
511     ESpecialPurpose purpose,
512     no_of_input_plugs_t nrOfInputPlugs,
513     no_of_output_plugs_t nrOfOutputPlugs,
514     int verbose )
515     : FunctionBlock( subunit,
516                      eFBT_AudioSubunitCodec,
517                      0,
518                      id,
519                      purpose,
520                      nrOfInputPlugs,
521                      nrOfOutputPlugs,
522                      verbose )
523 {
524 }
525
526 FunctionBlockCodec::FunctionBlockCodec( const FunctionBlockCodec& rhs )
527     : FunctionBlock( rhs )
528 {
529 }
530
531 FunctionBlockCodec::FunctionBlockCodec()
532     : FunctionBlock()
533 {
534 }
535
536 FunctionBlockCodec::~FunctionBlockCodec()
537 {
538 }
539
540 const char*
541 FunctionBlockCodec::getName()
542 {
543     return "Dummy Codec";
544 }
545
546 bool
547 FunctionBlockCodec::serializeChild( Glib::ustring basePath,
548                                     Util::IOSerialize& ser ) const
549 {
550     return true;
551 }
552
553 bool
554 FunctionBlockCodec::deserializeChild( Glib::ustring basePath,
555                                       Util::IODeserialize& deser,
556                                       AvDevice& unit )
557 {
558     return true;
559 }
560
561 }
Note: See TracBrowser for help on using the browser.