root/branches/streaming-rework/src/bebob/bebob_avdevice_subunit.cpp

Revision 404, 17.2 kB (checked in by pieterpalmers, 16 years ago)

- introduce support framework for DICE and Metric Halo
- change probe/discovery code to make adding devices easier
- made conditional compilation effectively work.

./configure now has the following switches:

--enable-bebob build BeBoB support (default=yes)
--enable-motu build Motu support (default=no)
--enable-dice build DICE support (default=no)
--enable-metric-halo build Metric Halo support (note: completely useless)

(default=no)

--enable-rme build RME support (note: completely useless)

(default=no)

--enable-bounce build Bounce device support (default=no)
--enable-all-devices build support for all supported devices (default=no)

these now turn on/off compilation effectively.

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