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

Revision 554, 14.0 kB (checked in by ppalmers, 15 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

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