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

Revision 1154, 74.9 kB (checked in by ppalmers, 14 years ago)

add expat based parsing of the device cache. add compile-time selection between libxml++ and expat. will allow to get rid of the libxml++ dependency on the long run. scons SERIALIZE_USE_EXPAT=0Only compile testedscons SERIALIZE_USE_EXPAT=0

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