root/branches/libfreebob-2.0/src/bebob/bebob_avdevice_subunit.cpp

Revision 341, 13.5 kB (checked in by pieterpalmers, 17 years ago)

- changed bebob avdevice to use debugmodule instead of printf/cout
- fixed some minor merge side-effects
- implement a RT safe mechanism to obtain the cycle counter.

Line 
1 /* bebob_avdevice_subunit.cpp
2  * Copyright (C) 2005,06 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 #include "bebob/bebob_functionblock.h"
22 #include "bebob/bebob_avdevice_subunit.h"
23 #include "bebob/bebob_avdevice.h"
24 #include "bebob/bebob_avplug.h"
25 #include "configrom.h"
26
27 #include "libfreebobavc/avc_plug_info.h"
28 #include "libfreebobavc/avc_extended_stream_format.h"
29 #include "libfreebobavc/serialize.h"
30
31 namespace BeBoB {
32
33 IMPL_DEBUG_MODULE( AvDeviceSubunit, AvDeviceSubunit, DEBUG_LEVEL_VERBOSE );
34
35 ////////////////////////////////////////////
36
37 AvDeviceSubunit::AvDeviceSubunit( AvDevice& avDevice,
38                                   AVCCommand::ESubunitType type,
39                                   subunit_t id,
40                                   int verboseLevel )
41     : m_avDevice( &avDevice )
42     , m_sbType( type )
43     , m_sbId( id )
44     , m_verboseLevel( verboseLevel )
45 {
46     setDebugLevel( m_verboseLevel );
47 }
48
49 AvDeviceSubunit::~AvDeviceSubunit()
50 {
51     for ( AvPlugVector::iterator it = m_plugs.begin();
52           it != m_plugs.end();
53           ++it )
54     {
55         delete *it;
56     }
57 }
58
59 bool
60 AvDeviceSubunit::discover()
61 {
62     if ( !discoverPlugs() ) {
63         debugError( "plug discovering failed\n" );
64         return false;
65     }
66
67     return true;
68 }
69
70 bool
71 AvDeviceSubunit::discoverPlugs()
72 {
73     PlugInfoCmd plugInfoCmd( m_avDevice->get1394Service(),
74                              PlugInfoCmd::eSF_SerialBusIsochronousAndExternalPlug );
75     plugInfoCmd.setNodeId( m_avDevice->getConfigRom().getNodeId() );
76     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
77     plugInfoCmd.setSubunitType( m_sbType );
78     plugInfoCmd.setSubunitId( m_sbId );
79     plugInfoCmd.setVerbose( m_verboseLevel );
80
81     if ( !plugInfoCmd.fire() ) {
82         debugError( "plug info command failed\n" );
83         return false;
84     }
85
86     debugOutput( DEBUG_LEVEL_NORMAL, "number of source plugs = %d\n",
87                  plugInfoCmd.m_sourcePlugs );
88     debugOutput( DEBUG_LEVEL_NORMAL, "number of destination output "
89                  "plugs = %d\n", plugInfoCmd.m_destinationPlugs );
90
91     if ( !discoverPlugs( AvPlug::eAPD_Input,
92                          plugInfoCmd.m_destinationPlugs ) )
93     {
94         debugError( "destination plug discovering failed\n" );
95         return false;
96     }
97
98     if ( !discoverPlugs(  AvPlug::eAPD_Output,
99                           plugInfoCmd.m_sourcePlugs ) )
100     {
101         debugError( "source plug discovering failed\n" );
102         return false;
103     }
104
105     return true;
106 }
107
108 bool
109 AvDeviceSubunit::discoverConnections()
110 {
111     for ( AvPlugVector::iterator it = m_plugs.begin();
112           it != m_plugs.end();
113           ++it )
114     {
115         AvPlug* plug = *it;
116         if ( !plug->discoverConnections() ) {
117             debugError( "plug connection discovering failed ('%s')\n",
118                         plug->getName() );
119             return false;
120         }
121     }
122
123     return true;
124 }
125
126 bool
127 AvDeviceSubunit::discoverPlugs(AvPlug::EAvPlugDirection plugDirection,
128                                plug_id_t plugMaxId )
129 {
130     for ( int plugIdx = 0;
131           plugIdx < plugMaxId;
132           ++plugIdx )
133     {
134         AVCCommand::ESubunitType subunitType =
135             static_cast<AVCCommand::ESubunitType>( getSubunitType() );
136         AvPlug* plug = new AvPlug( *m_avDevice->get1394Service(),
137                                    m_avDevice->getConfigRom().getNodeId(),
138                                    m_avDevice->getPlugManager(),
139                                    subunitType,
140                                    getSubunitId(),
141                                    0xff,
142                                    0xff,
143                                    AvPlug::eAPA_SubunitPlug,
144                                    plugDirection,
145                                    plugIdx,
146                                    m_verboseLevel );
147         if ( !plug || !plug->discover() ) {
148             debugError( "plug discover failed\n" );
149             return false;
150         }
151
152         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
153                      plug->getName() );
154         m_plugs.push_back( plug );
155     }
156     return true;
157 }
158
159 bool
160 AvDeviceSubunit::addPlug( AvPlug& plug )
161 {
162     m_plugs.push_back( &plug );
163     return true;
164 }
165
166
167 AvPlug*
168 AvDeviceSubunit::getPlug(AvPlug::EAvPlugDirection direction, plug_id_t plugId)
169 {
170     for ( AvPlugVector::iterator it = m_plugs.begin();
171           it != m_plugs.end();
172           ++it )
173     {
174         AvPlug* plug = *it;
175         if ( ( plug->getPlugId() == plugId )
176             && ( plug->getDirection() == direction ) )
177         {
178             return plug;
179         }
180     }
181     return 0;
182 }
183
184 ////////////////////////////////////////////
185
186 AvDeviceSubunitAudio::AvDeviceSubunitAudio( AvDevice& avDevice,
187                                             subunit_t id,
188                                             int verboseLevel )
189     : AvDeviceSubunit( avDevice, AVCCommand::eST_Audio, id, verboseLevel )
190 {
191 }
192
193 AvDeviceSubunitAudio::~AvDeviceSubunitAudio()
194 {
195     for ( FunctionBlockVector::iterator it = m_functions.begin();
196           it != m_functions.end();
197           ++it )
198     {
199         delete *it;
200     }
201 }
202
203 bool
204 AvDeviceSubunitAudio::discover()
205 {
206     if ( !AvDeviceSubunit::discover() ) {
207         return false;
208     }
209
210     if ( !discoverFunctionBlocks() ) {
211         debugError( "function block discovering failed\n" );
212         return false;
213     }
214
215     return true;
216 }
217
218 bool
219 AvDeviceSubunitAudio::discoverConnections()
220 {
221     if ( !AvDeviceSubunit::discoverConnections() ) {
222         return false;
223     }
224
225     for ( FunctionBlockVector::iterator it = m_functions.begin();
226           it != m_functions.end();
227           ++it )
228     {
229         FunctionBlock* function = *it;
230         if ( !function->discoverConnections() ) {
231             debugError( "functionblock connection discovering failed ('%s')\n",
232                         function->getName() );
233             return false;
234         }
235     }
236
237     return true;
238 }
239
240 const char*
241 AvDeviceSubunitAudio::getName()
242 {
243     return "AudioSubunit";
244 }
245
246 bool
247 AvDeviceSubunitAudio::discoverFunctionBlocks()
248 {
249     if ( !discoverFunctionBlocksDo(
250              ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector) )
251     {
252         debugError( "Could not discover function block selector\n" );
253         return false;
254     }
255     if ( !discoverFunctionBlocksDo(
256              ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature) )
257     {
258         debugError( "Could not discover function block feature\n" );
259         return false;
260     }
261     if ( !discoverFunctionBlocksDo(
262              ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing) )
263     {
264         debugError( "Could not discover function block processing\n" );
265         return false;
266     }
267     if ( !discoverFunctionBlocksDo(
268              ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec) )
269     {
270         debugError( "Could not discover function block codec\n" );
271         return false;
272     }
273
274     return true;
275 }
276
277 bool
278 AvDeviceSubunitAudio::discoverFunctionBlocksDo(
279     ExtendedSubunitInfoCmd::EFunctionBlockType fbType )
280 {
281     int page = 0;
282     bool cmdSuccess = false;
283     bool finished = false;
284
285     do {
286         ExtendedSubunitInfoCmd
287             extSubunitInfoCmd( m_avDevice->get1394Service() );
288         extSubunitInfoCmd.setNodeId( m_avDevice->getConfigRom().getNodeId() );
289         extSubunitInfoCmd.setCommandType( AVCCommand::eCT_Status );
290         extSubunitInfoCmd.setSubunitId( getSubunitId() );
291         extSubunitInfoCmd.setSubunitType( getSubunitType() );
292         extSubunitInfoCmd.setVerbose( m_verboseLevel );
293
294         extSubunitInfoCmd.m_fbType = fbType;
295         extSubunitInfoCmd.m_page = page;
296
297         cmdSuccess = extSubunitInfoCmd.fire();
298         if ( cmdSuccess
299              && ( extSubunitInfoCmd.getResponse()
300                   == AVCCommand::eR_Implemented ) )
301         {
302             for ( ExtendedSubunitInfoPageDataVector::iterator it =
303                       extSubunitInfoCmd.m_infoPageDatas.begin();
304                   cmdSuccess
305                       && ( it != extSubunitInfoCmd.m_infoPageDatas.end() );
306                   ++it )
307             {
308                 cmdSuccess = createFunctionBlock( fbType, **it );
309             }
310             if ( ( extSubunitInfoCmd.m_infoPageDatas.size() != 0 )
311                  && ( extSubunitInfoCmd.m_infoPageDatas.size() == 5 ) )
312             {
313                 page++;
314             } else {
315                 finished = true;
316             }
317         } else {
318             finished = true;
319         }
320     } while ( cmdSuccess && !finished );
321
322     return cmdSuccess;
323 }
324
325 bool
326 AvDeviceSubunitAudio::createFunctionBlock(
327     ExtendedSubunitInfoCmd::EFunctionBlockType fbType,
328     ExtendedSubunitInfoPageData& data )
329 {
330     FunctionBlock::ESpecialPurpose purpose
331         = convertSpecialPurpose(  data.m_functionBlockSpecialPupose );
332
333     FunctionBlock* fb = 0;
334
335     switch ( fbType ) {
336     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitSelector:
337     {
338         fb = new FunctionBlockSelector( *this,
339                                         data.m_functionBlockId,
340                                         purpose,
341                                         data.m_noOfInputPlugs,
342                                         data.m_noOfOutputPlugs,
343                                         m_verboseLevel );
344     }
345     break;
346     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitFeature:
347     {
348         fb = new FunctionBlockFeature( *this,
349                                        data.m_functionBlockId,
350                                        purpose,
351                                        data.m_noOfInputPlugs,
352                                        data.m_noOfOutputPlugs,
353                                        m_verboseLevel );
354     }
355     break;
356     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitProcessing:
357     {
358         switch ( data.m_functionBlockType ) {
359         case ExtendedSubunitInfoCmd::ePT_EnhancedMixer:
360         {
361             fb = new FunctionBlockEnhancedMixer( *this,
362                                                  data.m_functionBlockId,
363                                                  purpose,
364                                                  data.m_noOfInputPlugs,
365                                                  data.m_noOfOutputPlugs,
366                                                  m_verboseLevel );
367         }
368         break;
369         case ExtendedSubunitInfoCmd::ePT_Mixer:
370         case ExtendedSubunitInfoCmd::ePT_Generic:
371         case ExtendedSubunitInfoCmd::ePT_UpDown:
372         case ExtendedSubunitInfoCmd::ePT_DolbyProLogic:
373         case ExtendedSubunitInfoCmd::ePT_3DStereoExtender:
374         case ExtendedSubunitInfoCmd::ePT_Reverberation:
375         case ExtendedSubunitInfoCmd::ePT_Chorus:
376         case ExtendedSubunitInfoCmd::ePT_DynamicRangeCompression:
377         default:
378             fb = new FunctionBlockProcessing( *this,
379                                               data.m_functionBlockId,
380                                               purpose,
381                                               data.m_noOfInputPlugs,
382                                               data.m_noOfOutputPlugs,
383                                               m_verboseLevel );
384             debugWarning( "Dummy function block processing created. "
385                           "Implementation is missing\n" );
386         }
387     }
388     break;
389     case ExtendedSubunitInfoCmd::eFBT_AudioSubunitCodec:
390     {
391         fb = new FunctionBlockCodec( *this,
392                                      data.m_functionBlockId,
393                                      purpose,
394                                      data.m_noOfInputPlugs,
395                                      data.m_noOfOutputPlugs,
396                                      m_verboseLevel );
397         debugWarning( "Dummy function block codec created. "
398                       "Implementation is missing\n" );
399     }
400     break;
401     default:
402         debugError( "Unhandled function block type found\n" );
403         return false;
404     }
405
406     if ( !fb ) {
407         debugError( "Could create function block\n" );
408         return false;
409     }
410     if ( !fb->discover() ) {
411         debugError( "Could not discover function block %s\n",
412                     fb->getName() );
413         delete fb;
414         return false;
415     }
416     m_functions.push_back( fb );
417
418     return true;
419 }
420
421 FunctionBlock::ESpecialPurpose
422 AvDeviceSubunitAudio::convertSpecialPurpose(
423     function_block_special_purpose_t specialPurpose )
424 {
425     FunctionBlock::ESpecialPurpose p;
426     switch ( specialPurpose ) {
427     case ExtendedSubunitInfoPageData::eSP_InputGain:
428         p  = FunctionBlock::eSP_InputGain;
429         break;
430     case ExtendedSubunitInfoPageData::eSP_OutputVolume:
431         p = FunctionBlock::eSP_OutputVolume;
432     break;
433     default:
434         p = FunctionBlock::eSP_NoSpecialPurpose;
435     }
436     return p;
437 }
438
439
440 ////////////////////////////////////////////
441
442 AvDeviceSubunitMusic::AvDeviceSubunitMusic( AvDevice& avDevice,
443                                             subunit_t id,
444                                             int verboseLevel )
445     : AvDeviceSubunit( avDevice, AVCCommand::eST_Music, id, verboseLevel )
446 {
447 }
448
449 AvDeviceSubunitMusic::~AvDeviceSubunitMusic()
450 {
451 }
452
453 const char*
454 AvDeviceSubunitMusic::getName()
455 {
456     return "MusicSubunit";
457 }
458
459 }
Note: See TracBrowser for help on using the browser.