root/branches/streaming-rework/src/bebob/bebob_avplug.cpp

Revision 438, 72.8 kB (checked in by pieterpalmers, 17 years ago)

- introduced generic setting of the samplerate, removed AVC depency for other IAvDevices.

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