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

Revision 404, 72.4 kB (checked in by pieterpalmers, 17 years ago)

- introduce support framework for DICE and Metric Halo
- change probe/discovery code to make adding devices easier
- made conditional compilation effectively work.

./configure now has the following switches:

--enable-bebob build BeBoB support (default=yes)
--enable-motu build Motu support (default=no)
--enable-dice build DICE support (default=no)
--enable-metric-halo build Metric Halo support (note: completely useless)

(default=no)

--enable-rme build RME support (note: completely useless)

(default=no)

--enable-bounce build Bounce device support (default=no)
--enable-all-devices build support for all supported devices (default=no)

these now turn on/off compilation effectively.

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