root/trunk/libffado/src/libavc/general/avc_plug.cpp

Revision 1568, 83.2 kB (checked in by holin, 15 years ago)

gcc 4.4 fixes (r1566, r1567, DICE) to trunk

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