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

Revision 1110, 75.0 kB (checked in by wagi, 14 years ago)

Lot's of small and big bug fixes allong the caching path.
There were several parts not correctly deserialized.

This should fix ticket #65

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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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( Glib::ustring 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.