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

Revision 447, 73.0 kB (checked in by ppalmers, 16 years ago)

- Better display of the function blocks in the graph
- test-mixer can now switch the front/back switch of the phase88

(function block 10: ./test-mixer PORT NODE 10)

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