root/branches/libffado-2.0/src/libavc/general/avc_plug.cpp

Revision 1722, 79.9 kB (checked in by ppalmers, 14 years ago)

fix format warnings for extreme debugging

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