root/trunk/libfreebob/src/avplug.cpp

Revision 181, 55.9 kB (checked in by wagi, 18 years ago)

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

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