root/branches/echoaudio/src/bebob/bebob_avdevice_subunit.cpp

Revision 503, 17.8 kB (checked in by ppalmers, 14 years ago)

- put all libavc stuff into it's own name namespace (AVC)

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 "bebob/bebob_avplug.h"
28 #include "libieee1394/configrom.h"
29
30 #include "libavc/general/avc_plug_info.h"
31 #include "libavc/streamformat/avc_extended_stream_format.h"
32 #include "libavc/util/avc_serialize.h"
33
34 #include <sstream>
35
36 using namespace AVC;
37
38 IMPL_DEBUG_MODULE( BeBoB::AvDeviceSubunit, BeBoB::AvDeviceSubunit, DEBUG_LEVEL_VERBOSE );
39
40 ////////////////////////////////////////////
41
42 BeBoB::AvDeviceSubunit::AvDeviceSubunit( AvDevice& avDevice,
43                                          ESubunitType type,
44                                          subunit_t id,
45                                          int verboseLevel )
46     : m_avDevice( &avDevice )
47     , m_sbType( type )
48     , m_sbId( id )
49     , m_verboseLevel( verboseLevel )
50 {
51     setDebugLevel( m_verboseLevel );
52 }
53
54 BeBoB::AvDeviceSubunit::AvDeviceSubunit()
55 {
56 }
57
58 BeBoB::AvDeviceSubunit::~AvDeviceSubunit()
59 {
60     for ( AvPlugVector::iterator it = m_plugs.begin();
61           it != m_plugs.end();
62           ++it )
63     {
64         delete *it;
65     }
66 }
67
68 bool
69 BeBoB::AvDeviceSubunit::discover()
70 {
71     if ( !discoverPlugs() ) {
72         debugError( "plug discovering failed\n" );
73         return false;
74     }
75
76     return true;
77 }
78
79 bool
80 BeBoB::AvDeviceSubunit::discoverPlugs()
81 {
82     PlugInfoCmd plugInfoCmd( m_avDevice->get1394Service(),
83                              PlugInfoCmd::eSF_SerialBusIsochronousAndExternalPlug );
84     plugInfoCmd.setNodeId( m_avDevice->getConfigRom().getNodeId() );
85     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
86     plugInfoCmd.setSubunitType( m_sbType );
87     plugInfoCmd.setSubunitId( m_sbId );
88     plugInfoCmd.setVerbose( m_verboseLevel );
89
90     if ( !plugInfoCmd.fire() ) {
91         debugError( "plug info command failed\n" );
92         return false;
93     }
94
95     debugOutput( DEBUG_LEVEL_NORMAL, "number of source plugs = %d\n",
96                  plugInfoCmd.m_sourcePlugs );
97     debugOutput( DEBUG_LEVEL_NORMAL, "number of destination output "
98                  "plugs = %d\n", plugInfoCmd.m_destinationPlugs );
99
100     if ( !discoverPlugs( AvPlug::eAPD_Input,
101                          plugInfoCmd.m_destinationPlugs ) )
102     {
103         debugError( "destination plug discovering failed\n" );
104         return false;
105     }
106
107     if ( !discoverPlugs(  AvPlug::eAPD_Output,
108                           plugInfoCmd.m_sourcePlugs ) )
109     {
110         debugError( "source plug discovering failed\n" );
111         return false;
112     }
113
114     return true;
115 }
116
117 bool
118 BeBoB::AvDeviceSubunit::discoverConnections()
119 {
120     for ( AvPlugVector::iterator it = m_plugs.begin();
121           it != m_plugs.end();
122           ++it )
123     {
124         AvPlug* plug = *it;
125         if ( !plug->discoverConnections() ) {
126             debugError( "plug connection discovering failed ('%s')\n",
127                         plug->getName() );
128             return false;
129         }
130     }
131
132     return true;
133 }
134
135 bool
136 BeBoB::AvDeviceSubunit::discoverPlugs(AvPlug::EAvPlugDirection plugDirection,
137                                       plug_id_t plugMaxId )
138 {
139     for ( int plugIdx = 0;
140           plugIdx < plugMaxId;
141           ++plugIdx )
142     {
143         ESubunitType subunitType =
144             static_cast<ESubunitType>( getSubunitType() );
145         AvPlug* plug = new AvPlug( m_avDevice->get1394Service(),
146                                    m_avDevice->getConfigRom(),
147                                    m_avDevice->getPlugManager(),
148                                    subunitType,
149                                    getSubunitId(),
150                                    0xff,
151                                    0xff,
152                                    AvPlug::eAPA_SubunitPlug,
153                                    plugDirection,
154                                    plugIdx,
155                                    m_verboseLevel );
156         if ( !plug || !plug->discover() ) {
157             debugError( "plug discover failed\n" );
158             return false;
159         }
160
161         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
162                      plug->getName() );
163         m_plugs.push_back( plug );
164     }
165     return true;
166 }
167
168 bool
169 BeBoB::AvDeviceSubunit::addPlug( AvPlug& plug )
170 {
171     m_plugs.push_back( &plug );
172     return true;
173 }
174
175
176 BeBoB::AvPlug*
177 BeBoB::AvDeviceSubunit::getPlug(AvPlug::EAvPlugDirection direction, plug_id_t plugId)
178 {
179     for ( AvPlugVector::iterator it = m_plugs.begin();
180           it != m_plugs.end();
181           ++it )
182     {
183         AvPlug* plug = *it;
184         if ( ( plug->getPlugId() == plugId )
185             && ( plug->getDirection() == direction ) )
186         {
187             return plug;
188         }
189     }
190     return 0;
191 }
192
193
194 bool
195 BeBoB::AvDeviceSubunit::serialize( Glib::ustring basePath,
196                                    Util::IOSerialize& ser ) const
197 {
198     bool result;
199
200     result  = ser.write( basePath + "m_sbType", m_sbType );
201     result &= ser.write( basePath + "m_sbId", m_sbId );
202     result &= ser.write( basePath + "m_verboseLevel", m_verboseLevel );
203     result &= serializeChild( basePath, ser );
204
205     return result;
206 }
207
208 BeBoB::AvDeviceSubunit*
209 BeBoB::AvDeviceSubunit::deserialize( Glib::ustring basePath,
210                                      Util::IODeserialize& deser,
211                                      AvDevice& avDevice )
212 {
213     bool result;
214     ESubunitType sbType;
215     result  = deser.read( basePath + "m_sbType", sbType );
216
217     AvDeviceSubunit* pSubunit = 0;
218     switch( sbType ) {
219     case eST_Audio:
220         pSubunit = new AvDeviceSubunitAudio;
221         break;
222     case eST_Music:
223         pSubunit = new AvDeviceSubunitMusic;
224         break;
225     default:
226         pSubunit = 0;
227     }
228
229     if ( !pSubunit ) {
230         return 0;
231     }
232
233     pSubunit->m_avDevice = &avDevice;
234     pSubunit->m_sbType = sbType;
235     result &= deser.read( basePath + "m_sbId", pSubunit->m_sbId );
236     result &= deser.read( basePath + "m_verboseLevel", pSubunit->m_verboseLevel );
237     result &= pSubunit->deserializeChild( basePath, deser, avDevice );
238
239     if ( !result ) {
240         delete pSubunit;
241         return 0;
242     }
243
244     return pSubunit;
245 }
246
247 ////////////////////////////////////////////
248
249 BeBoB::AvDeviceSubunitAudio::AvDeviceSubunitAudio( AvDevice& avDevice,
250                                                    subunit_t id,
251                                                    int verboseLevel )
252     : AvDeviceSubunit( avDevice, eST_Audio, id, verboseLevel )
253 {
254 }
255
256 BeBoB::AvDeviceSubunitAudio::AvDeviceSubunitAudio()
257     : AvDeviceSubunit()
258 {
259 }
260
261 BeBoB::AvDeviceSubunitAudio::~AvDeviceSubunitAudio()
262 {
263     for ( FunctionBlockVector::iterator it = m_functions.begin();
264           it != m_functions.end();
265           ++it )
266     {
267         delete *it;
268     }
269 }
270
271 bool
272 BeBoB::AvDeviceSubunitAudio::discover()
273 {
274     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering Audio Subunit...\n");
275    
276     if ( !AvDeviceSubunit::discover() ) {
277         return false;
278     }
279
280     if ( !discoverFunctionBlocks() ) {
281         debugError( "function block discovering failed\n" );
282         return false;
283     }
284
285     return true;
286 }
287
288 bool
289 BeBoB::AvDeviceSubunitAudio::discoverConnections()
290 {
291     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering connections...\n");
292     if ( !AvDeviceSubunit::discoverConnections() ) {
293         return false;
294     }
295
296     for ( FunctionBlockVector::iterator it = m_functions.begin();
297           it != m_functions.end();
298           ++it )
299     {
300         FunctionBlock* function = *it;
301         if ( !function->discoverConnections() ) {
302             debugError( "functionblock connection discovering failed ('%s')\n",
303                         function->getName() );
304             return false;
305         }
306     }
307
308     return true;
309 }
310
311 const char*
312 BeBoB::AvDeviceSubunitAudio::getName()
313 {
314     return "AudioSubunit";
315 }
316
317 bool
318 BeBoB::AvDeviceSubunitAudio::discoverFunctionBlocks()
319 {
320     debugOutput( DEBUG_LEVEL_NORMAL,
321                  "Discovering function blocks...\n");
322
323     if ( !discoverFunctionBlocksDo(
324              ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector) )
325     {
326         debugError( "Could not discover function block selector\n" );
327         return false;
328     }
329     if ( !discoverFunctionBlocksDo(
330              ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature) )
331     {
332         debugError( "Could not discover function block feature\n" );
333         return false;
334     }
335     if ( !discoverFunctionBlocksDo(
336              ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing) )
337     {
338         debugError( "Could not discover function block processing\n" );
339         return false;
340     }
341     if ( !discoverFunctionBlocksDo(
342              ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec) )
343     {
344         debugError( "Could not discover function block codec\n" );
345         return false;
346     }
347
348     // print a function block list
349 #ifdef DEBUG
350     if (getDebugLevel() >= DEBUG_LEVEL_NORMAL) {
351    
352         for ( FunctionBlockVector::iterator it = m_functions.begin();
353             it != m_functions.end();
354             ++it )
355         {
356             debugOutput(DEBUG_LEVEL_NORMAL, "%20s FB, type 0x%X, id=%d\n",
357                 (*it)->getName(),
358                 (*it)->getType(),
359                 (*it)->getId());
360         }
361     }
362 #endif
363
364     return true;
365 }
366
367 bool
368 BeBoB::AvDeviceSubunitAudio::discoverFunctionBlocksDo(
369     ExtendedSubunitInfoCmd::EFunctionBlockType fbType )
370 {
371     int page = 0;
372     bool cmdSuccess = false;
373     bool finished = false;
374
375     do {
376         ExtendedSubunitInfoCmd
377             extSubunitInfoCmd( m_avDevice->get1394Service() );
378         extSubunitInfoCmd.setNodeId( m_avDevice->getConfigRom().getNodeId() );
379         extSubunitInfoCmd.setCommandType( AVCCommand::eCT_Status );
380         extSubunitInfoCmd.setSubunitId( getSubunitId() );
381         extSubunitInfoCmd.setSubunitType( getSubunitType() );
382         extSubunitInfoCmd.setVerbose( m_verboseLevel );
383
384         extSubunitInfoCmd.m_fbType = fbType;
385         extSubunitInfoCmd.m_page = page;
386
387         cmdSuccess = extSubunitInfoCmd.fire();
388         if ( cmdSuccess
389              && ( extSubunitInfoCmd.getResponse()
390                   == AVCCommand::eR_Implemented ) )
391         {
392             for ( ExtendedSubunitInfoPageDataVector::iterator it =
393                       extSubunitInfoCmd.m_infoPageDatas.begin();
394                   cmdSuccess
395                       && ( it != extSubunitInfoCmd.m_infoPageDatas.end() );
396                   ++it )
397             {
398                 cmdSuccess = createFunctionBlock( fbType, **it );
399             }
400             if ( ( extSubunitInfoCmd.m_infoPageDatas.size() != 0 )
401                  && ( extSubunitInfoCmd.m_infoPageDatas.size() == 5 ) )
402             {
403                 page++;
404             } else {
405                 finished = true;
406             }
407         } else {
408             finished = true;
409         }
410     } while ( cmdSuccess && !finished );
411
412     return cmdSuccess;
413 }
414
415 bool
416 BeBoB::AvDeviceSubunitAudio::createFunctionBlock(
417     ExtendedSubunitInfoCmd::EFunctionBlockType fbType,
418     ExtendedSubunitInfoPageData& data )
419 {
420     FunctionBlock::ESpecialPurpose purpose
421         = convertSpecialPurpose(  data.m_functionBlockSpecialPupose );
422
423     FunctionBlock* fb = 0;
424
425     switch ( fbType ) {
426     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector:
427     {
428         fb = new FunctionBlockSelector( *this,
429                                         data.m_functionBlockId,
430                                         purpose,
431                                         data.m_noOfInputPlugs,
432                                         data.m_noOfOutputPlugs,
433                                         m_verboseLevel );
434     }
435     break;
436     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature:
437     {
438         fb = new FunctionBlockFeature( *this,
439                                        data.m_functionBlockId,
440                                        purpose,
441                                        data.m_noOfInputPlugs,
442                                        data.m_noOfOutputPlugs,
443                                        m_verboseLevel );
444     }
445     break;
446     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing:
447     {
448         switch ( data.m_functionBlockType ) {
449         case ExtendedSubunitInfoCmd::ePT_EnhancedMixer:
450         {
451             fb = new FunctionBlockEnhancedMixer( *this,
452                                                  data.m_functionBlockId,
453                                                  purpose,
454                                                  data.m_noOfInputPlugs,
455                                                  data.m_noOfOutputPlugs,
456                                                  m_verboseLevel );
457         }
458         break;
459         case ExtendedSubunitInfoCmd::ePT_Mixer:
460         case ExtendedSubunitInfoCmd::ePT_Generic:
461         case ExtendedSubunitInfoCmd::ePT_UpDown:
462         case ExtendedSubunitInfoCmd::ePT_DolbyProLogic:
463         case ExtendedSubunitInfoCmd::ePT_3DStereoExtender:
464         case ExtendedSubunitInfoCmd::ePT_Reverberation:
465         case ExtendedSubunitInfoCmd::ePT_Chorus:
466         case ExtendedSubunitInfoCmd::ePT_DynamicRangeCompression:
467         default:
468             fb = new FunctionBlockProcessing( *this,
469                                               data.m_functionBlockId,
470                                               purpose,
471                                               data.m_noOfInputPlugs,
472                                               data.m_noOfOutputPlugs,
473                                               m_verboseLevel );
474             debugWarning( "Dummy function block processing created. "
475                           "Implementation is missing\n" );
476         }
477     }
478     break;
479     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec:
480     {
481         fb = new FunctionBlockCodec( *this,
482                                      data.m_functionBlockId,
483                                      purpose,
484                                      data.m_noOfInputPlugs,
485                                      data.m_noOfOutputPlugs,
486                                      m_verboseLevel );
487         debugWarning( "Dummy function block codec created. "
488                       "Implementation is missing\n" );
489     }
490     break;
491     default:
492         debugError( "Unhandled function block type found\n" );
493         return false;
494     }
495
496     if ( !fb ) {
497         debugError( "Could create function block\n" );
498         return false;
499     }
500     if ( !fb->discover() ) {
501         debugError( "Could not discover function block %s\n",
502                     fb->getName() );
503         delete fb;
504         return false;
505     }
506     m_functions.push_back( fb );
507
508     return true;
509 }
510
511 BeBoB::FunctionBlock::ESpecialPurpose
512 BeBoB::AvDeviceSubunitAudio::convertSpecialPurpose(
513     function_block_special_purpose_t specialPurpose )
514 {
515     FunctionBlock::ESpecialPurpose p;
516     switch ( specialPurpose ) {
517     case ExtendedSubunitInfoPageData::eSP_InputGain:
518         p  = FunctionBlock::eSP_InputGain;
519         break;
520     case ExtendedSubunitInfoPageData::eSP_OutputVolume:
521         p = FunctionBlock::eSP_OutputVolume;
522     break;
523     default:
524         p = FunctionBlock::eSP_NoSpecialPurpose;
525     }
526     return p;
527 }
528
529 bool
530 BeBoB::AvDeviceSubunitAudio::serializeChild( Glib::ustring basePath,
531                                              Util::IOSerialize& ser ) const
532 {
533     bool result = true;
534     int i = 0;
535
536     for ( FunctionBlockVector::const_iterator it = m_functions.begin();
537           it != m_functions.end();
538           ++it )
539     {
540         FunctionBlock* pFB = *it;
541         std::ostringstream strstrm;
542         strstrm << basePath << "FunctionBlock" << i << "/";
543
544         result &= pFB->serialize( strstrm.str() , ser );
545
546         i++;
547     }
548
549     return result;
550 }
551
552 bool
553 BeBoB::AvDeviceSubunitAudio::deserializeChild( Glib::ustring basePath,
554                                                Util::IODeserialize& deser,
555                                                AvDevice& avDevice )
556 {
557     int i = 0;
558     bool bFinished = false;
559     do {
560         std::ostringstream strstrm;
561         strstrm << basePath << "FunctionBlock" << i << "/";
562         FunctionBlock* pFB = FunctionBlock::deserialize( strstrm.str(),
563                                                          deser,
564                                                          avDevice,
565                                                          *this );
566         if ( pFB ) {
567             m_functions.push_back( pFB );
568             i++;
569         } else {
570             bFinished = true;
571         }
572     } while ( !bFinished );
573
574     return true;
575 }
576
577 ////////////////////////////////////////////
578
579 BeBoB::AvDeviceSubunitMusic::AvDeviceSubunitMusic( AvDevice& avDevice,
580                                                    subunit_t id,
581                                                    int verboseLevel )
582     : AvDeviceSubunit( avDevice, eST_Music, id, verboseLevel )
583 {
584 }
585
586 BeBoB::AvDeviceSubunitMusic::AvDeviceSubunitMusic()
587     : AvDeviceSubunit()
588 {
589 }
590
591 BeBoB::AvDeviceSubunitMusic::~AvDeviceSubunitMusic()
592 {
593 }
594
595 const char*
596 BeBoB::AvDeviceSubunitMusic::getName()
597 {
598     return "MusicSubunit";
599 }
600
601 bool
602 BeBoB::AvDeviceSubunitMusic::serializeChild( Glib::ustring basePath,
603                                              Util::IOSerialize& ser ) const
604 {
605     return true;
606 }
607
608 bool
609 BeBoB::AvDeviceSubunitMusic::deserializeChild( Glib::ustring basePath,
610                                                Util::IODeserialize& deser,
611                                                AvDevice& avDevice )
612 {
613     return true;
614 }
Note: See TracBrowser for help on using the browser.