root/branches/echoaudio/src/bebob/bebob_avplug.cpp

Revision 543, 17.4 kB (checked in by ppalmers, 15 years ago)

- some cosmetic changes
- struggle with the indexing of bebob channels
- reimplement propagateClusterInfos to make sure it doesn't do anything

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_avplug.h"
25 #include "bebob/bebob_avdevice.h"
26 #include "libieee1394/configrom.h"
27
28 #include "libieee1394/ieee1394service.h"
29 #include "libavc/util/avc_serialize.h"
30
31 #include <sstream>
32
33 using namespace AVC;
34
35 namespace BeBoB {
36
37 Plug::Plug( AVC::Unit* unit,
38             AVC::Subunit* subunit,
39             AVC::function_block_type_t functionBlockType,
40             AVC::function_block_type_t functionBlockId,
41             AVC::Plug::EPlugAddressType plugAddressType,
42             AVC::Plug::EPlugDirection plugDirection,
43             AVC::plug_id_t plugId )
44     : AVC::Plug( unit,
45                  subunit,
46                  functionBlockType,
47                  functionBlockId,
48                  plugAddressType,
49                  plugDirection,
50                  plugId )
51 {
52     debugOutput( DEBUG_LEVEL_VERBOSE,
53                  "nodeId = %d, subunitType = %d, "
54                  "subunitId = %d, functionBlockType = %d, "
55                  "functionBlockId = %d, addressType = %d, "
56                  "direction = %d, id = %d\n",
57                  unit->getConfigRom().getNodeId(),
58                  getSubunitType(),
59                  getSubunitId(),
60                  functionBlockType,
61                  functionBlockId,
62                  plugAddressType,
63                  plugDirection,
64                  plugId );
65 }
66
67 Plug::Plug( const Plug& rhs )
68     : AVC::Plug( rhs )
69 {
70
71 }
72
73 Plug::Plug()
74     : AVC::Plug()
75 {
76 }
77
78 Plug::~Plug()
79 {
80
81 }
82
83 bool
84 Plug::discover()
85 {
86     if ( !discoverPlugType() ) {
87         debugError( "discover: Could not discover plug type (%d,%d,%d,%d,%d)\n",
88                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
89         return false;
90     }
91
92     if ( !discoverName() ) {
93         debugError( "Could not discover name (%d,%d,%d,%d,%d)\n",
94                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
95         return false;
96     }
97
98     if ( !discoverNoOfChannels() ) {
99         debugError( "Could not discover number of channels "
100                     "(%d,%d,%d,%d,%d)\n",
101                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
102         return false;
103     }
104
105     if ( !discoverChannelPosition() ) {
106         debugError( "Could not discover channel positions "
107                     "(%d,%d,%d,%d,%d)\n",
108                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
109         return false;
110     }
111
112     if ( !discoverChannelName() ) {
113         debugError( "Could not discover channel name "
114                     "(%d,%d,%d,%d,%d)\n",
115                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
116         return false;
117     }
118
119     if ( !discoverClusterInfo() ) {
120         debugError( "Could not discover channel name "
121                     "(%d,%d,%d,%d,%d)\n",
122                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
123         return false;
124     }
125
126     if ( !discoverStreamFormat() ) {
127         debugError( "Could not discover stream format "
128                     "(%d,%d,%d,%d,%d)\n",
129                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
130         return false;
131     }
132
133     if ( !discoverSupportedStreamFormats() ) {
134         debugError( "Could not discover supported stream formats "
135                     "(%d,%d,%d,%d,%d)\n",
136                     m_unit->getConfigRom().getNodeId(), getSubunitType(), getSubunitId(), m_direction, m_id );
137         return false;
138     }
139
140     return m_unit->getPlugManager().addPlug( *this );
141 }
142
143 bool
144 Plug::discoverConnections()
145 {
146     return discoverConnectionsInput() && discoverConnectionsOutput();
147 }
148
149 bool
150 Plug::discoverPlugType()
151 {
152     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
153     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
154         ExtendedPlugInfoInfoType::eIT_PlugType );
155     extendedPlugInfoInfoType.initialize();
156     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
157     extPlugInfoCmd.setVerbose( getDebugLevel() );
158
159     if ( !extPlugInfoCmd.fire() ) {
160         debugError( "plug type command failed\n" );
161         return false;
162     }
163
164     m_infoPlugType = eAPT_Unknown;
165
166     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Implemented ) {
167
168         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
169         if ( infoType
170              && infoType->m_plugType )
171         {
172             plug_type_t plugType = infoType->m_plugType->m_plugType;
173
174             debugOutput( DEBUG_LEVEL_VERBOSE,
175                          "plug %d is of type %d (%s)\n",
176                          m_id,
177                          plugType,
178                          extendedPlugInfoPlugTypeToString( plugType ) );
179             switch ( plugType ) {
180             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_IsoStream:
181                 m_infoPlugType = eAPT_IsoStream;
182                 break;
183             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_AsyncStream:
184                 m_infoPlugType = eAPT_AsyncStream;
185                 break;
186             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Midi:
187                 m_infoPlugType = eAPT_Midi;
188                 break;
189             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Sync:
190                 m_infoPlugType = eAPT_Sync;
191                 break;
192             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Analog:
193                 m_infoPlugType = eAPT_Analog;
194                 break;
195             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Digital:
196                 m_infoPlugType = eAPT_Digital;
197                 break;
198             default:
199                 m_infoPlugType = eAPT_Unknown;
200
201             }
202         }
203     } else {
204         debugError( "Plug does not implement extended plug info plug "
205                     "type info command\n" );
206         return false;
207     }
208
209    return true;
210 }
211
212 bool
213 Plug::discoverName()
214 {
215     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
216     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
217         ExtendedPlugInfoInfoType::eIT_PlugName );
218     extendedPlugInfoInfoType.initialize();
219     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
220     extPlugInfoCmd.setVerbose( getDebugLevel() );
221
222     if ( !extPlugInfoCmd.fire() ) {
223         debugError( "name command failed\n" );
224         return false;
225     }
226
227     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
228     if ( infoType
229          && infoType->m_plugName )
230     {
231         std::string name =
232             infoType->m_plugName->m_name;
233
234         debugOutput( DEBUG_LEVEL_VERBOSE,
235                      "plug %d has name '%s'\n",
236                      m_id,
237                      name.c_str() );
238
239         m_name = name;
240     }
241     return true;
242 }
243
244 bool
245 Plug::discoverNoOfChannels()
246 {
247     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
248     //extPlugInfoCmd.setVerbose( true );
249     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
250         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
251     extendedPlugInfoInfoType.initialize();
252     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
253     extPlugInfoCmd.setVerbose( getDebugLevel() );
254
255     if ( !extPlugInfoCmd.fire() ) {
256         debugError( "number of channels command failed\n" );
257         return false;
258     }
259
260     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
261     if ( infoType
262          && infoType->m_plugNrOfChns )
263     {
264         nr_of_channels_t nrOfChannels
265             = infoType->m_plugNrOfChns->m_nrOfChannels;
266
267         debugOutput( DEBUG_LEVEL_VERBOSE,
268                      "plug %d has %d channels\n",
269                      m_id,
270                      nrOfChannels );
271
272         m_nrOfChannels = nrOfChannels;
273     }
274     return true;
275 }
276
277 bool
278 Plug::discoverChannelPosition()
279 {
280     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
281     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
282         ExtendedPlugInfoInfoType::eIT_ChannelPosition );
283     extendedPlugInfoInfoType.initialize();
284     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
285     extPlugInfoCmd.setVerbose( getDebugLevel() );
286
287     if ( !extPlugInfoCmd.fire() ) {
288         debugError( "channel position command failed\n" );
289         return false;
290     }
291
292     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
293     if ( infoType
294          && infoType->m_plugChannelPosition )
295     {
296         if ( !copyClusterInfo( *( infoType->m_plugChannelPosition ) ) ) {
297             debugError( "Could not copy channel position "
298                         "information\n" );
299             return false;
300         }
301
302         debugOutput( DEBUG_LEVEL_VERBOSE,
303                      "plug %d: channel position information "
304                      "retrieved\n",
305                      m_id );
306
307         debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
308     }
309
310     return true;
311 }
312
313 bool
314 Plug::discoverChannelName()
315 {
316     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
317           clit != m_clusterInfos.end();
318           ++clit )
319     {
320         ClusterInfo* clitInfo = &*clit;
321
322         for ( ChannelInfoVector::iterator pit =  clitInfo->m_channelInfos.begin();
323               pit != clitInfo->m_channelInfos.end();
324               ++pit )
325         {
326             ChannelInfo* channelInfo = &*pit;
327
328             ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
329             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
330                 ExtendedPlugInfoInfoType::eIT_ChannelName );
331             extendedPlugInfoInfoType.initialize();
332             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
333             extPlugInfoCmd.setVerbose( getDebugLevel() );
334
335             ExtendedPlugInfoInfoType* infoType =
336                 extPlugInfoCmd.getInfoType();
337             if ( infoType ) {
338                 infoType->m_plugChannelName->m_streamPosition =
339                     channelInfo->m_streamPosition;
340             }
341             if ( !extPlugInfoCmd.fire() ) {
342                 debugError( "channel name command failed\n" );
343                 return false;
344             }
345             infoType = extPlugInfoCmd.getInfoType();
346             if ( infoType
347                  && infoType->m_plugChannelName )
348             {
349                 debugOutput( DEBUG_LEVEL_VERBOSE,
350                              "plug %d stream "
351                              "position %d: channel name = %s\n",
352                              m_id,
353                              channelInfo->m_streamPosition,
354                              infoType->m_plugChannelName->m_plugChannelName.c_str() );
355                 channelInfo->m_name =
356                     infoType->m_plugChannelName->m_plugChannelName;
357             }
358
359         }
360     }
361
362     return true;
363 }
364
365 bool
366 Plug::discoverClusterInfo()
367 {
368     if ( m_infoPlugType == eAPT_Sync )
369     {
370         // If the plug is of type sync it is either a normal 2 channel
371         // stream (not compound stream) or it is a compound stream
372         // with exactly one cluster. This depends on the
373         // extended stream format command version which is used.
374         // We are not interested in this plug so we skip it.
375         debugOutput( DEBUG_LEVEL_VERBOSE,
376                      "%s plug %d is of type sync -> skip\n",
377                      getName(),
378                      m_id );
379         return true;
380     }
381
382     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
383           clit != m_clusterInfos.end();
384           ++clit )
385     {
386         ClusterInfo* clusterInfo = &*clit;
387
388         ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
389         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
390             ExtendedPlugInfoInfoType::eIT_ClusterInfo );
391         extendedPlugInfoInfoType.initialize();
392         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
393         extPlugInfoCmd.setVerbose( getDebugLevel() );
394
395         extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
396             clusterInfo->m_index;
397
398         if ( !extPlugInfoCmd.fire() ) {
399             debugError( "cluster info command failed\n" );
400             return false;
401         }
402
403         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
404         if ( infoType
405              && infoType->m_plugClusterInfo )
406         {
407             debugOutput( DEBUG_LEVEL_VERBOSE,
408                          "%s plug %d: cluster index = %d, "
409                          "portType %s, cluster name = %s\n",
410                          getName(),
411                          m_id,
412                          infoType->m_plugClusterInfo->m_clusterIndex,
413                          extendedPlugInfoClusterInfoPortTypeToString(
414                              infoType->m_plugClusterInfo->m_portType ),
415                          infoType->m_plugClusterInfo->m_clusterName.c_str() );
416
417             clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
418             clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
419         }
420     }
421
422     return true;
423 }
424
425 bool
426 Plug::discoverConnectionsInput()
427 {
428     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
429     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
430         ExtendedPlugInfoInfoType::eIT_PlugInput );
431     extendedPlugInfoInfoType.initialize();
432     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
433     extPlugInfoCmd.setVerbose( getDebugLevel() );
434
435     if ( !extPlugInfoCmd.fire() ) {
436         debugError( "plug type command failed\n" );
437         return false;
438     }
439
440     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
441         // Plugs does not like to be asked about connections
442         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
443                      "connections command\n",
444                      getName() );
445         return true;
446     }
447
448     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
449     if ( infoType
450          && infoType->m_plugInput )
451     {
452         PlugAddressSpecificData* plugAddress
453             = infoType->m_plugInput->m_plugAddress;
454
455         if ( plugAddress->m_addressMode ==
456              PlugAddressSpecificData::ePAM_Undefined )
457         {
458             // This plug has no input connection
459             return true;
460         }
461
462         if ( !discoverConnectionsFromSpecificData( eAPD_Input,
463                                                    plugAddress,
464                                                    m_inputConnections ) )
465         {
466             debugWarning( "Could not discover connnections for plug '%s'\n",
467                           getName() );
468         }
469     } else {
470         debugError( "no valid info type for plug '%s'\n", getName() );
471         return false;
472     }
473
474     return true;
475 }
476
477 bool
478 Plug::discoverConnectionsOutput()
479 {
480     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
481     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
482         ExtendedPlugInfoInfoType::eIT_PlugOutput );
483     extendedPlugInfoInfoType.initialize();
484     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
485     extPlugInfoCmd.setVerbose( getDebugLevel() );
486
487     if ( !extPlugInfoCmd.fire() ) {
488         debugError( "plug type command failed\n" );
489         return false;
490     }
491
492     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
493         // Plugs does not like to be asked about connections
494         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
495                      "connections command\n",
496                      getName() );
497         return true;
498     }
499
500     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
501     if ( infoType
502          && infoType->m_plugOutput )
503     {
504         if ( infoType->m_plugOutput->m_nrOfOutputPlugs
505              != infoType->m_plugOutput->m_outputPlugAddresses.size() )
506         {
507             debugError( "number of output plugs (%d) disagree with "
508                         "number of elements in plug address vector (%d)\n",
509                         infoType->m_plugOutput->m_nrOfOutputPlugs,
510                         infoType->m_plugOutput->m_outputPlugAddresses.size());
511         }
512
513         if ( infoType->m_plugOutput->m_nrOfOutputPlugs == 0 ) {
514             // This plug has no output connections
515             return true;
516         }
517
518         for ( unsigned int i = 0;
519               i < infoType->m_plugOutput->m_outputPlugAddresses.size();
520               ++i )
521         {
522             PlugAddressSpecificData* plugAddress
523                 = infoType->m_plugOutput->m_outputPlugAddresses[i];
524
525             if ( !discoverConnectionsFromSpecificData( eAPD_Output,
526                                                        plugAddress,
527                                                        m_outputConnections ) )
528             {
529                 debugWarning( "Could not discover connnections for "
530                               "plug '%s'\n", getName() );
531             }
532         }
533     } else {
534         debugError( "no valid info type for plug '%s'\n", getName() );
535         return false;
536     }
537
538     return true;
539 }
540
541 }
Note: See TracBrowser for help on using the browser.