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

Revision 736, 13.5 kB (checked in by ppalmers, 16 years ago)

fix some stuff that was not merged correctly

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 "libutil/cmd_serialize.h"
33
34 #include <sstream>
35
36 using namespace AVC;
37
38 //////////////////////////
39
40 BeBoB::SubunitAudio::SubunitAudio( AVC::Unit& avDevice,
41                                    subunit_t id )
42     : AVC::SubunitAudio( avDevice, id )
43 {
44 }
45
46 BeBoB::SubunitAudio::SubunitAudio()
47     : AVC::SubunitAudio()
48 {
49 }
50
51 BeBoB::SubunitAudio::~SubunitAudio()
52 {
53     for ( FunctionBlockVector::iterator it = m_functions.begin();
54           it != m_functions.end();
55           ++it )
56     {
57         delete *it;
58     }
59 }
60
61 AVC::Plug *
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 )
69 {
70
71     return new BeBoB::Plug( unit,
72                      subunit,
73                      functionBlockType,
74                      functionBlockId,
75                      plugAddressType,
76                      plugDirection,
77                      plugId );
78 }
79
80 bool
81 BeBoB::SubunitAudio::discover()
82 {
83     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering %s...\n", getName());
84
85     // discover the AV/C generic part
86     if ( !AVC::SubunitAudio::discover() ) {
87         return false;
88     }
89
90     // do the remaining BeBoB audio subunit discovery
91     if ( !discoverFunctionBlocks() ) {
92         debugError( "function block discovering failed\n" );
93         return false;
94     }
95
96     return true;
97 }
98
99 bool
100 BeBoB::SubunitAudio::discoverConnections()
101 {
102     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering connections...\n");
103     if ( !Subunit::discoverConnections() ) {
104         return false;
105     }
106
107     for ( FunctionBlockVector::iterator it = m_functions.begin();
108           it != m_functions.end();
109           ++it )
110     {
111         FunctionBlock* function = *it;
112         if ( !function->discoverConnections() ) {
113             debugError( "functionblock connection discovering failed ('%s')\n",
114                         function->getName() );
115             return false;
116         }
117     }
118
119     return true;
120 }
121
122 const char*
123 BeBoB::SubunitAudio::getName()
124 {
125     return "BeBoB::AudioSubunit";
126 }
127
128 bool
129 BeBoB::SubunitAudio::discoverFunctionBlocks()
130 {
131     debugOutput( DEBUG_LEVEL_NORMAL,
132                  "Discovering function blocks...\n");
133
134     if ( !discoverFunctionBlocksDo(
135              ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector) )
136     {
137         debugError( "Could not discover function block selector\n" );
138         return false;
139     }
140     if ( !discoverFunctionBlocksDo(
141              ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature) )
142     {
143         debugError( "Could not discover function block feature\n" );
144         return false;
145     }
146     if ( !discoverFunctionBlocksDo(
147              ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing) )
148     {
149         debugError( "Could not discover function block processing\n" );
150         return false;
151     }
152     if ( !discoverFunctionBlocksDo(
153              ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec) )
154     {
155         debugError( "Could not discover function block codec\n" );
156         return false;
157     }
158
159     // print a function block list
160 #ifdef DEBUG
161     if ((int)getDebugLevel() >= DEBUG_LEVEL_NORMAL) {
162
163         for ( FunctionBlockVector::iterator it = m_functions.begin();
164             it != m_functions.end();
165             ++it )
166         {
167             debugOutput(DEBUG_LEVEL_NORMAL, "%20s FB, type 0x%X, id=%d\n",
168                 (*it)->getName(),
169                 (*it)->getType(),
170                 (*it)->getId());
171         }
172     }
173 #endif
174
175     return true;
176 }
177
178 bool
179 BeBoB::SubunitAudio::discoverFunctionBlocksDo(
180     ExtendedSubunitInfoCmd::EFunctionBlockType fbType )
181 {
182     int page = 0;
183     bool cmdSuccess = false;
184     bool finished = false;
185
186     do {
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() );
194
195         extSubunitInfoCmd.m_fbType = fbType;
196         extSubunitInfoCmd.m_page = page;
197
198         cmdSuccess = extSubunitInfoCmd.fire();
199         if ( cmdSuccess
200              && ( extSubunitInfoCmd.getResponse()
201                   == AVCCommand::eR_Implemented ) )
202         {
203             for ( ExtendedSubunitInfoPageDataVector::iterator it =
204                       extSubunitInfoCmd.m_infoPageDatas.begin();
205                   cmdSuccess
206                       && ( it != extSubunitInfoCmd.m_infoPageDatas.end() );
207                   ++it )
208             {
209                 cmdSuccess = createFunctionBlock( fbType, **it );
210             }
211             if ( ( extSubunitInfoCmd.m_infoPageDatas.size() != 0 )
212                  && ( extSubunitInfoCmd.m_infoPageDatas.size() == 5 ) )
213             {
214                 page++;
215             } else {
216                 finished = true;
217             }
218         } else {
219             finished = true;
220         }
221     } while ( cmdSuccess && !finished );
222
223     return cmdSuccess;
224 }
225
226 bool
227 BeBoB::SubunitAudio::createFunctionBlock(
228     ExtendedSubunitInfoCmd::EFunctionBlockType fbType,
229     ExtendedSubunitInfoPageData& data )
230 {
231     FunctionBlock::ESpecialPurpose purpose
232         = convertSpecialPurpose(  data.m_functionBlockSpecialPupose );
233
234     FunctionBlock* fb = 0;
235
236     switch ( fbType ) {
237     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector:
238     {
239         fb = new FunctionBlockSelector( *this,
240                                         data.m_functionBlockId,
241                                         purpose,
242                                         data.m_noOfInputPlugs,
243                                         data.m_noOfOutputPlugs,
244                                         (int)getDebugLevel() );
245     }
246     break;
247     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature:
248     {
249         fb = new FunctionBlockFeature( *this,
250                                        data.m_functionBlockId,
251                                        purpose,
252                                        data.m_noOfInputPlugs,
253                                        data.m_noOfOutputPlugs,
254                                        (int)getDebugLevel() );
255     }
256     break;
257     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing:
258     {
259         switch ( data.m_functionBlockType ) {
260         case ExtendedSubunitInfoCmd::ePT_EnhancedMixer:
261         {
262             fb = new FunctionBlockEnhancedMixer( *this,
263                                                  data.m_functionBlockId,
264                                                  purpose,
265                                                  data.m_noOfInputPlugs,
266                                                  data.m_noOfOutputPlugs,
267                                                  (int)getDebugLevel() );
268         }
269         break;
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:
278         default:
279             fb = new FunctionBlockProcessing( *this,
280                                               data.m_functionBlockId,
281                                               purpose,
282                                               data.m_noOfInputPlugs,
283                                               data.m_noOfOutputPlugs,
284                                               (int)getDebugLevel() );
285             debugWarning( "Dummy function block processing created. "
286                           "Implementation is missing\n" );
287         }
288     }
289     break;
290     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec:
291     {
292         fb = new FunctionBlockCodec( *this,
293                                      data.m_functionBlockId,
294                                      purpose,
295                                      data.m_noOfInputPlugs,
296                                      data.m_noOfOutputPlugs,
297                                      (int)getDebugLevel() );
298         debugWarning( "Dummy function block codec created. "
299                       "Implementation is missing\n" );
300     }
301     break;
302     default:
303         debugError( "Unhandled function block type found\n" );
304         return false;
305     }
306
307     if ( !fb ) {
308         debugError( "Could create function block\n" );
309         return false;
310     }
311     if ( !fb->discover() ) {
312         debugError( "Could not discover function block %s\n",
313                     fb->getName() );
314         delete fb;
315         return false;
316     }
317     m_functions.push_back( fb );
318
319     return true;
320 }
321
322 BeBoB::FunctionBlock::ESpecialPurpose
323 BeBoB::SubunitAudio::convertSpecialPurpose(
324     function_block_special_purpose_t specialPurpose )
325 {
326     FunctionBlock::ESpecialPurpose p;
327     switch ( specialPurpose ) {
328     case ExtendedSubunitInfoPageData::eSP_InputGain:
329         p  = FunctionBlock::eSP_InputGain;
330         break;
331     case ExtendedSubunitInfoPageData::eSP_OutputVolume:
332         p = FunctionBlock::eSP_OutputVolume;
333     break;
334     default:
335         p = FunctionBlock::eSP_NoSpecialPurpose;
336     }
337     return p;
338 }
339
340 bool
341 BeBoB::SubunitAudio::serializeChild( Glib::ustring basePath,
342                                      Util::IOSerialize& ser ) const
343 {
344     bool result = true;
345     int i = 0;
346
347     for ( FunctionBlockVector::const_iterator it = m_functions.begin();
348           it != m_functions.end();
349           ++it )
350     {
351         FunctionBlock* pFB = *it;
352         std::ostringstream strstrm;
353         strstrm << basePath << "FunctionBlock" << i << "/";
354
355         result &= pFB->serialize( strstrm.str() , ser );
356
357         i++;
358     }
359
360     return result;
361 }
362
363 bool
364 BeBoB::SubunitAudio::deserializeChild( Glib::ustring basePath,
365                                        Util::IODeserialize& deser,
366                                        AVC::Unit& avDevice )
367 {
368     int i = 0;
369     bool bFinished = false;
370     do {
371         std::ostringstream strstrm;
372         strstrm << basePath << "FunctionBlock" << i << "/";
373         FunctionBlock* pFB = FunctionBlock::deserialize( strstrm.str(),
374                                                          deser,
375                                                          avDevice,
376                                                          *this );
377         if ( pFB ) {
378             m_functions.push_back( pFB );
379             i++;
380         } else {
381             bFinished = true;
382         }
383     } while ( !bFinished );
384
385     return true;
386 }
387
388 ////////////////////////////////////////////
389
390 BeBoB::SubunitMusic::SubunitMusic( AVC::Unit& avDevice,
391                                    subunit_t id )
392     : AVC::SubunitMusic( avDevice, id )
393 {
394 }
395
396 BeBoB::SubunitMusic::SubunitMusic()
397     : AVC::SubunitMusic()
398 {
399 }
400
401 BeBoB::SubunitMusic::~SubunitMusic()
402 {
403 }
404
405 AVC::Plug *
406 BeBoB::SubunitMusic::createPlug( AVC::Unit* unit,
407                      AVC::Subunit* subunit,
408                      AVC::function_block_type_t functionBlockType,
409                      AVC::function_block_type_t functionBlockId,
410                      AVC::Plug::EPlugAddressType plugAddressType,
411                      AVC::Plug::EPlugDirection plugDirection,
412                      AVC::plug_id_t plugId )
413 {
414
415     return new BeBoB::Plug( unit,
416                      subunit,
417                      functionBlockType,
418                      functionBlockId,
419                      plugAddressType,
420                      plugDirection,
421                      plugId );
422 }
423
424 bool
425 BeBoB::SubunitMusic::discover()
426 {
427     debugOutput(DEBUG_LEVEL_NORMAL, "Discovering %s...\n", getName());
428
429     // discover the AV/C generic part
430     if ( !AVC::SubunitMusic::discover() ) {
431         return false;
432     }
433
434     // do the remaining BeBoB music subunit discovery
435     // which is nothing
436
437     return true;
438 }
439
440 const char*
441 BeBoB::SubunitMusic::getName()
442 {
443     return "BeBoB::MusicSubunit";
444 }
445
446 bool
447 BeBoB::SubunitMusic::serializeChild( Glib::ustring basePath,
448                                              Util::IOSerialize& ser ) const
449 {
450     return true;
451 }
452
453 bool
454 BeBoB::SubunitMusic::deserializeChild( Glib::ustring basePath,
455                                                Util::IODeserialize& deser,
456                                                AVC::Unit& avDevice )
457 {
458     return true;
459 }
Note: See TracBrowser for help on using the browser.