root/branches/echoaudio/src/libavc/general/avc_plug.cpp

Revision 548, 72.7 kB (checked in by ppalmers, 15 years ago)

- make the BeBoB AvDevice? a child class of the GenericAVC AvDevice?. This
avoids a lot of code duplication.
- fix inconsistency in position/location numbering between ext pluginfo
cmd and descriptor.

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