2 * Copyright (C) 2005-2008 by Daniel Wagner
4 * This file is part of FFADO
5 * FFADO = Free Firewire (pro-)audio drivers for linux
7 * FFADO is based upon FreeBoB
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.
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.
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/>.
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"
30 #include "libavc/general/avc_plug_info.h"
31 #include "libavc/streamformat/avc_extended_stream_format.h"
32 #include "libutil/cmd_serialize.h"
38 //////////////////////////
40 BeBoB::SubunitAudio::SubunitAudio( AVC::Unit
& avDevice
,
42 : AVC::SubunitAudio( avDevice
, id
)
46 BeBoB::SubunitAudio::SubunitAudio()
51 BeBoB::SubunitAudio::~SubunitAudio()
53 for ( FunctionBlockVector::iterator it
= m_functions
.begin();
54 it
!= m_functions
.end();
62 BeBoB::SubunitAudio::createPlug( AVC::Unit
* unit
,
63 AVC::Subunit
* subunit
,
64 AVC::function_block_type_t functionBlockType
,
65 AVC::function_block_type_t functionBlockId
,
66 AVC::Plug::EPlugAddressType plugAddressType
,
67 AVC::Plug::EPlugDirection plugDirection
,
68 AVC::plug_id_t plugId
)
71 return new BeBoB::Plug( unit
,
81 BeBoB::SubunitAudio::discover()
83 debugOutput(DEBUG_LEVEL_NORMAL
, "Discovering %s...\n", getName());
85 // discover the AV/C generic part
86 if ( !AVC::SubunitAudio::discover() ) {
90 // do the remaining BeBoB audio subunit discovery
91 if ( !discoverFunctionBlocks() ) {
92 debugError( "function block discovering failed\n" );
100 BeBoB::SubunitAudio::discoverConnections()
102 debugOutput(DEBUG_LEVEL_NORMAL
, "Discovering connections...\n");
103 if ( !Subunit::discoverConnections() ) {
107 for ( FunctionBlockVector::iterator it
= m_functions
.begin();
108 it
!= m_functions
.end();
111 FunctionBlock
* function
= *it
;
112 if ( !function
->discoverConnections() ) {
113 debugError( "functionblock connection discovering failed ('%s')\n",
114 function
->getName() );
123 BeBoB::SubunitAudio::getName()
125 return "BeBoB::AudioSubunit";
129 BeBoB::SubunitAudio::discoverFunctionBlocks()
131 debugOutput( DEBUG_LEVEL_NORMAL
,
132 "Discovering function blocks...\n");
134 if ( !discoverFunctionBlocksDo(
135 ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector
) )
137 debugError( "Could not discover function block selector\n" );
140 if ( !discoverFunctionBlocksDo(
141 ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature
) )
143 debugError( "Could not discover function block feature\n" );
146 if ( !discoverFunctionBlocksDo(
147 ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing
) )
149 debugError( "Could not discover function block processing\n" );
152 if ( !discoverFunctionBlocksDo(
153 ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec
) )
155 debugError( "Could not discover function block codec\n" );
159 // print a function block list
161 if ((int)getDebugLevel() >= DEBUG_LEVEL_NORMAL
) {
163 for ( FunctionBlockVector::iterator it
= m_functions
.begin();
164 it
!= m_functions
.end();
167 debugOutput(DEBUG_LEVEL_NORMAL
, "%20s FB, type 0x%X, id=%d\n",
179 BeBoB::SubunitAudio::discoverFunctionBlocksDo(
180 ExtendedSubunitInfoCmd::EFunctionBlockType fbType
)
183 bool cmdSuccess
= false;
184 bool finished
= false;
187 ExtendedSubunitInfoCmd
188 extSubunitInfoCmd( m_unit
->get1394Service() );
189 extSubunitInfoCmd
.setNodeId( m_unit
->getConfigRom().getNodeId() );
190 extSubunitInfoCmd
.setCommandType( AVCCommand::eCT_Status
);
191 extSubunitInfoCmd
.setSubunitId( getSubunitId() );
192 extSubunitInfoCmd
.setSubunitType( getSubunitType() );
193 extSubunitInfoCmd
.setVerbose( (int)getDebugLevel() );
195 extSubunitInfoCmd
.m_fbType
= fbType
;
196 extSubunitInfoCmd
.m_page
= page
;
198 cmdSuccess
= extSubunitInfoCmd
.fire();
200 && ( extSubunitInfoCmd
.getResponse()
201 == AVCCommand::eR_Implemented
) )
203 for ( ExtendedSubunitInfoPageDataVector::iterator it
=
204 extSubunitInfoCmd
.m_infoPageDatas
.begin();
206 && ( it
!= extSubunitInfoCmd
.m_infoPageDatas
.end() );
209 cmdSuccess
= createFunctionBlock( fbType
, **it
);
211 if ( ( extSubunitInfoCmd
.m_infoPageDatas
.size() != 0 )
212 && ( extSubunitInfoCmd
.m_infoPageDatas
.size() == 5 ) )
221 } while ( cmdSuccess
&& !finished
);
227 BeBoB::SubunitAudio::createFunctionBlock(
228 ExtendedSubunitInfoCmd::EFunctionBlockType fbType
,
229 ExtendedSubunitInfoPageData
& data
)
231 FunctionBlock::ESpecialPurpose purpose
232 = convertSpecialPurpose( data
.m_functionBlockSpecialPupose
);
234 FunctionBlock
* fb
= 0;
237 case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector
:
239 fb
= new FunctionBlockSelector( *this,
240 data
.m_functionBlockId
,
242 data
.m_noOfInputPlugs
,
243 data
.m_noOfOutputPlugs
,
244 (int)getDebugLevel() );
247 case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature
:
249 fb
= new FunctionBlockFeature( *this,
250 data
.m_functionBlockId
,
252 data
.m_noOfInputPlugs
,
253 data
.m_noOfOutputPlugs
,
254 (int)getDebugLevel() );
257 case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing
:
259 switch ( data
.m_functionBlockType
) {
260 case ExtendedSubunitInfoCmd::ePT_EnhancedMixer
:
262 fb
= new FunctionBlockEnhancedMixer( *this,
263 data
.m_functionBlockId
,
265 data
.m_noOfInputPlugs
,
266 data
.m_noOfOutputPlugs
,
267 (int)getDebugLevel() );
270 case ExtendedSubunitInfoCmd::ePT_Mixer
:
271 case ExtendedSubunitInfoCmd::ePT_Generic
:
272 case ExtendedSubunitInfoCmd::ePT_UpDown
:
273 case ExtendedSubunitInfoCmd::ePT_DolbyProLogic
:
274 case ExtendedSubunitInfoCmd::ePT_3DStereoExtender
:
275 case ExtendedSubunitInfoCmd::ePT_Reverberation
:
276 case ExtendedSubunitInfoCmd::ePT_Chorus
:
277 case ExtendedSubunitInfoCmd::ePT_DynamicRangeCompression
:
279 /* It is no use to add a dummy FunctionBlockProcessing because
280 then the function type is not set in FunctionBlockProcessing.
281 When we try to discover the plugs attached to this function block
282 it will fail. It's better just to skip them. */
283 debugOutput( DEBUG_LEVEL_NORMAL
, "Found a processing subfunction (type %d) which is not supported. "
284 "It will be ignored.\n",
285 data
.m_functionBlockType
);
290 case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec
:
292 /* It is no use to add a dummy FunctionBlockProcessing because
293 then the function type is not set in FunctionBlockProcessing.
294 When we try to discover the plugs attached to this function block
295 it will fail. It's better just to skip them. */
296 debugOutput( DEBUG_LEVEL_NORMAL
, "Found a codec subfunction (type %d) which is not supported. "
297 "It will be ignored.\n",
298 data
.m_functionBlockType
);
303 debugError( "Unhandled function block type found\n" );
308 debugError( "Could create function block\n" );
311 if ( !fb
->discover() ) {
312 debugError( "Could not discover function block %s\n",
317 m_functions
.push_back( fb
);
322 BeBoB::FunctionBlock::ESpecialPurpose
323 BeBoB::SubunitAudio::convertSpecialPurpose(
324 function_block_special_purpose_t specialPurpose
)
326 FunctionBlock::ESpecialPurpose p
;
327 switch ( specialPurpose
) {
328 case ExtendedSubunitInfoPageData::eSP_InputGain
:
329 p
= FunctionBlock::eSP_InputGain
;
331 case ExtendedSubunitInfoPageData::eSP_OutputVolume
:
332 p
= FunctionBlock::eSP_OutputVolume
;
335 p
= FunctionBlock::eSP_NoSpecialPurpose
;
341 BeBoB::SubunitAudio::serializeChild( std::string basePath
,
342 Util::IOSerialize
& ser
) const
347 for ( FunctionBlockVector::const_iterator it
= m_functions
.begin();
348 it
!= m_functions
.end();
351 FunctionBlock
* pFB
= *it
;
352 std::ostringstream strstrm
;
353 strstrm
<< basePath
<< "FunctionBlock" << i
<< "/";
355 result
&= pFB
->serialize( strstrm
.str() , ser
);
364 BeBoB::SubunitAudio::deserializeChild( std::string basePath
,
365 Util::IODeserialize
& deser
,
366 AVC::Unit
& avDevice
)
369 bool bFinished
= false;
371 std::ostringstream strstrm
;
372 strstrm
<< basePath
<< "FunctionBlock" << i
<< "/";
373 FunctionBlock
* pFB
= FunctionBlock::deserialize( strstrm
.str(),
378 m_functions
.push_back( pFB
);
383 } while ( !bFinished
);
389 BeBoB::SubunitAudio::deserializeUpdateChild( std::string basePath
,
390 Util::IODeserialize
& deser
)
395 for ( FunctionBlockVector::iterator it
= m_functions
.begin();
396 it
!= m_functions
.end();
399 std::ostringstream strstrm
;
400 strstrm
<< basePath
<< "FunctionBlock" << i
<< "/";
402 result
&= (*it
)->deserializeUpdate( basePath
, deser
);
410 ////////////////////////////////////////////
412 BeBoB::SubunitMusic::SubunitMusic( AVC::Unit
& avDevice
,
414 : AVC::SubunitMusic( avDevice
, id
)
418 BeBoB::SubunitMusic::SubunitMusic()
419 : AVC::SubunitMusic()
423 BeBoB::SubunitMusic::~SubunitMusic()
428 BeBoB::SubunitMusic::createPlug( AVC::Unit
* unit
,
429 AVC::Subunit
* subunit
,
430 AVC::function_block_type_t functionBlockType
,
431 AVC::function_block_type_t functionBlockId
,
432 AVC::Plug::EPlugAddressType plugAddressType
,
433 AVC::Plug::EPlugDirection plugDirection
,
434 AVC::plug_id_t plugId
)
437 return new BeBoB::Plug( unit
,
447 BeBoB::SubunitMusic::discover()
449 debugOutput(DEBUG_LEVEL_NORMAL
, "Discovering %s...\n", getName());
451 // discover the AV/C generic part
452 if ( !AVC::SubunitMusic::discover() ) {
456 // do the remaining BeBoB music subunit discovery
463 BeBoB::SubunitMusic::getName()
465 return "BeBoB::MusicSubunit";
469 BeBoB::SubunitMusic::serializeChild( std::string basePath
,
470 Util::IOSerialize
& ser
) const
476 BeBoB::SubunitMusic::deserializeChild( std::string basePath
,
477 Util::IODeserialize
& deser
,
478 AVC::Unit
& avDevice
)
484 BeBoB::SubunitMusic::deserializeUpdateChild( std::string basePath
,
485 Util::IODeserialize
& deser
)