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

Revision 1110, 14.4 kB (checked in by wagi, 16 years ago)

Lot's of small and big bug fixes allong the caching path.
There were several parts not correctly deserialized.

This should fix ticket #65

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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     if ( !deser.isExisting( basePath + "m_type" ) ) {
191         return 0;
192     }
193
194     result  = deser.read( basePath + "m_type", type );
195     result &= deser.read( basePath + "m_subtype", subtype );
196     if ( !result ) {
197         return 0;
198     }
199
200     switch ( type ) {
201     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector:
202         pFB = new FunctionBlockSelector;
203         break;
204     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature:
205         pFB = new FunctionBlockFeature;
206         break;
207     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing:
208         if ( subtype == ExtendedSubunitInfoCmd::ePT_EnhancedMixer ) {
209             pFB = new FunctionBlockEnhancedMixer;
210         } else {
211             pFB = new FunctionBlockProcessing;
212         }
213         break;
214     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec:
215         pFB = new FunctionBlockCodec;
216         break;
217     default:
218         pFB = 0;
219     }
220
221     if ( !pFB ) {
222         return 0;
223     }
224
225     pFB->m_subunit = &subunit;
226     pFB->m_type = type;
227     pFB->m_subtype = subtype;
228
229     result &= deser.read( basePath + "m_id", pFB->m_id );
230     result &= deser.read( basePath + "m_purpose", pFB->m_purpose );
231     result &= deser.read( basePath + "m_nrOfInputPlugs", pFB->m_nrOfInputPlugs );
232     result &= deser.read( basePath + "m_nrOfOutputPlugs", pFB->m_nrOfOutputPlugs );
233
234     if ( !result ) {
235         delete pFB;
236         return 0;
237     }
238
239     return pFB;
240 }
241
242 bool
243 FunctionBlock::deserializeUpdate( Glib::ustring basePath,
244                                   Util::IODeserialize& deser )
245 {
246     bool result;
247
248     result = deserializePlugVector( basePath + "m_plugs", deser,
249                                     m_subunit->getUnit().getPlugManager(), m_plugs );
250     return result;
251 }
252
253 ///////////////////////
254
255 FunctionBlockSelector::FunctionBlockSelector(
256     AVC::Subunit& subunit,
257     function_block_id_t id,
258     ESpecialPurpose purpose,
259     no_of_input_plugs_t nrOfInputPlugs,
260     no_of_output_plugs_t nrOfOutputPlugs,
261     int verbose )
262     : FunctionBlock( subunit,
263                      eFBT_AudioSubunitSelector,
264                      0,
265                      id,
266                      purpose,
267                      nrOfInputPlugs,
268                      nrOfOutputPlugs,
269                      verbose )
270 {
271 }
272
273 FunctionBlockSelector::FunctionBlockSelector(
274     const FunctionBlockSelector& rhs )
275     : FunctionBlock( rhs )
276 {
277 }
278
279 FunctionBlockSelector::FunctionBlockSelector()
280     : FunctionBlock()
281 {
282 }
283
284 FunctionBlockSelector::~FunctionBlockSelector()
285 {
286 }
287
288 const char*
289 FunctionBlockSelector::getName()
290 {
291     return "Selector";
292 }
293
294 bool
295 FunctionBlockSelector::serializeChild( Glib::ustring basePath,
296                                        Util::IOSerialize& ser ) const
297 {
298     return true;
299 }
300
301 bool
302 FunctionBlockSelector::deserializeChild( Glib::ustring basePath,
303                                          Util::IODeserialize& deser,
304                                          AvDevice& unit )
305 {
306     return true;
307 }
308
309 ///////////////////////
310
311 FunctionBlockFeature::FunctionBlockFeature(
312     AVC::Subunit& subunit,
313     function_block_id_t id,
314     ESpecialPurpose purpose,
315     no_of_input_plugs_t nrOfInputPlugs,
316     no_of_output_plugs_t nrOfOutputPlugs,
317     int verbose )
318     : FunctionBlock( subunit,
319                      eFBT_AudioSubunitFeature,
320                      0,
321                      id,
322                      purpose,
323                      nrOfInputPlugs,
324                      nrOfOutputPlugs,
325                      verbose )
326 {
327 }
328
329 FunctionBlockFeature::FunctionBlockFeature(
330     const FunctionBlockFeature& rhs )
331     : FunctionBlock( rhs )
332 {
333 }
334
335 FunctionBlockFeature::FunctionBlockFeature()
336     : FunctionBlock()
337 {
338 }
339
340 FunctionBlockFeature::~FunctionBlockFeature()
341 {
342 }
343
344 const char*
345 FunctionBlockFeature::getName()
346 {
347     return "Feature";
348 }
349
350 bool
351 FunctionBlockFeature::serializeChild( Glib::ustring basePath,
352                                       Util::IOSerialize& ser ) const
353 {
354     return true;
355 }
356
357 bool
358 FunctionBlockFeature::deserializeChild( Glib::ustring basePath,
359                                         Util::IODeserialize& deser,
360                                         AvDevice& unit )
361 {
362     return true;
363 }
364
365 ///////////////////////
366
367 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer(
368     AVC::Subunit& subunit,
369     function_block_id_t id,
370     ESpecialPurpose purpose,
371     no_of_input_plugs_t nrOfInputPlugs,
372     no_of_output_plugs_t nrOfOutputPlugs,
373     int verbose )
374     : FunctionBlock( subunit,
375                      eFBT_AudioSubunitProcessing,
376                      ExtendedSubunitInfoCmd::ePT_EnhancedMixer,
377                      id,
378                      purpose,
379                      nrOfInputPlugs,
380                      nrOfOutputPlugs,
381                      verbose )
382 {
383 }
384
385 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer(
386     const FunctionBlockEnhancedMixer& rhs )
387     : FunctionBlock( rhs )
388 {
389 }
390
391 FunctionBlockEnhancedMixer::FunctionBlockEnhancedMixer()
392     : FunctionBlock()
393 {
394 }
395
396 FunctionBlockEnhancedMixer::~FunctionBlockEnhancedMixer()
397 {
398 }
399
400 bool
401 FunctionBlockEnhancedMixer::discover()
402 {
403     if (!FunctionBlock::discover())
404         return false;
405
406     /*
407      * Disable discovering of enhanced mixer because all
408      * device out there do not use, and all implementations
409      * are buggy. So there is no point to use it.
410      * All 'mixer' functions are implemented with selector function blocks
411
412     AVC::FunctionBlockCmd fbCmd( m_subunit->getUnit().get1394Service(),
413                                  FunctionBlockCmd::eFBT_Processing,
414                                  m_id,
415                                  FunctionBlockCmd::eCA_Current);
416     fbCmd.setNodeId( m_subunit->getUnit().getConfigRom().getNodeId() );
417     fbCmd.setSubunitId( 0x00 );
418     fbCmd.setCommandType( AVCCommand::eCT_Status );
419     // fbCmd.setVerboseLevel( DEBUG_LEVEL_VERY_VERBOSE );
420
421     // Ok, this enhanced  mixer setting here is just a hack, we need
422     // a sane way to set processing features (read pointer management)
423     AVC::FunctionBlockProcessingEnhancedMixer em;
424     delete fbCmd.m_pFBProcessing->m_pMixer;
425     fbCmd.m_pFBProcessing->m_pMixer = 0;
426     fbCmd.m_pFBProcessing->m_pEnhancedMixer = em.clone();
427    
428     if ( !fbCmd.fire() ) {
429         debugError( "cmd failed\n" );
430         return false;
431     }
432    
433     //     if ( getDebugLevel() >= DEBUG_LEVEL_NORMAL ) {
434     //         Util::Cmd::CoutSerializer se;
435     //         fbCmd.serialize( se );
436     //     }
437
438     if((fbCmd.getResponse() != AVCCommand::eR_Implemented)) {
439         debugWarning("fbCmd.getResponse() != AVCCommand::eR_Implemented\n");
440     }
441     */
442    
443     return true;
444 }
445
446
447 const char*
448 FunctionBlockEnhancedMixer::getName()
449 {
450     return "EnhancedMixer";
451 }
452
453 bool
454 FunctionBlockEnhancedMixer::serializeChild( Glib::ustring basePath,
455                                             Util::IOSerialize& ser ) const
456 {
457     return true;
458 }
459
460 bool
461 FunctionBlockEnhancedMixer::deserializeChild( Glib::ustring basePath,
462                                               Util::IODeserialize& deser,
463                                               AvDevice& unit )
464 {
465     return true;
466 }
467
468 ///////////////////////
469
470 FunctionBlockProcessing::FunctionBlockProcessing(
471     AVC::Subunit& subunit,
472     function_block_id_t id,
473     ESpecialPurpose purpose,
474     no_of_input_plugs_t nrOfInputPlugs,
475     no_of_output_plugs_t nrOfOutputPlugs,
476     int verbose )
477     : FunctionBlock( subunit,
478                      eFBT_AudioSubunitProcessing,
479                      0,
480                      id,
481                      purpose,
482                      nrOfInputPlugs,
483                      nrOfOutputPlugs,
484                      verbose )
485 {
486 }
487
488 FunctionBlockProcessing::FunctionBlockProcessing(
489     const FunctionBlockProcessing& rhs )
490     : FunctionBlock( rhs )
491 {
492 }
493
494 FunctionBlockProcessing::FunctionBlockProcessing()
495     : FunctionBlock()
496 {
497 }
498
499 FunctionBlockProcessing::~FunctionBlockProcessing()
500 {
501 }
502
503 const char*
504 FunctionBlockProcessing::getName()
505 {
506     return "Dummy Processing";
507 }
508
509 bool
510 FunctionBlockProcessing::serializeChild( Glib::ustring basePath,
511                                          Util::IOSerialize& ser ) const
512 {
513     return true;
514 }
515
516 bool
517 FunctionBlockProcessing::deserializeChild( Glib::ustring basePath,
518                                            Util::IODeserialize& deser,
519                                            AvDevice& unit )
520 {
521     return true;
522 }
523
524 ///////////////////////
525
526 FunctionBlockCodec::FunctionBlockCodec(
527     AVC::Subunit& subunit,
528     function_block_id_t id,
529     ESpecialPurpose purpose,
530     no_of_input_plugs_t nrOfInputPlugs,
531     no_of_output_plugs_t nrOfOutputPlugs,
532     int verbose )
533     : FunctionBlock( subunit,
534                      eFBT_AudioSubunitCodec,
535                      0,
536                      id,
537                      purpose,
538                      nrOfInputPlugs,
539                      nrOfOutputPlugs,
540                      verbose )
541 {
542 }
543
544 FunctionBlockCodec::FunctionBlockCodec( const FunctionBlockCodec& rhs )
545     : FunctionBlock( rhs )
546 {
547 }
548
549 FunctionBlockCodec::FunctionBlockCodec()
550     : FunctionBlock()
551 {
552 }
553
554 FunctionBlockCodec::~FunctionBlockCodec()
555 {
556 }
557
558 const char*
559 FunctionBlockCodec::getName()
560 {
561     return "Dummy Codec";
562 }
563
564 bool
565 FunctionBlockCodec::serializeChild( Glib::ustring basePath,
566                                     Util::IOSerialize& ser ) const
567 {
568     return true;
569 }
570
571 bool
572 FunctionBlockCodec::deserializeChild( Glib::ustring basePath,
573                                       Util::IODeserialize& deser,
574                                       AvDevice& unit )
575 {
576     return true;
577 }
578
579 }
Note: See TracBrowser for help on using the browser.