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

Revision 2803, 83.7 kB (checked in by jwoithe, 3 years ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

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