root/branches/echoaudio/src/libavc/general/avc_subunit.cpp

Revision 507, 14.8 kB (checked in by ppalmers, 16 years ago)

[Temporary commit: compiles but doesn't run]

First pass on AV/C code refactoring. Generic code and data structures
are moved to libavc classes. Implementation/vendor specific stuff remains
in specific classes.

In this case all 'Extended' commands and the discovery procedures remain in
the bebob/ classes, while the remainder goes into the libavc classes.

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