root/trunk/libfreebob/src/avplug.cpp

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

2006-03-30 Daniel Wagner <wagi@monom.org>

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