root/trunk/libfreebob/src/bebob/bebob_avplug.cpp

Revision 187, 56.5 kB (checked in by wagi, 18 years ago)

2006-05-04 Daniel Wagner <wagi@monom.org>

  • configure.ac: Version bumped to 0.7.2
  • src/bebob: Some cleanup on naming and
    namespaces.
Line 
1 /* bebob_avplug.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_avplug.h"
22
23 #include "libfreebobavc/ieee1394service.h"
24 #include "libfreebobavc/serialize.h"
25
26 namespace BeBoB {
27
28 int AvPlug::m_globalIdCounter = 0;
29
30 IMPL_DEBUG_MODULE( AvPlug, AvPlug, DEBUG_LEVEL_NORMAL );
31 IMPL_DEBUG_MODULE( AvPlugManager, AvPlugManager, DEBUG_LEVEL_NORMAL );
32
33 AvPlug::AvPlug( Ieee1394Service& ieee1394Service,
34                 int nodeId,
35                 AvPlugManager& plugManager,
36                 AVCCommand::ESubunitType subunitType,
37                 subunit_id_t subunitId,
38                 function_block_type_t functionBlockType,
39                 function_block_id_t functionBlockId,
40                 EAvPlugAddressType plugAddressType,
41                 EAvPlugDirection plugDirection,
42                 plug_id_t plugId,
43                 int verboseLevel )
44     : m_1394Service( &ieee1394Service )
45     , m_nodeId( nodeId )
46     , m_subunitType( subunitType )
47     , m_subunitId( subunitId )
48     , m_functionBlockType( functionBlockType )
49     , m_functionBlockId( functionBlockId )
50     , m_addressType( plugAddressType )
51     , m_direction( plugDirection )
52     , m_id( plugId )
53     , m_infoPlugType( eAPT_Unknown )
54     , m_nrOfChannels( 0 )
55     , m_plugManager( &plugManager )
56     , m_verboseLevel( verboseLevel )
57     , m_globalId( m_globalIdCounter++ )
58 {
59     if ( m_verboseLevel ) {
60         setDebugLevel( DEBUG_LEVEL_VERBOSE );
61     }
62     debugOutput( DEBUG_LEVEL_VERBOSE,
63                  "nodeId = %d, subunitType = %d, "
64                  "subunitId = %d, functionBlockType = %d, "
65                  "functionBlockId = %d, addressType = %d, "
66                  "direction = %d, id = %d\n",
67                  m_nodeId,
68                  m_subunitType,
69                  m_subunitId,
70                  m_functionBlockType,
71                  m_functionBlockId,
72                  m_addressType,
73                  m_direction,
74                  m_id );
75 }
76
77 AvPlug::AvPlug( const AvPlug& rhs )
78     : m_1394Service( rhs.m_1394Service )
79     , m_nodeId( rhs.m_nodeId )
80     , m_subunitType( rhs.m_subunitType )
81     , m_subunitId( rhs.m_subunitId )
82     , m_functionBlockType( rhs.m_functionBlockType )
83     , m_functionBlockId( rhs.m_functionBlockId )
84     , m_addressType( rhs.m_addressType )
85     , m_direction( rhs.m_direction )
86     , m_id( rhs.m_id )
87     , m_infoPlugType( rhs.m_infoPlugType )
88     , m_nrOfChannels( rhs.m_nrOfChannels )
89     , m_name( rhs.m_name )
90     , m_clusterInfos( rhs.m_clusterInfos )
91     , m_formatInfos( rhs.m_formatInfos )
92     , m_plugManager( rhs.m_plugManager )
93     , m_verboseLevel( rhs.m_verboseLevel )
94 {
95     if ( m_verboseLevel ) {
96         setDebugLevel( DEBUG_LEVEL_VERBOSE );
97     }
98 }
99
100 AvPlug::~AvPlug()
101 {
102     m_plugManager->remPlug( *this );
103 }
104
105 bool
106 AvPlug::discover()
107 {
108     if ( !discoverPlugType() ) {
109         debugError( "discover: Could not discover plug type (%d,%d,%d,%d,%d)\n",
110                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
111         return false;
112     }
113
114     if ( !discoverName() ) {
115         debugError( "Could not discover name (%d,%d,%d,%d,%d)\n",
116                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
117         return false;
118     }
119
120     if ( !discoverNoOfChannels() ) {
121         debugError( "Could not discover number of channels "
122                     "(%d,%d,%d,%d,%d)\n",
123                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
124         return false;
125     }
126
127     if ( !discoverChannelPosition() ) {
128         debugError( "Could not discover channel positions "
129                     "(%d,%d,%d,%d,%d)\n",
130                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
131         return false;
132     }
133
134     if ( !discoverChannelName() ) {
135         debugError( "Could not discover channel name "
136                     "(%d,%d,%d,%d,%d)\n",
137                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
138         return false;
139     }
140
141     if ( !discoverClusterInfo() ) {
142         debugError( "Could not discover channel name "
143                     "(%d,%d,%d,%d,%d)\n",
144                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
145         return false;
146     }
147
148     if ( !discoverStreamFormat() ) {
149         debugError( "Could not discover stream format "
150                     "(%d,%d,%d,%d,%d)\n",
151                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
152         return false;
153     }
154
155     if ( !discoverSupportedStreamFormats() ) {
156         debugError( "Could not discover supported stream formats "
157                     "(%d,%d,%d,%d,%d)\n",
158                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
159         return false;
160     }
161
162     return m_plugManager->addPlug( *this );
163 }
164
165 bool
166 AvPlug::discoverConnections()
167 {
168     return discoverConnectionsInput() && discoverConnectionsOutput();
169 }
170
171 bool
172 AvPlug::inquireConnnection( AvPlug& plug )
173 {
174     SignalSourceCmd signalSourceCmd = setSrcPlugAddrToSignalCmd();
175     setDestPlugAddrToSignalCmd( signalSourceCmd, plug );
176     signalSourceCmd.setVerbose( m_verboseLevel );
177
178     if ( !signalSourceCmd.fire() ) {
179         debugError( "Could not inquire connection between '%s' and '%s'\n",
180                     getName(), plug.getName() );
181         return false;
182     }
183
184     if ( signalSourceCmd.getResponse() == AVCCommand::eR_Implemented ) {
185         debugOutput( DEBUG_LEVEL_VERBOSE,
186                      "Connection possible between '%s' and '%s'\n",
187                      getName(),  plug.getName() );
188         return true;
189     }
190     debugOutput( DEBUG_LEVEL_VERBOSE,
191                  "Connection not possible between '%s' and '%s'\n",
192                  getName(),  plug.getName() );
193     return false;
194 }
195
196 int
197 AvPlug::getNrOfStreams() const
198 {
199     int nrOfChannels = 0;
200     for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
201           it != m_clusterInfos.end();
202           ++it )
203     {
204         const ClusterInfo* clusterInfo = &( *it );
205         nrOfChannels += clusterInfo->m_nrOfChannels;
206     }
207     return nrOfChannels;
208 }
209
210 int
211 AvPlug::getNrOfChannels() const
212 {
213     return m_nrOfChannels;
214 }
215
216 int
217 AvPlug::getSampleRate() const
218 {
219     return convertESamplingFrequency( static_cast<ESamplingFrequency>( m_samplingFrequency ) );
220 }
221
222 bool
223 AvPlug::discoverPlugType()
224 {
225     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
226     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
227         ExtendedPlugInfoInfoType::eIT_PlugType );
228     extendedPlugInfoInfoType.initialize();
229     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
230     extPlugInfoCmd.setVerbose( m_verboseLevel );
231
232     if ( !extPlugInfoCmd.fire() ) {
233         debugError( "plug type command failed\n" );
234         return false;
235     }
236
237     m_infoPlugType = eAPT_Unknown;
238
239     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Implemented ) {
240
241         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
242         if ( infoType
243              && infoType->m_plugType )
244         {
245             plug_type_t plugType = infoType->m_plugType->m_plugType;
246
247             debugOutput( DEBUG_LEVEL_VERBOSE,
248                          "plug %d is of type %d (%s)\n",
249                          m_id,
250                          plugType,
251                          extendedPlugInfoPlugTypeToString( plugType ) );
252             switch ( plugType ) {
253             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_IsoStream:
254                 m_infoPlugType = eAPT_IsoStream;
255                 break;
256             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_AsyncStream:
257                 m_infoPlugType = eAPT_AsyncStream;
258                 break;
259             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Midi:
260                 m_infoPlugType = eAPT_Midi;
261                 break;
262             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Sync:
263                 m_infoPlugType = eAPT_Sync;
264                 break;
265             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Analog:
266                 m_infoPlugType = eAPT_Analog;
267                 break;
268             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Digital:
269                 m_infoPlugType = eAPT_Digital;
270                 break;
271             default:
272                 m_infoPlugType = eAPT_Unknown;
273
274             }
275         }
276     } else {
277         debugError( "Plug does not implement extended plug info plug "
278                     "type info command\n" );
279         return false;
280     }
281
282    return true;
283 }
284
285 bool
286 AvPlug::discoverName()
287 {
288     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
289     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
290         ExtendedPlugInfoInfoType::eIT_PlugName );
291     extendedPlugInfoInfoType.initialize();
292     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
293     extPlugInfoCmd.setVerbose( m_verboseLevel );
294
295     if ( !extPlugInfoCmd.fire() ) {
296         debugError( "name command failed\n" );
297         return false;
298     }
299
300     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
301     if ( infoType
302          && infoType->m_plugName )
303     {
304         std::string name =
305             infoType->m_plugName->m_name;
306
307         debugOutput( DEBUG_LEVEL_VERBOSE,
308                      "plug %d has name '%s'\n",
309                      m_id,
310                      name.c_str() );
311
312         m_name = name;
313     }
314     return true;
315 }
316
317 bool
318 AvPlug::discoverNoOfChannels()
319 {
320     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
321     //extPlugInfoCmd.setVerbose( true );
322     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
323         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
324     extendedPlugInfoInfoType.initialize();
325     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
326     extPlugInfoCmd.setVerbose( m_verboseLevel );
327
328     if ( !extPlugInfoCmd.fire() ) {
329         debugError( "number of channels command failed\n" );
330         return false;
331     }
332
333     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
334     if ( infoType
335          && infoType->m_plugNrOfChns )
336     {
337         nr_of_channels_t nrOfChannels
338             = infoType->m_plugNrOfChns->m_nrOfChannels;
339
340         debugOutput( DEBUG_LEVEL_VERBOSE,
341                      "plug %d has %d channels\n",
342                      m_id,
343                      nrOfChannels );
344
345         m_nrOfChannels = nrOfChannels;
346     }
347     return true;
348 }
349
350 bool
351 AvPlug::discoverChannelPosition()
352 {
353     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
354     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
355         ExtendedPlugInfoInfoType::eIT_ChannelPosition );
356     extendedPlugInfoInfoType.initialize();
357     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
358     extPlugInfoCmd.setVerbose( m_verboseLevel );
359
360     if ( !extPlugInfoCmd.fire() ) {
361         debugError( "channel position command failed\n" );
362         return false;
363     }
364
365     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
366     if ( infoType
367          && infoType->m_plugChannelPosition )
368     {
369         if ( !copyClusterInfo( *( infoType->m_plugChannelPosition ) ) ) {
370             debugError( "Could not copy channel position "
371                         "information\n" );
372             return false;
373         }
374
375         debugOutput( DEBUG_LEVEL_VERBOSE,
376                      "plug %d: channel position information "
377                      "retrieved\n",
378                      m_id );
379
380         debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
381     }
382
383     return true;
384 }
385
386 bool
387 AvPlug::discoverChannelName()
388 {
389     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
390           clit != m_clusterInfos.end();
391           ++clit )
392     {
393         ClusterInfo* clitInfo = &*clit;
394
395         for ( ChannelInfoVector::iterator pit =  clitInfo->m_channelInfos.begin();
396               pit != clitInfo->m_channelInfos.end();
397               ++pit )
398         {
399             ChannelInfo* channelInfo = &*pit;
400
401             ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
402             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
403                 ExtendedPlugInfoInfoType::eIT_ChannelName );
404             extendedPlugInfoInfoType.initialize();
405             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
406             extPlugInfoCmd.setVerbose( m_verboseLevel );
407
408             ExtendedPlugInfoInfoType* infoType =
409                 extPlugInfoCmd.getInfoType();
410             if ( infoType ) {
411                 infoType->m_plugChannelName->m_streamPosition =
412                     channelInfo->m_streamPosition;
413             }
414             if ( !extPlugInfoCmd.fire() ) {
415                 debugError( "channel name command failed\n" );
416                 return false;
417             }
418             infoType = extPlugInfoCmd.getInfoType();
419             if ( infoType
420                  && infoType->m_plugChannelName )
421             {
422                 debugOutput( DEBUG_LEVEL_VERBOSE,
423                              "plug %d stream "
424                              "position %d: channel name = %s\n",
425                              m_id,
426                              channelInfo->m_streamPosition,
427                              infoType->m_plugChannelName->m_plugChannelName.c_str() );
428                 channelInfo->m_name =
429                     infoType->m_plugChannelName->m_plugChannelName;
430             }
431
432         }
433     }
434
435     return true;
436 }
437
438 bool
439 AvPlug::discoverClusterInfo()
440 {
441     if ( m_infoPlugType == eAPT_Sync )
442     {
443         // If the plug is of type sync it is either a normal 2 channel
444         // stream (not compound stream) or it is a compound stream
445         // with exactly one cluster. This depends on the
446         // extended stream format command version which is used.
447         // We are not interested in this plug so we skip it.
448         debugOutput( DEBUG_LEVEL_VERBOSE,
449                      "%s plug %d is of type sync -> skip\n",
450                      getName(),
451                      m_id );
452         return true;
453     }
454
455     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
456           clit != m_clusterInfos.end();
457           ++clit )
458     {
459         ClusterInfo* clusterInfo = &*clit;
460
461         ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
462         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
463             ExtendedPlugInfoInfoType::eIT_ClusterInfo );
464         extendedPlugInfoInfoType.initialize();
465         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
466         extPlugInfoCmd.setVerbose( m_verboseLevel );
467
468         extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
469             clusterInfo->m_index;
470
471         if ( !extPlugInfoCmd.fire() ) {
472             debugError( "cluster info command failed\n" );
473             return false;
474         }
475
476         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
477         if ( infoType
478              && infoType->m_plugClusterInfo )
479         {
480             debugOutput( DEBUG_LEVEL_VERBOSE,
481                          "%s plug %d: cluster index = %d, "
482                          "portType %s, cluster name = %s\n",
483                          getName(),
484                          m_id,
485                          infoType->m_plugClusterInfo->m_clusterIndex,
486                          extendedPlugInfoClusterInfoPortTypeToString(
487                              infoType->m_plugClusterInfo->m_portType ),
488                          infoType->m_plugClusterInfo->m_clusterName.c_str() );
489
490             clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
491             clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
492         }
493     }
494
495     return true;
496 }
497
498 bool
499 AvPlug::discoverStreamFormat()
500 {
501     ExtendedStreamFormatCmd extStreamFormatCmd =
502         setPlugAddrToStreamFormatCmd( ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand );
503     extStreamFormatCmd.setVerbose( m_verboseLevel );
504
505     if ( !extStreamFormatCmd.fire() ) {
506         debugError( "stream format command failed\n" );
507         return false;
508     }
509
510     if ( ( extStreamFormatCmd.getStatus() ==  ExtendedStreamFormatCmd::eS_NoStreamFormat )
511          || ( extStreamFormatCmd.getStatus() ==  ExtendedStreamFormatCmd::eS_NotUsed ) )
512     {
513         debugOutput( DEBUG_LEVEL_VERBOSE,
514                      "No stream format information available\n" );
515         return true;
516     }
517
518     if ( !extStreamFormatCmd.getFormatInformation() ) {
519         debugWarning( "No stream format information for plug found -> skip\n" );
520         return true;
521     }
522
523     if ( extStreamFormatCmd.getFormatInformation()->m_root
524            != FormatInformation::eFHR_AudioMusic  )
525     {
526         debugWarning( "Format hierarchy root is not Audio&Music -> skip\n" );
527         return true;
528     }
529
530     FormatInformation* formatInfo =
531         extStreamFormatCmd.getFormatInformation();
532     FormatInformationStreamsCompound* compoundStream
533         = dynamic_cast< FormatInformationStreamsCompound* > (
534             formatInfo->m_streams );
535     if ( compoundStream ) {
536         m_samplingFrequency =
537             compoundStream->m_samplingFrequency;
538         debugOutput( DEBUG_LEVEL_VERBOSE,
539                      "%s plug %d uses "
540                      "sampling frequency %d, nr of stream infos = %d\n",
541                      getName(),
542                      m_id,
543                      m_samplingFrequency,
544                      compoundStream->m_numberOfStreamFormatInfos );
545
546         for ( int i = 1;
547               i <= compoundStream->m_numberOfStreamFormatInfos;
548               ++i )
549         {
550             ClusterInfo* clusterInfo =
551                 const_cast<ClusterInfo*>( getClusterInfoByIndex( i ) );
552
553             if ( !clusterInfo ) {
554                 debugError( "No matching cluster "
555                             "info found for index %d\n",  i );
556                     return false;
557             }
558             StreamFormatInfo* streamFormatInfo =
559                 compoundStream->m_streamFormatInfos[ i - 1 ];
560
561             debugOutput( DEBUG_LEVEL_VERBOSE,
562                          "number of channels = %d, stream format = %d\n",
563                          streamFormatInfo->m_numberOfChannels,
564                          streamFormatInfo->m_streamFormat );
565
566             int nrOfChannels = clusterInfo->m_nrOfChannels;
567             if ( streamFormatInfo->m_streamFormat ==
568                  FormatInformation::eFHL2_AM824_MIDI_CONFORMANT )
569             {
570                 // 8 logical midi channels fit into 1 channel
571                 nrOfChannels = ( ( nrOfChannels + 7 ) / 8 );
572             }
573             // sanity check
574             if ( nrOfChannels != streamFormatInfo->m_numberOfChannels )
575             {
576                 debugWarning( "Number of channels "
577                               "mismatch: '%s' plug discovering reported "
578                               "%d channels for cluster '%s', while stream "
579                               "format reported %d\n",
580                               getName(),
581                               nrOfChannels,
582                               clusterInfo->m_name.c_str(),
583                               streamFormatInfo->m_numberOfChannels);
584             }
585             clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat;
586
587             debugOutput( DEBUG_LEVEL_VERBOSE,
588                          "%s plug %d cluster info %d ('%s'): "
589                          "stream format %d\n",
590                          getName(),
591                          m_id,
592                          i,
593                          clusterInfo->m_name.c_str(),
594                          clusterInfo->m_streamFormat );
595         }
596     }
597
598     FormatInformationStreamsSync* syncStream
599         = dynamic_cast< FormatInformationStreamsSync* > (
600             formatInfo->m_streams );
601     if ( syncStream ) {
602         m_samplingFrequency =
603             syncStream->m_samplingFrequency;
604         debugOutput( DEBUG_LEVEL_VERBOSE,
605                      "%s plug %d is sync stream with sampling frequency %d\n",
606                      getName(),
607                      m_id,
608                      m_samplingFrequency );
609     }
610
611
612     if ( !compoundStream && !syncStream )
613     {
614         debugError( "Unsupported stream format\n" );
615         return false;
616     }
617
618     return true;
619 }
620
621 bool
622 AvPlug::discoverSupportedStreamFormats()
623 {
624     ExtendedStreamFormatCmd extStreamFormatCmd =
625         setPlugAddrToStreamFormatCmd(
626             ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList);
627     extStreamFormatCmd.setVerbose( m_verboseLevel );
628
629     int i = 0;
630     bool cmdSuccess = false;
631
632     do {
633         extStreamFormatCmd.setIndexInStreamFormat( i );
634         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
635         cmdSuccess = extStreamFormatCmd.fire();
636         if ( cmdSuccess
637              && ( extStreamFormatCmd.getResponse()
638                   == AVCCommand::eR_Implemented ) )
639         {
640             FormatInfo formatInfo;
641             formatInfo.m_index = i;
642             bool formatInfoIsValid = true;
643
644             FormatInformationStreamsSync* syncStream
645                 = dynamic_cast< FormatInformationStreamsSync* >
646                 ( extStreamFormatCmd.getFormatInformation()->m_streams );
647             if ( syncStream ) {
648                 formatInfo.m_samplingFrequency =
649                     syncStream->m_samplingFrequency;
650                 formatInfo.m_isSyncStream = true ;
651             }
652
653             FormatInformationStreamsCompound* compoundStream
654                 = dynamic_cast< FormatInformationStreamsCompound* >
655                 ( extStreamFormatCmd.getFormatInformation()->m_streams );
656             if ( compoundStream ) {
657                 formatInfo.m_samplingFrequency =
658                     compoundStream->m_samplingFrequency;
659                 formatInfo.m_isSyncStream = false;
660                 for ( int j = 0;
661                       j < compoundStream->m_numberOfStreamFormatInfos;
662                       ++j )
663                 {
664                     switch ( compoundStream->m_streamFormatInfos[j]->m_streamFormat ) {
665                     case AVC1394_STREAM_FORMAT_AM824_IEC60968_3:
666                         formatInfo.m_audioChannels +=
667                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
668                         break;
669                     case AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_RAW:
670                         formatInfo.m_audioChannels +=
671                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
672                         break;
673                     case AVC1394_STREAM_FORMAT_AM824_MIDI_CONFORMANT:
674                         formatInfo.m_midiChannels +=
675                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
676                         break;
677                     default:
678                         formatInfoIsValid = false;
679                         debugWarning("unknown stream format (0x%02x) for channel "
680                                       "(%d)\n",
681                                      compoundStream->m_streamFormatInfos[j]->m_streamFormat,
682                                      j );
683                     }
684                 }
685             }
686
687             if ( formatInfoIsValid ) {
688                 debugOutput( DEBUG_LEVEL_VERBOSE,
689                              "[%s:%d] formatInfo[%d].m_samplingFrequency "
690                              "= %d\n",
691                              getName(), m_id,
692                              i, formatInfo.m_samplingFrequency );
693                 debugOutput( DEBUG_LEVEL_VERBOSE,
694                              "[%s:%d] formatInfo[%d].m_isSyncStream = %d\n",
695                              getName(), m_id,
696                              i, formatInfo.m_isSyncStream );
697                 debugOutput( DEBUG_LEVEL_VERBOSE,
698                              "[%s:%d] formatInfo[%d].m_audioChannels = %d\n",
699                              getName(), m_id,
700                              i, formatInfo.m_audioChannels );
701                 debugOutput( DEBUG_LEVEL_VERBOSE,
702                              "[%s:%d] formatInfo[%d].m_midiChannels = %d\n",
703                              getName(), m_id,
704                              i, formatInfo.m_midiChannels );
705                 m_formatInfos.push_back( formatInfo );
706             }
707         }
708
709         ++i;
710     } while ( cmdSuccess && ( extStreamFormatCmd.getResponse()
711                               == ExtendedStreamFormatCmd::eR_Implemented ) );
712
713     return true;
714 }
715
716
717 bool
718 AvPlug::discoverConnectionsInput()
719 {
720     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
721     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
722         ExtendedPlugInfoInfoType::eIT_PlugInput );
723     extendedPlugInfoInfoType.initialize();
724     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
725     extPlugInfoCmd.setVerbose( m_verboseLevel );
726
727     if ( !extPlugInfoCmd.fire() ) {
728         debugError( "plug type command failed\n" );
729         return false;
730     }
731
732     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
733         // Plugs does not like to be asked about connections
734         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
735                      "connections command\n",
736                      getName() );
737         return true;
738     }
739
740     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
741     if ( infoType
742          && infoType->m_plugInput )
743     {
744         PlugAddressSpecificData* plugAddress
745             = infoType->m_plugInput->m_plugAddress;
746
747         if ( plugAddress->m_addressMode ==
748              PlugAddressSpecificData::ePAM_Undefined )
749         {
750             // This plug has no input connection
751             return true;
752         }
753
754         if ( !discoverConnectionsFromSpecificData( eAPD_Input,
755                                                    plugAddress,
756                                                    m_inputConnections ) )
757         {
758             debugWarning( "Could not discover connnections for plug '%s'\n",
759                           getName() );
760         }
761     } else {
762         debugError( "no valid info type for plug '%s'\n", getName() );
763         return false;
764     }
765
766     return true;
767 }
768
769 bool
770 AvPlug::discoverConnectionsOutput()
771 {
772     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
773     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
774         ExtendedPlugInfoInfoType::eIT_PlugOutput );
775     extendedPlugInfoInfoType.initialize();
776     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
777     extPlugInfoCmd.setVerbose( m_verboseLevel );
778
779     if ( !extPlugInfoCmd.fire() ) {
780         debugError( "plug type command failed\n" );
781         return false;
782     }
783
784     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
785         // Plugs does not like to be asked about connections
786         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
787                      "connections command\n",
788                      getName() );
789         return true;
790     }
791
792     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
793     if ( infoType
794          && infoType->m_plugOutput )
795     {
796         if ( infoType->m_plugOutput->m_nrOfOutputPlugs
797              != infoType->m_plugOutput->m_outputPlugAddresses.size() )
798         {
799             debugError( "number of output plugs (%d) disagree with "
800                         "number of elements in plug address vector (%d)\n",
801                         infoType->m_plugOutput->m_nrOfOutputPlugs,
802                         infoType->m_plugOutput->m_outputPlugAddresses.size());
803         }
804
805         if ( infoType->m_plugOutput->m_nrOfOutputPlugs == 0 ) {
806             // This plug has no output connections
807             return true;
808         }
809
810         for ( unsigned int i = 0;
811               i < infoType->m_plugOutput->m_outputPlugAddresses.size();
812               ++i )
813         {
814             PlugAddressSpecificData* plugAddress
815                 = infoType->m_plugOutput->m_outputPlugAddresses[i];
816
817             if ( !discoverConnectionsFromSpecificData( eAPD_Output,
818                                                        plugAddress,
819                                                        m_outputConnections ) )
820             {
821                 debugWarning( "Could not discover connnections for "
822                               "plug '%s'\n", getName() );
823             }
824         }
825     } else {
826         debugError( "no valid info type for plug '%s'\n", getName() );
827         return false;
828     }
829
830     return true;
831 }
832
833 bool
834 AvPlug::discoverConnectionsFromSpecificData(
835     EAvPlugDirection discoverDirection,
836     PlugAddressSpecificData* plugAddress,
837     AvPlugVector& connections )
838 {
839     UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
840         dynamic_cast<UnitPlugSpecificDataPlugAddress*>
841         ( plugAddress->m_plugAddressData );
842
843     SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
844         dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
845         ( plugAddress->m_plugAddressData );
846
847     FunctionBlockPlugSpecificDataPlugAddress*
848         pFunctionBlockPlugAddress =
849         dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
850         ( plugAddress->m_plugAddressData );
851
852     AvPlug* plug = getPlugDefinedBySpecificData(
853         pUnitPlugAddress,
854         pSubunitPlugAddress,
855         pFunctionBlockPlugAddress );
856
857     if ( plug ) {
858         debugOutput( DEBUG_LEVEL_NORMAL,
859                      "'(%d) %s' has a connection to '(%d) %s'\n",
860                      getGlobalId(),
861                      getName(),
862                      plug->getGlobalId(),
863                      plug->getName() );
864         addPlugConnection( connections, *plug );
865     } else {
866         debugError( "no corresponding plug found for '(%d) %s'\n",
867                     getGlobalId(),
868                     getName() );
869         return false;
870     }
871
872     return true;
873 }
874
875 bool
876 AvPlug::addPlugConnection( AvPlugVector& connections,
877                            AvPlug& plug )
878
879 {
880     for ( AvPlugVector::iterator it = connections.begin();
881           it != connections.end();
882           ++it )
883     {
884         AvPlug* cPlug = *it;
885         if ( cPlug == &plug ) {
886             debugOutput( DEBUG_LEVEL_VERBOSE,
887                          "plug '%s' already in connection list\n",
888                          plug.getName() );
889             return true;
890         }
891     }
892
893     connections.push_back( &plug );
894     return true;
895 }
896
897 ExtendedPlugInfoCmd
898 AvPlug::setPlugAddrToPlugInfoCmd()
899 {
900     ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
901
902     switch( m_subunitType ) {
903     case AVCCommand::eST_Unit:
904         {
905             UnitPlugAddress::EPlugType ePlugType =
906                 UnitPlugAddress::ePT_Unknown;
907             switch ( m_addressType ) {
908                 case eAPA_PCR:
909                     ePlugType = UnitPlugAddress::ePT_PCR;
910                     break;
911                 case eAPA_ExternalPlug:
912                     ePlugType = UnitPlugAddress::ePT_ExternalPlug;
913                     break;
914                 case eAPA_AsynchronousPlug:
915                     ePlugType = UnitPlugAddress::ePT_AsynchronousPlug;
916                     break;
917                 default:
918                     ePlugType = UnitPlugAddress::ePT_Unknown;
919             }
920             UnitPlugAddress unitPlugAddress( ePlugType,
921                                              m_id );
922             extPlugInfoCmd.setPlugAddress(
923                 PlugAddress( convertPlugDirection( getPlugDirection() ),
924                              PlugAddress::ePAM_Unit,
925                              unitPlugAddress ) );
926         }
927         break;
928     case AVCCommand::eST_Music:
929     case AVCCommand::eST_Audio:
930         {
931             switch( m_addressType ) {
932             case eAPA_SubunitPlug:
933             {
934                 SubunitPlugAddress subunitPlugAddress( m_id );
935                 extPlugInfoCmd.setPlugAddress(
936                     PlugAddress(
937                         convertPlugDirection( getPlugDirection() ),
938                         PlugAddress::ePAM_Subunit,
939                         subunitPlugAddress ) );
940             }
941             break;
942             case eAPA_FunctionBlockPlug:
943             {
944                 FunctionBlockPlugAddress functionBlockPlugAddress(
945                     m_functionBlockType,
946                     m_functionBlockId,
947                     m_id );
948                 extPlugInfoCmd.setPlugAddress(
949                     PlugAddress(
950                         convertPlugDirection( getPlugDirection() ),
951                         PlugAddress::ePAM_FunctionBlock,
952                         functionBlockPlugAddress ) );
953             }
954             break;
955             default:
956                 extPlugInfoCmd.setPlugAddress(PlugAddress());
957             }
958         }
959         break;
960     default:
961         debugError( "Unknown subunit type\n" );
962     }
963
964     extPlugInfoCmd.setNodeId( m_nodeId );
965     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
966     extPlugInfoCmd.setSubunitId( m_subunitId );
967     extPlugInfoCmd.setSubunitType( m_subunitType );
968
969     return extPlugInfoCmd;
970 }
971
972 ExtendedStreamFormatCmd
973 AvPlug::setPlugAddrToStreamFormatCmd(
974     ExtendedStreamFormatCmd::ESubFunction subFunction)
975 {
976     ExtendedStreamFormatCmd extStreamFormatInfoCmd(
977         m_1394Service,
978         subFunction );
979     switch( m_subunitType ) {
980     case AVCCommand::eST_Unit:
981     {
982             UnitPlugAddress::EPlugType ePlugType =
983                 UnitPlugAddress::ePT_Unknown;
984             switch ( m_addressType ) {
985                 case eAPA_PCR:
986                     ePlugType = UnitPlugAddress::ePT_PCR;
987                     break;
988                 case eAPA_ExternalPlug:
989                     ePlugType = UnitPlugAddress::ePT_ExternalPlug;
990                     break;
991                 case eAPA_AsynchronousPlug:
992                     ePlugType = UnitPlugAddress::ePT_AsynchronousPlug;
993                     break;
994                 default:
995                     ePlugType = UnitPlugAddress::ePT_Unknown;
996             }
997         UnitPlugAddress unitPlugAddress( ePlugType,
998                                          m_id );
999         extStreamFormatInfoCmd.setPlugAddress(
1000             PlugAddress( convertPlugDirection( getPlugDirection() ),
1001                          PlugAddress::ePAM_Unit,
1002                          unitPlugAddress ) );
1003         }
1004         break;
1005     case AVCCommand::eST_Music:
1006     case AVCCommand::eST_Audio:
1007     {
1008         switch( m_addressType ) {
1009         case eAPA_SubunitPlug:
1010         {
1011             SubunitPlugAddress subunitPlugAddress( m_id );
1012             extStreamFormatInfoCmd.setPlugAddress(
1013                 PlugAddress( convertPlugDirection( getPlugDirection() ),
1014                              PlugAddress::ePAM_Subunit,
1015                              subunitPlugAddress ) );
1016         }
1017         break;
1018         case eAPA_FunctionBlockPlug:
1019         {
1020             FunctionBlockPlugAddress functionBlockPlugAddress(
1021                 m_functionBlockType,
1022                 m_functionBlockId,
1023                 m_id );
1024             extStreamFormatInfoCmd.setPlugAddress(
1025                 PlugAddress( convertPlugDirection( getPlugDirection() ),
1026                              PlugAddress::ePAM_FunctionBlock,
1027                              functionBlockPlugAddress ) );
1028         }
1029         break;
1030         default:
1031             extStreamFormatInfoCmd.setPlugAddress(PlugAddress());
1032         }
1033     }
1034     break;
1035     default:
1036         debugError( "Unknown subunit type\n" );
1037     }
1038
1039     extStreamFormatInfoCmd.setNodeId( m_nodeId );
1040     extStreamFormatInfoCmd.setCommandType( AVCCommand::eCT_Status );
1041     extStreamFormatInfoCmd.setSubunitId( m_subunitId );
1042     extStreamFormatInfoCmd.setSubunitType( m_subunitType );
1043
1044     return extStreamFormatInfoCmd;
1045 }
1046
1047 SignalSourceCmd
1048 AvPlug::setSrcPlugAddrToSignalCmd()
1049 {
1050     SignalSourceCmd signalSourceCmd( m_1394Service );
1051
1052     switch( m_subunitType ) {
1053     case AVCCommand::eST_Unit:
1054     {
1055         SignalUnitAddress signalUnitAddr;
1056         if ( getPlugAddressType() == eAPA_ExternalPlug ) {
1057             signalUnitAddr.m_plugId = m_id + 0x80;
1058         } else {
1059             signalUnitAddr.m_plugId = m_id;
1060         }
1061         signalSourceCmd.setSignalSource( signalUnitAddr );
1062     }
1063     break;
1064     case AVCCommand::eST_Music:
1065     case AVCCommand::eST_Audio:
1066     {
1067         SignalSubunitAddress signalSubunitAddr;
1068         signalSubunitAddr.m_subunitType = m_subunitType;
1069         signalSubunitAddr.m_subunitId = m_subunitId;
1070         signalSubunitAddr.m_plugId = m_id;
1071         signalSourceCmd.setSignalSource( signalSubunitAddr );
1072     }
1073     break;
1074     default:
1075         debugError( "Unknown subunit type\n" );
1076     }
1077
1078     signalSourceCmd.setNodeId( m_nodeId );
1079     signalSourceCmd.setCommandType( AVCCommand::eCT_SpecificInquiry );
1080     signalSourceCmd.setSubunitType( AVCCommand::eST_Unit  );
1081     signalSourceCmd.setSubunitId( 0xff );
1082
1083     return signalSourceCmd;
1084 }
1085
1086 void
1087 AvPlug::setDestPlugAddrToSignalCmd(SignalSourceCmd& signalSourceCmd,
1088                                    AvPlug& plug)
1089 {
1090     switch( plug.m_subunitType ) {
1091     case AVCCommand::eST_Unit:
1092     {
1093         SignalUnitAddress signalUnitAddr;
1094         if ( plug.getPlugAddressType() == eAPA_ExternalPlug ) {
1095             signalUnitAddr.m_plugId = plug.m_id + 0x80;
1096         } else {
1097             signalUnitAddr.m_plugId = plug.m_id;
1098         }
1099         signalSourceCmd.setSignalDestination( signalUnitAddr );
1100     }
1101     break;
1102     case AVCCommand::eST_Music:
1103     case AVCCommand::eST_Audio:
1104     {
1105         SignalSubunitAddress signalSubunitAddr;
1106         signalSubunitAddr.m_subunitType = plug.m_subunitType;
1107         signalSubunitAddr.m_subunitId = plug.m_subunitId;
1108         signalSubunitAddr.m_plugId = plug.m_id;
1109         signalSourceCmd.setSignalDestination( signalSubunitAddr );
1110     }
1111     break;
1112     default:
1113         debugError( "Unknown subunit type\n" );
1114     }
1115 }
1116
1117
1118 bool
1119 AvPlug::copyClusterInfo(ExtendedPlugInfoPlugChannelPositionSpecificData&
1120                         channelPositionData )
1121 {
1122     int index = 1;
1123     for ( ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfoVector::const_iterator it
1124               = channelPositionData.m_clusterInfos.begin();
1125           it != channelPositionData.m_clusterInfos.end();
1126           ++it )
1127     {
1128         const ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfo*
1129             extPlugSpClusterInfo = &( *it );
1130
1131         ClusterInfo clusterInfo;
1132         clusterInfo.m_nrOfChannels = extPlugSpClusterInfo->m_nrOfChannels;
1133         clusterInfo.m_index = index;
1134         index++;
1135
1136         for (  ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfoVector::const_iterator cit
1137                   = extPlugSpClusterInfo->m_channelInfos.begin();
1138               cit != extPlugSpClusterInfo->m_channelInfos.end();
1139               ++cit )
1140         {
1141             const ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfo*
1142                 extPlugSpChannelInfo = &( *cit );
1143
1144             ChannelInfo channelInfo;
1145             channelInfo.m_streamPosition =
1146                 extPlugSpChannelInfo->m_streamPosition;
1147             channelInfo.m_location =
1148                 extPlugSpChannelInfo->m_location;
1149
1150             clusterInfo.m_channelInfos.push_back( channelInfo );
1151         }
1152         m_clusterInfos.push_back( clusterInfo );
1153     }
1154
1155     return true;
1156 }
1157
1158 void
1159 AvPlug::debugOutputClusterInfos( int debugLevel )
1160 {
1161     for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
1162           it != m_clusterInfos.end();
1163           ++it )
1164     {
1165         const ClusterInfo* clusterInfo = &( *it );
1166
1167         debugOutput( debugLevel, "number of channels: %d\n",
1168                      clusterInfo->m_nrOfChannels );
1169
1170         for ( ChannelInfoVector::const_iterator cit
1171                   = clusterInfo->m_channelInfos.begin();
1172               cit != clusterInfo->m_channelInfos.end();
1173               ++cit )
1174         {
1175             const ChannelInfo* channelInfo = &( *cit );
1176             channelInfo = channelInfo;
1177             debugOutput( debugLevel,
1178                          "stream position: %d\n",
1179                          channelInfo->m_streamPosition );
1180             debugOutput( debugLevel,
1181                          "location: %d\n",
1182                          channelInfo->m_location );
1183         }
1184     }
1185 }
1186
1187 const AvPlug::ClusterInfo*
1188 AvPlug::getClusterInfoByIndex(int index) const
1189 {
1190     for ( AvPlug::ClusterInfoVector::const_iterator clit =
1191               m_clusterInfos.begin();
1192           clit != m_clusterInfos.end();
1193           ++clit )
1194     {
1195         const ClusterInfo* info = &*clit;
1196         if ( info->m_index == index ) {
1197             return info;
1198         }
1199     }
1200     return 0;
1201 }
1202
1203 PlugAddress::EPlugDirection
1204 AvPlug::convertPlugDirection( EAvPlugDirection direction )
1205 {
1206     PlugAddress::EPlugDirection dir;
1207     switch ( direction ) {
1208     case AvPlug::eAPD_Input:
1209         dir = PlugAddress::ePD_Input;
1210         break;
1211     case AvPlug::eAPD_Output:
1212         dir = PlugAddress::ePD_Output;
1213         break;
1214     default:
1215         dir = PlugAddress::ePD_Undefined;
1216     }
1217     return dir;
1218 }
1219
1220 void
1221 AvPlug::showPlug() const
1222 {
1223     debugOutput( DEBUG_LEVEL_VERBOSE, "\tName               = %s\n",
1224                  getName() );
1225     debugOutput( DEBUG_LEVEL_VERBOSE, "\tType               = %s\n",
1226                  extendedPlugInfoPlugTypeToString( getPlugType() ) );
1227     debugOutput( DEBUG_LEVEL_VERBOSE, "\tAddress Type       = %s\n",
1228                  avPlugAddressTypeToString( getPlugAddressType() ) );
1229     debugOutput( DEBUG_LEVEL_VERBOSE, "\tId                 = %d\n",
1230                  getPlugId() );
1231     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitType        = %d\n",
1232                  getSubunitType() );
1233     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitId          = %d\n",
1234                  getSubunitId() );
1235     debugOutput( DEBUG_LEVEL_VERBOSE, "\tDirection          = %s\n",
1236                  avPlugDirectionToString( getPlugDirection() ) );
1237     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSampling Rate      = %d\n",
1238                  getSampleRate() );
1239     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Channels = %d\n",
1240                  getNrOfChannels() );
1241     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Streams  = %d\n",
1242                  getNrOfStreams() );
1243 }
1244
1245
1246 AvPlug*
1247 AvPlug::getPlugDefinedBySpecificData(
1248     UnitPlugSpecificDataPlugAddress* pUnitPlugAddress,
1249     SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress,
1250     FunctionBlockPlugSpecificDataPlugAddress* pFunctionBlockPlugAddress )
1251 {
1252     subunit_type_t        subunitType       = 0xff;
1253     subunit_id_t          subunitId         = 0xff;
1254     function_block_type_t functionBlockType = 0xff;
1255     function_block_id_t   functionBlockId   = 0xff;
1256     EAvPlugAddressType    addressType       = eAPA_Undefined;
1257     EAvPlugDirection      direction         = eAPD_Unknown;
1258     plug_id_t             plugId            = 0xff;
1259
1260     if ( !pUnitPlugAddress
1261          && !pSubunitPlugAddress
1262          && !pFunctionBlockPlugAddress )
1263     {
1264         debugError( "No correct specific data found\n" );
1265         return 0;
1266     }
1267
1268     if ( pUnitPlugAddress ) {
1269         subunitType = AVCCommand::eST_Unit;
1270         switch ( pUnitPlugAddress->m_plugType ) {
1271         case UnitPlugSpecificDataPlugAddress::ePT_PCR:
1272             addressType = eAPA_PCR;
1273             break;
1274         case UnitPlugSpecificDataPlugAddress::ePT_ExternalPlug:
1275             addressType = eAPA_ExternalPlug;
1276             break;
1277         case UnitPlugSpecificDataPlugAddress::ePT_AsynchronousPlug:
1278             addressType = eAPA_AsynchronousPlug;
1279             break;
1280         }
1281         // unit plug have only connections to subunits
1282         if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1283             direction = getDirection();
1284         } else {
1285             debugError( "Function block has connection from/to unknown "
1286                         "plug type\n" );
1287             direction = eAPD_Unknown;
1288         }
1289         plugId = pUnitPlugAddress->m_plugId;
1290
1291         debugOutput( DEBUG_LEVEL_NORMAL,
1292                      "'(%d) %s': Remote plug is a unit plug "
1293                      "(%s, %s, %d)\n",
1294                      getGlobalId(),
1295                      getName(),
1296                      avPlugAddressTypeToString( addressType ),
1297                      avPlugDirectionToString( direction ),
1298                      plugId );
1299     }
1300
1301     if ( pSubunitPlugAddress ) {
1302         subunitType = pSubunitPlugAddress->m_subunitType;
1303         subunitId = pSubunitPlugAddress->m_subunitId;
1304         addressType = eAPA_SubunitPlug;
1305
1306         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1307             direction = getDirection();
1308         } else if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1309             direction = toggleDirection( getDirection() );
1310         } else {
1311             // unit
1312             direction = getDirection();
1313         }
1314
1315         plugId = pSubunitPlugAddress->m_plugId;
1316         debugOutput( DEBUG_LEVEL_VERBOSE,
1317                      "'(%d) %s': Remote plug is a subunit plug "
1318                      "(%d, %d, %s, %d)\n",
1319                      getGlobalId(),
1320                      getName(),
1321                      subunitType,
1322                      subunitId,
1323                      avPlugDirectionToString( direction ),
1324                      plugId );
1325     }
1326
1327     if ( pFunctionBlockPlugAddress ) {
1328         subunitType = pFunctionBlockPlugAddress->m_subunitType;
1329         subunitId = pFunctionBlockPlugAddress->m_subunitId;
1330         functionBlockType = pFunctionBlockPlugAddress->m_functionBlockType;
1331         functionBlockId = pFunctionBlockPlugAddress->m_functionBlockId;
1332         addressType = eAPA_FunctionBlockPlug;
1333
1334         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1335             direction = toggleDirection( getDirection() );
1336         } else if ( getPlugAddressType() == eAPA_SubunitPlug ){
1337             direction = getDirection();
1338         } else {
1339             debugError( "Function block has connection from/to unknown "
1340                         "plug type\n" );
1341             direction = eAPD_Unknown;
1342         }
1343
1344         plugId = pFunctionBlockPlugAddress->m_plugId;
1345
1346         debugOutput( DEBUG_LEVEL_VERBOSE,
1347                      "'(%d) %s': Remote plug is a functionblock plug "
1348                      "(%d, %d, %d, %d, %s, %d)\n",
1349                      getGlobalId(),
1350                      getName(),
1351                      subunitType,
1352                      subunitId,
1353                      functionBlockType,
1354                      functionBlockId,
1355                      avPlugDirectionToString( direction ),
1356                      plugId );
1357     }
1358
1359     AVCCommand::ESubunitType enumSubunitType =
1360         static_cast<AVCCommand::ESubunitType>( subunitType );
1361
1362     return m_plugManager->getPlug(
1363         enumSubunitType,
1364         subunitId,
1365         functionBlockType,
1366         functionBlockId,
1367         addressType,
1368         direction,
1369         plugId );
1370 }
1371
1372 AvPlug::EAvPlugDirection
1373 AvPlug::toggleDirection( EAvPlugDirection direction ) const
1374 {
1375     EAvPlugDirection newDirection;
1376     switch ( direction ) {
1377     case eAPD_Output:
1378         newDirection = eAPD_Input;
1379         break;
1380     case eAPD_Input:
1381         newDirection = eAPD_Output;
1382         break;
1383     default:
1384         newDirection = direction;
1385     }
1386
1387     return newDirection;
1388 }
1389
1390 /////////////////////////////////////////
1391 /////////////////////////////////////////
1392
1393 const char* avPlugAddressTypeStrings[] =
1394 {
1395     "PCR",
1396     "external",
1397     "asynchronous",
1398     "subunit",
1399     "functionblock",
1400     "undefined",
1401 };
1402
1403 const char* avPlugAddressTypeToString( AvPlug::EAvPlugAddressType type )
1404 {
1405     if ( type > ( int )( sizeof( avPlugAddressTypeStrings )
1406                          / sizeof( avPlugAddressTypeStrings[0] ) ) )
1407     {
1408         type = AvPlug::eAPA_Undefined;
1409     }
1410     return avPlugAddressTypeStrings[type];
1411 }
1412
1413 const char* avPlugTypeStrings[] =
1414 {
1415     "IsoStream",
1416     "AsyncStream",
1417     "MIDI",
1418     "Sync",
1419     "Analog",
1420     "Digital",
1421     "Unknown",
1422 };
1423
1424 const char* avPlugTypeToString( AvPlug::EAvPlugType type )
1425 {
1426     if ( type > ( int )( sizeof( avPlugTypeStrings )
1427                          / sizeof( avPlugTypeStrings[0] ) ) )
1428     {
1429         type = AvPlug::eAPT_Unknown;
1430     }
1431     return avPlugTypeStrings[type];
1432 }
1433
1434 const char* avPlugDirectionStrings[] =
1435 {
1436     "Input",
1437     "Output",
1438     "Unknown",
1439 };
1440
1441 const char* avPlugDirectionToString( AvPlug::EAvPlugDirection type )
1442 {
1443     if ( type > ( int )( sizeof( avPlugDirectionStrings )
1444                          / sizeof( avPlugDirectionStrings[0] ) ) )
1445     {
1446         type = AvPlug::eAPD_Unknown;
1447     }
1448     return avPlugDirectionStrings[type];
1449 }
1450
1451 /////////////////////////////////////
1452
1453
1454 AvPlugManager::AvPlugManager( int verboseLevel )
1455     : m_verboseLevel( verboseLevel )
1456 {
1457     if ( m_verboseLevel ) {
1458         setDebugLevel( DEBUG_LEVEL_VERBOSE );
1459     }
1460 }
1461
1462 AvPlugManager::AvPlugManager( const AvPlugManager& rhs )
1463     : m_verboseLevel( rhs.m_verboseLevel )
1464 {
1465     if ( m_verboseLevel ) {
1466         setDebugLevel( DEBUG_LEVEL_VERBOSE );
1467     }
1468 }
1469
1470 AvPlugManager::~AvPlugManager()
1471 {
1472 }
1473
1474 bool
1475 AvPlugManager::addPlug( AvPlug& plug )
1476 {
1477     m_plugs.push_back( &plug );
1478     return true;
1479 }
1480
1481 bool
1482 AvPlugManager::remPlug( AvPlug& plug )
1483 {
1484     for ( AvPlugVector::iterator it = m_plugs.begin();
1485           it !=  m_plugs.end();
1486           ++it )
1487     {
1488         AvPlug* plugIt = *it;
1489         if ( plugIt == &plug ) {
1490             m_plugs.erase( it );
1491             return true;
1492         }
1493     }
1494     return false;
1495 }
1496
1497 // helper function
1498 static void addConnection( AvPlugConnectionOwnerVector& connections,
1499                            AvPlug& srcPlug,
1500                            AvPlug& destPlug )
1501 {
1502     for ( AvPlugConnectionOwnerVector::iterator it = connections.begin();
1503           it != connections.end();
1504           ++it )
1505     {
1506         AvPlugConnection& con = *it;
1507         if ( ( &( con.getSrcPlug() ) == &srcPlug )
1508              && ( &( con.getDestPlug() ) == &destPlug ) )
1509         {
1510             return;
1511         }
1512     }
1513     connections.push_back( AvPlugConnection( srcPlug, destPlug ) );
1514 }
1515
1516 void
1517 AvPlugManager::showPlugs() const
1518 {
1519     // \todo The information provided here could be better arranged. For a start it is ok, but
1520     // there is room for improvement. Something for a lazy sunday afternoon (tip: maybe drink some
1521     // beer to get into the mood)
1522
1523     printf( "\nSummary\n" );
1524     printf( "-------\n\n" );
1525     printf( "Nr | AddressType     | Direction | SubUnitType | SubUnitId | FunctionBlockType | FunctionBlockId | Id   | Type         |Name\n" );
1526     printf( "---+-----------------+-----------+-------------+-----------+-------------------+-----------------+------+--------------+------\n" );
1527
1528     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1529           it !=  m_plugs.end();
1530           ++it )
1531     {
1532         AvPlug* plug = *it;
1533
1534         printf( "%2d | %15s | %9s | %11s |      0x%02x |              0x%02x |            0x%02x | 0x%02x | %12s | %s\n",
1535                 plug->getGlobalId(),
1536                 avPlugAddressTypeToString( plug->getPlugAddressType() ),
1537                 avPlugDirectionToString( plug->getDirection() ),
1538                 subunitTypeToString( plug->getSubunitType() ),
1539                 plug->getSubunitId(),
1540                 plug->getFunctionBlockType(),
1541                 plug->getFunctionBlockId(),
1542                 plug->getPlugId(),
1543                 avPlugTypeToString( plug->getPlugType() ),
1544                 plug->getName() );
1545     }
1546
1547     printf( "\nConnections\n" );
1548     printf( "-----------\n" );
1549
1550     AvPlugConnectionOwnerVector connections;
1551
1552     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1553           it !=  m_plugs.end();
1554           ++it )
1555     {
1556         AvPlug* plug = *it;
1557         for ( AvPlugVector::const_iterator it =
1558                   plug->getInputConnections().begin();
1559             it != plug->getInputConnections().end();
1560             ++it )
1561         {
1562             addConnection( connections, *( *it ), *plug );
1563         }
1564         for ( AvPlugVector::const_iterator it =
1565                   plug->getOutputConnections().begin();
1566             it != plug->getOutputConnections().end();
1567             ++it )
1568         {
1569             addConnection( connections, *plug, *( *it ) );
1570         }
1571     }
1572
1573     printf( "digraph avcconnections {\n" );
1574     for ( AvPlugConnectionOwnerVector::iterator it = connections.begin();
1575           it != connections.end();
1576           ++it )
1577     {
1578         AvPlugConnection& con = *it;
1579         printf( "\t\"(%d) %s\" -> \"(%d) %s\"\n",
1580                 con.getSrcPlug().getGlobalId(),
1581                 con.getSrcPlug().getName(),
1582                 con.getDestPlug().getGlobalId(),
1583                 con.getDestPlug().getName() );
1584     }
1585     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1586           it != m_plugs.end();
1587           ++it )
1588     {
1589         AvPlug* plug = *it;
1590         if ( plug->getFunctionBlockType() != 0xff ) {
1591             if ( plug->getPlugDirection() == AvPlug::eAPD_Input ) {
1592                 printf( "\t\"(%d) %s\" -> \"(0x%02x,%d)\"\n",
1593                         plug->getGlobalId(),
1594                         plug->getName(),
1595                         plug->getFunctionBlockType(),
1596                         plug->getFunctionBlockId() );
1597             } else {
1598                 printf( "\t\"(0x%02x,%d)\" -> \t\"(%d) %s\"\n",
1599                         plug->getFunctionBlockType(),
1600                         plug->getFunctionBlockId(),
1601                         plug->getGlobalId(),
1602                         plug->getName() );
1603             }
1604         }
1605     }
1606
1607     const char* colorStrings[] = {
1608         "coral",
1609         "slateblue",
1610         "white",
1611         "green",
1612         "yellow",
1613         "grey",
1614     };
1615
1616     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1617           it !=  m_plugs.end();
1618           ++it )
1619     {
1620         AvPlug* plug = *it;
1621         printf( "\t\"(%d) %s\" [color=%s,style=filled];\n",
1622                 plug->getGlobalId(), plug->getName(),
1623                 colorStrings[plug->getPlugAddressType() ] );
1624     }
1625
1626     printf("}\n" );
1627     printf( "Use \"dot -Tps FILENAME.dot -o FILENAME.ps\" "
1628             "to generate graph\n");
1629
1630     debugOutput( DEBUG_LEVEL_VERBOSE, "Plug details\n" );
1631     debugOutput( DEBUG_LEVEL_VERBOSE, "------------\n" );
1632     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1633           it !=  m_plugs.end();
1634           ++it )
1635     {
1636         AvPlug* plug = *it;
1637         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d:\n", plug->getGlobalId() );
1638         plug->showPlug();
1639
1640     }
1641 }
1642
1643 AvPlug*
1644 AvPlugManager::getPlug( AVCCommand::ESubunitType subunitType,
1645                         subunit_id_t subunitId,
1646                         function_block_type_t functionBlockType,
1647                         function_block_id_t functionBlockId,
1648                         AvPlug::EAvPlugAddressType plugAddressType,
1649                         AvPlug::EAvPlugDirection plugDirection,
1650                         plug_id_t plugId ) const
1651 {
1652     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, ID = "
1653                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
1654                  subunitType,
1655                  subunitId,
1656                  functionBlockType,
1657                  functionBlockId,
1658                  plugAddressType,
1659                  plugDirection,
1660                  plugId );
1661
1662     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1663           it !=  m_plugs.end();
1664           ++it )
1665     {
1666         AvPlug* plug = *it;
1667
1668         if (    ( subunitType == plug->getSubunitType() )
1669              && ( subunitId == plug->getSubunitId() )
1670              && ( functionBlockType == plug->getFunctionBlockType() )
1671              && ( functionBlockId == plug->getFunctionBlockId() )
1672              && ( plugAddressType == plug->getPlugAddressType() )
1673              && ( plugDirection == plug->getPlugDirection() )
1674              && ( plugId == plug->getPlugId() ) )
1675         {
1676             return plug;
1677         }
1678     }
1679
1680     return 0;
1681 }
1682
1683 AvPlugVector
1684 AvPlugManager::getPlugsByType( AVCCommand::ESubunitType subunitType,
1685                                subunit_id_t subunitId,
1686                                function_block_type_t functionBlockType,
1687                                function_block_id_t functionBlockId,
1688                                AvPlug::EAvPlugAddressType plugAddressType,
1689                                AvPlug::EAvPlugDirection plugDirection,
1690                                AvPlug::EAvPlugType type) const
1691 {
1692     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, T = "
1693                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
1694                  subunitType,
1695                  subunitId,
1696                  functionBlockType,
1697                  functionBlockId,
1698                  plugAddressType,
1699                  plugDirection,
1700                  type );
1701
1702     AvPlugVector plugVector;
1703     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1704           it !=  m_plugs.end();
1705           ++it )
1706     {
1707         AvPlug* plug = *it;
1708
1709         if (    ( subunitType == plug->getSubunitType() )
1710              && ( subunitId == plug->getSubunitId() )
1711              && ( functionBlockType == plug->getFunctionBlockType() )
1712              && ( functionBlockId == plug->getFunctionBlockId() )
1713              && ( plugAddressType == plug->getPlugAddressType() )
1714              && ( plugDirection == plug->getPlugDirection() )
1715              && ( type == plug->getPlugType() ) )
1716         {
1717             plugVector.push_back( plug );
1718         }
1719     }
1720
1721     return plugVector;
1722 }
1723
1724 ////////////////////////////////////
1725
1726 AvPlugCluster::AvPlugCluster()
1727 {
1728 }
1729
1730 AvPlugCluster::~AvPlugCluster()
1731 {
1732 }
1733
1734 ////////////////////////////////////
1735
1736 AvPlugConnection::AvPlugConnection( AvPlug& srcPlug, AvPlug& destPlug )
1737     : m_srcPlug( &srcPlug )
1738     , m_destPlug( &destPlug )
1739 {
1740 }
1741
1742 }
Note: See TracBrowser for help on using the browser.