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

Revision 336, 57.4 kB (checked in by pieterpalmers, 16 years ago)

- Merged the developments on trunk since branch-off:

branch occurred at rev 194
svn merge -r 194:HEAD https://svn.sourceforge.net/svnroot/freebob/trunk/libfreebob

- Modified libfreebobavc to use the messagebuffer for debug info.
- This should compile and run

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