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

Revision 2322, 83.7 kB (checked in by jwoithe, 11 years ago)

libavc: fix wrong format name of stream for digital audio interface. In libavc component, there is a format of stream named as AM824_IEC60968_3. But IEC 60968 is for electric lights then IEC 60958 seems to be valid here. This patch just rename the macro and add no functional changes. Patch from Takashi Sakamoto.

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             channelInfo = channelInfo;
1344             debugOutput( debugLevel,
1345                          "stream position: %d\n",
1346                          channelInfo->m_streamPosition );
1347             debugOutput( debugLevel,
1348                          "location: %d\n",
1349                          channelInfo->m_location );
1350         }
1351     }
1352 }
1353
1354 const Plug::ClusterInfo*
1355 Plug::getClusterInfoByIndex(int index) const
1356 {
1357     for ( Plug::ClusterInfoVector::const_iterator clit =
1358               m_clusterInfos.begin();
1359           clit != m_clusterInfos.end();
1360           ++clit )
1361     {
1362         const ClusterInfo* info = &*clit;
1363         if ( info->m_index == index ) {
1364             return info;
1365         }
1366     }
1367     return 0;
1368 }
1369
1370 PlugAddress::EPlugDirection
1371 Plug::convertPlugDirection( EPlugDirection direction )
1372 {
1373     PlugAddress::EPlugDirection dir;
1374     switch ( direction ) {
1375     case Plug::eAPD_Input:
1376         dir = PlugAddress::ePD_Input;
1377         break;
1378     case Plug::eAPD_Output:
1379         dir = PlugAddress::ePD_Output;
1380         break;
1381     default:
1382         dir = PlugAddress::ePD_Undefined;
1383     }
1384     return dir;
1385 }
1386
1387 std::string
1388 Plug::plugAddressTypeToString(enum EPlugAddressType t) {
1389     switch (t) {
1390         case eAPA_PCR:
1391             return string("PCR");
1392         case eAPA_ExternalPlug:
1393             return string("External");
1394         case eAPA_AsynchronousPlug:
1395             return string("Async");
1396         case eAPA_SubunitPlug:
1397             return string("Subunit");
1398         case eAPA_FunctionBlockPlug:
1399             return string("Function Block");
1400         default:
1401         case eAPA_Undefined:
1402             return string("Undefined");
1403     }
1404 }
1405
1406 std::string
1407 Plug::plugTypeToString(enum EPlugType t) {
1408     switch (t) {
1409         case eAPT_IsoStream:
1410             return string("IsoStream");
1411         case eAPT_AsyncStream:
1412             return string("AsyncStream");
1413         case eAPT_Midi:
1414             return string("MIDI");
1415         case eAPT_Sync:
1416             return string("Sync");
1417         case eAPT_Analog:
1418             return string("Analog");
1419         case eAPT_Digital:
1420             return string("Digital");
1421         default:
1422         case eAPT_Unknown:
1423             return string("Unknown");
1424     }
1425 }
1426
1427 std::string
1428 Plug::plugDirectionToString(enum EPlugDirection t) {
1429     switch (t) {
1430         case eAPD_Input:
1431             return string("Input");
1432         case eAPD_Output:
1433             return string("Output");
1434         case eAPD_Unknown:
1435             return string("Unknown");
1436     }
1437     return string("ERROR");
1438 }
1439
1440 void
1441 Plug::showPlug() const
1442 {
1443     #ifdef DEBUG
1444     debugOutput( DEBUG_LEVEL_VERBOSE, "\tName               = %s\n",
1445                  getName() );
1446     debugOutput( DEBUG_LEVEL_VERBOSE, "\tType               = %s\n",
1447                  extendedPlugInfoPlugTypeToString( getPlugType() ) );
1448     debugOutput( DEBUG_LEVEL_VERBOSE, "\tAddress Type       = %s\n",
1449                  avPlugAddressTypeToString( getPlugAddressType() ) );
1450     debugOutput( DEBUG_LEVEL_VERBOSE, "\tId                 = %d\n",
1451                  getPlugId() );
1452     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitType        = %d\n",
1453                  getSubunitType() );
1454     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitId          = %d\n",
1455                  getSubunitId() );
1456     debugOutput( DEBUG_LEVEL_VERBOSE, "\tDirection          = %s\n",
1457                  avPlugDirectionToString( getPlugDirection() ) );
1458     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSampling Rate      = %d\n",
1459                  getSampleRate() );
1460     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Channels = %d\n",
1461                  getNrOfChannels() );
1462     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Streams  = %d\n",
1463                  getNrOfStreams() );
1464     debugOutput( DEBUG_LEVEL_VERBOSE, "\tIncoming connections from: ");
1465
1466     for ( PlugVector::const_iterator it = m_inputConnections.begin();
1467           it != m_inputConnections.end();
1468           ++it )
1469     {
1470         debugOutputShort(DEBUG_LEVEL_VERBOSE, "%s, ", (*it)->getName());
1471     }
1472     debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n");
1473
1474     debugOutput( DEBUG_LEVEL_VERBOSE, "\tOutgoing connections to: ");
1475     for ( PlugVector::const_iterator it = m_outputConnections.begin();
1476           it != m_outputConnections.end();
1477           ++it )
1478     {
1479         debugOutputShort(DEBUG_LEVEL_VERBOSE, "%s, ", (*it)->getName());
1480     }
1481     debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n");
1482
1483     debugOutput( DEBUG_LEVEL_VERBOSE, "\tChannel info:\n");
1484     unsigned int i=0;
1485     for ( Plug::ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
1486           it != m_clusterInfos.end();
1487           ++it )
1488     {
1489         const Plug::ClusterInfo* clusterInfo = &( *it );
1490
1491         debugOutput(DEBUG_LEVEL_VERBOSE, "         Cluster %s (idx=%2d, type=0x%02X, ch=%2d, format=0x%02X)\n",
1492             clusterInfo->m_name.c_str(), i, clusterInfo->m_portType, clusterInfo->m_nrOfChannels, clusterInfo->m_streamFormat);
1493         Plug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1494         for ( Plug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1495               it != channelInfos.end();
1496               ++it )
1497         {
1498             const Plug::ChannelInfo* channelInfo = &( *it );
1499             debugOutput(DEBUG_LEVEL_VERBOSE, "           Channel %s (pos=0x%02X, loc=0x%02X)\n",
1500                 channelInfo->m_name.c_str(), channelInfo->m_streamPosition, channelInfo->m_location);
1501         }
1502         i++;
1503     }
1504     flushDebugOutput();
1505     #endif
1506 }
1507
1508
1509 Plug*
1510 Plug::getPlugDefinedBySpecificData(
1511     UnitPlugSpecificDataPlugAddress* pUnitPlugAddress,
1512     SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress,
1513     FunctionBlockPlugSpecificDataPlugAddress* pFunctionBlockPlugAddress )
1514 {
1515     subunit_type_t        subunitType       = 0xff;
1516     subunit_id_t          subunitId         = 0xff;
1517     function_block_type_t functionBlockType = 0xff;
1518     function_block_id_t   functionBlockId   = 0xff;
1519     EPlugAddressType      addressType       = eAPA_Undefined;
1520     EPlugDirection        direction         = eAPD_Unknown;
1521     plug_id_t             plugId            = 0xff;
1522
1523     if ( !pUnitPlugAddress
1524          && !pSubunitPlugAddress
1525          && !pFunctionBlockPlugAddress )
1526     {
1527         debugError( "No correct specific data found\n" );
1528         return 0;
1529     }
1530
1531     if ( pUnitPlugAddress ) {
1532         subunitType = eST_Unit;
1533         switch ( pUnitPlugAddress->m_plugType ) {
1534         case UnitPlugSpecificDataPlugAddress::ePT_PCR:
1535             addressType = eAPA_PCR;
1536             break;
1537         case UnitPlugSpecificDataPlugAddress::ePT_ExternalPlug:
1538             addressType = eAPA_ExternalPlug;
1539             break;
1540         case UnitPlugSpecificDataPlugAddress::ePT_AsynchronousPlug:
1541             addressType = eAPA_AsynchronousPlug;
1542             break;
1543         }
1544         // unit plug have only connections to subunits
1545         if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1546             direction = getDirection();
1547         } else {
1548             debugError( "Function block has connection from/to unknown "
1549                         "plug type\n" );
1550             direction = eAPD_Unknown;
1551         }
1552         plugId = pUnitPlugAddress->m_plugId;
1553
1554         debugOutput( DEBUG_LEVEL_VERBOSE,
1555                      "'(%d) %s': Remote plug is a unit plug "
1556                      "(%s, %s, %d)\n",
1557                      getGlobalId(),
1558                      getName(),
1559                      avPlugAddressTypeToString( addressType ),
1560                      avPlugDirectionToString( direction ),
1561                      plugId );
1562     }
1563
1564     if ( pSubunitPlugAddress ) {
1565         subunitType = pSubunitPlugAddress->m_subunitType;
1566         subunitId = pSubunitPlugAddress->m_subunitId;
1567         addressType = eAPA_SubunitPlug;
1568
1569         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1570             direction = getDirection();
1571         } else if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1572             direction = toggleDirection( getDirection() );
1573         } else {
1574             // unit
1575             direction = getDirection();
1576         }
1577
1578         plugId = pSubunitPlugAddress->m_plugId;
1579         debugOutput( DEBUG_LEVEL_VERBOSE,
1580                      "'(%d) %s': Remote plug is a subunit plug "
1581                      "(%d, %d, %s, %d)\n",
1582                      getGlobalId(),
1583                      getName(),
1584                      subunitType,
1585                      subunitId,
1586                      avPlugDirectionToString( direction ),
1587                      plugId );
1588     }
1589
1590     if ( pFunctionBlockPlugAddress ) {
1591         subunitType = pFunctionBlockPlugAddress->m_subunitType;
1592         subunitId = pFunctionBlockPlugAddress->m_subunitId;
1593         functionBlockType = pFunctionBlockPlugAddress->m_functionBlockType;
1594         functionBlockId = pFunctionBlockPlugAddress->m_functionBlockId;
1595         addressType = eAPA_FunctionBlockPlug;
1596
1597         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1598             direction = toggleDirection( getDirection() );
1599         } else if ( getPlugAddressType() == eAPA_SubunitPlug ){
1600             direction = getDirection();
1601         } else {
1602             debugError( "Function block has connection from/to unknown "
1603                         "plug type\n" );
1604             direction = eAPD_Unknown;
1605         }
1606
1607         plugId = pFunctionBlockPlugAddress->m_plugId;
1608
1609         debugOutput( DEBUG_LEVEL_VERBOSE,
1610                      "'(%d) %s': Remote plug is a functionblock plug "
1611                      "(%d, %d, %d, %d, %s, %d)\n",
1612                      getGlobalId(),
1613                      getName(),
1614                      subunitType,
1615                      subunitId,
1616                      functionBlockType,
1617                      functionBlockId,
1618                      avPlugDirectionToString( direction ),
1619                      plugId );
1620     }
1621
1622     ESubunitType enumSubunitType =
1623         static_cast<ESubunitType>( subunitType );
1624
1625     return m_unit->getPlugManager().getPlug(
1626         enumSubunitType,
1627         subunitId,
1628         functionBlockType,
1629         functionBlockId,
1630         addressType,
1631         direction,
1632         plugId );
1633 }
1634
1635 Plug::EPlugDirection
1636 Plug::toggleDirection( EPlugDirection direction ) const
1637 {
1638     EPlugDirection newDirection;
1639     switch ( direction ) {
1640     case eAPD_Output:
1641         newDirection = eAPD_Input;
1642         break;
1643     case eAPD_Input:
1644         newDirection = eAPD_Output;
1645         break;
1646     default:
1647         newDirection = direction;
1648     }
1649
1650     return newDirection;
1651 }
1652
1653 bool
1654 Plug::serializeChannelInfos( std::string basePath,
1655                              Util::IOSerialize& ser,
1656                              const ClusterInfo& clusterInfo ) const
1657 {
1658     bool result = true;
1659     int i = 0;
1660     for ( ChannelInfoVector::const_iterator it = clusterInfo.m_channelInfos.begin();
1661           it != clusterInfo.m_channelInfos.end();
1662           ++it )
1663     {
1664         const ChannelInfo& info = *it;
1665         std::ostringstream strstrm;
1666         strstrm << basePath << i;
1667
1668         result &= ser.write( strstrm.str() + "/m_streamPosition", info.m_streamPosition );
1669         result &= ser.write( strstrm.str() + "/m_location", info.m_location );
1670         result &= ser.write( strstrm.str() + "/m_name", info.m_name );
1671         i++;
1672     }
1673
1674     return result;
1675 }
1676
1677 bool
1678 Plug::deserializeChannelInfos( std::string basePath,
1679                                Util::IODeserialize& deser,
1680                                ClusterInfo& clusterInfo )
1681 {
1682     int i = 0;
1683     bool bFinished = false;
1684     bool result = true;
1685     do {
1686         std::ostringstream strstrm;
1687         strstrm << basePath << i;
1688
1689         // check for one element to exist. when one exist the other elements
1690         // must also be there. otherwise just return (last) result.
1691         if ( deser.isExisting( strstrm.str() + "/m_streamPosition" ) ) {
1692             ChannelInfo info;
1693
1694             result &= deser.read( strstrm.str() + "/m_streamPosition", info.m_streamPosition );
1695             result &= deser.read( strstrm.str() + "/m_location", info.m_location );
1696             result &= deser.read( strstrm.str() + "/m_name", info.m_name );
1697
1698             if ( result ) {
1699                 clusterInfo.m_channelInfos.push_back( info );
1700                 i++;
1701             } else {
1702                 bFinished = true;
1703             }
1704         } else {
1705             bFinished = true;
1706         }
1707     } while ( !bFinished );
1708
1709     return result;
1710 }
1711
1712
1713 bool
1714 Plug::serializeClusterInfos( std::string basePath,
1715                              Util::IOSerialize& ser ) const
1716 {
1717     bool result = true;
1718     int i = 0;
1719     for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
1720           it != m_clusterInfos.end();
1721           ++it )
1722     {
1723         const ClusterInfo& info = *it;
1724         std::ostringstream strstrm;
1725         strstrm << basePath << i;
1726
1727         result &= ser.write( strstrm.str() + "/m_index", info.m_index );
1728         result &= ser.write( strstrm.str() + "/m_portType", info.m_portType );
1729         result &= ser.write( strstrm.str() + "/m_name", info.m_name );
1730         result &= ser.write( strstrm.str() + "/m_nrOfChannels", info.m_nrOfChannels );
1731         result &= serializeChannelInfos( strstrm.str() + "/m_channelInfo", ser, info );
1732         result &= ser.write( strstrm.str() + "/m_streamFormat", info.m_streamFormat );
1733         i++;
1734     }
1735
1736     return result;
1737 }
1738
1739 bool
1740 Plug::deserializeClusterInfos( std::string basePath,
1741                                Util::IODeserialize& deser )
1742 {
1743     int i = 0;
1744     bool bFinished = false;
1745     bool result = true;
1746     do {
1747         std::ostringstream strstrm;
1748         strstrm << basePath << i;
1749
1750         // check for one element to exist. when one exist the other elements
1751         // must also be there. otherwise just return (last) result.
1752         if ( deser.isExisting( strstrm.str() + "/m_index" ) ) {
1753             ClusterInfo info;
1754
1755             result &= deser.read( strstrm.str() + "/m_index", info.m_index );
1756             result &= deser.read( strstrm.str() + "/m_portType", info.m_portType );
1757             result &= deser.read( strstrm.str() + "/m_name", info.m_name );
1758             result &= deser.read( strstrm.str() + "/m_nrOfChannels", info.m_nrOfChannels );
1759             result &= deserializeChannelInfos( strstrm.str() + "/m_channelInfo", deser, info );
1760             result &= deser.read( strstrm.str() + "/m_streamFormat", info.m_streamFormat );
1761
1762             if ( result ) {
1763                 m_clusterInfos.push_back( info );
1764                 i++;
1765             } else {
1766                 bFinished = true;
1767             }
1768         } else {
1769             bFinished = true;
1770         }
1771     } while ( !bFinished );
1772
1773     return result;
1774 }
1775
1776
1777 bool
1778 Plug::serializeFormatInfos( std::string basePath,
1779                             Util::IOSerialize& ser ) const
1780 {
1781     bool result = true;
1782     int i = 0;
1783     for ( FormatInfoVector::const_iterator it = m_formatInfos.begin();
1784           it != m_formatInfos.end();
1785           ++it )
1786     {
1787         const FormatInfo& info = *it;
1788         std::ostringstream strstrm;
1789         strstrm << basePath << i;
1790
1791         result &= ser.write( strstrm.str() + "/m_samplingFrequency", info.m_samplingFrequency );
1792         result &= ser.write( strstrm.str() + "/m_isSyncStream", info.m_isSyncStream );
1793         result &= ser.write( strstrm.str() + "/m_audioChannels", info.m_audioChannels );
1794         result &= ser.write( strstrm.str() + "/m_midiChannels", info.m_midiChannels );
1795         result &= ser.write( strstrm.str() + "/m_index", info.m_index );
1796         i++;
1797     }
1798     return result;
1799 }
1800
1801 bool
1802 Plug::deserializeFormatInfos( std::string basePath,
1803                               Util::IODeserialize& deser )
1804 {
1805     int i = 0;
1806     bool bFinished = false;
1807     bool result = true;
1808     do {
1809         std::ostringstream strstrm;
1810         strstrm << basePath << i;
1811
1812         // check for one element to exist. when one exist the other elements
1813         // must also be there. otherwise just return (last) result.
1814         if ( deser.isExisting( strstrm.str() + "/m_samplingFrequency" ) ) {
1815             FormatInfo info;
1816
1817             result &= deser.read( strstrm.str() + "/m_samplingFrequency", info.m_samplingFrequency );
1818             result &= deser.read( strstrm.str() + "/m_isSyncStream", info.m_isSyncStream );
1819             result &= deser.read( strstrm.str() + "/m_audioChannels", info.m_audioChannels );
1820             result &= deser.read( strstrm.str() + "/m_midiChannels", info.m_midiChannels );
1821             result &= deser.read( strstrm.str() + "/m_index", info.m_index );
1822
1823             if ( result ) {
1824                 m_formatInfos.push_back( info );
1825                 i++;
1826             } else {
1827                 bFinished = true;
1828             }
1829         } else {
1830             bFinished = true;
1831         }
1832     } while ( !bFinished );
1833
1834     return result;
1835 }
1836
1837 bool
1838 Plug::serialize( std::string basePath, Util::IOSerialize& ser ) const
1839 {
1840     bool result=true;
1841     result &= ser.write( basePath + "m_subunitType", getSubunitType());
1842     result &= ser.write( basePath + "m_subunitId", getSubunitId());
1843     result &= ser.write( basePath + "m_functionBlockType", m_functionBlockType);
1844     result &= ser.write( basePath + "m_functionBlockId", m_functionBlockId);
1845     result &= ser.write( basePath + "m_addressType", m_addressType );
1846     result &= ser.write( basePath + "m_direction", m_direction);
1847     result &= ser.write( basePath + "m_id", m_id);
1848     result &= ser.write( basePath + "m_infoPlugType", m_infoPlugType);
1849     result &= ser.write( basePath + "m_nrOfChannels", m_nrOfChannels);
1850     result &= ser.write( basePath + "m_name", m_name);
1851     result &= serializeClusterInfos( basePath + "m_clusterInfos", ser );
1852     result &= ser.write( basePath + "m_samplingFrequency", m_samplingFrequency);
1853     result &= serializeFormatInfos( basePath + "m_formatInfo", ser );
1854     result &= serializePlugVector( basePath + "m_inputConnections", ser, m_inputConnections );
1855     result &= serializePlugVector( basePath + "m_outputConnections", ser, m_outputConnections );
1856     result &= ser.write( basePath + "m_globalId", m_globalId);
1857
1858     return result;
1859 }
1860
1861 Plug*
1862 Plug::deserialize( std::string basePath,
1863                    Util::IODeserialize& deser,
1864                    Unit& unit,
1865                    PlugManager& plugManager )
1866 {
1867     ESubunitType          subunitType;
1868     subunit_t             subunitId;
1869     function_block_type_t functionBlockType;
1870     function_block_id_t   functionBlockId;
1871     EPlugAddressType      addressType;
1872     EPlugDirection        direction;
1873     plug_id_t             id;
1874     int                   globalId;
1875
1876     if ( !deser.isExisting( basePath + "m_subunitType" ) ) {
1877         return 0;
1878     }
1879
1880     bool result=true;
1881
1882     result  = deser.read( basePath + "m_subunitType", subunitType );
1883     result &= deser.read( basePath + "m_subunitId", subunitId );
1884     Subunit* subunit = unit.getSubunit( subunitType, subunitId );
1885
1886     result &= deser.read( basePath + "m_functionBlockType", functionBlockType );
1887     result &= deser.read( basePath + "m_functionBlockId", functionBlockId );
1888     result &= deser.read( basePath + "m_addressType", addressType );
1889     result &= deser.read( basePath + "m_direction", direction );
1890     result &= deser.read( basePath + "m_id", id );
1891     result &= deser.read( basePath + "m_globalId", globalId );
1892
1893     Plug* pPlug = unit.createPlug( &unit, subunit, functionBlockType,
1894                                    functionBlockId, addressType, direction,
1895                                    id, globalId);
1896     if ( !pPlug ) {
1897         return 0;
1898     }
1899
1900     // this is needed to allow for the update of the subunit pointer later on
1901     // in the deserializeUpdateSubunit.
1902     pPlug->m_subunitType = subunitType;
1903     pPlug->m_subunitId = subunitId;
1904
1905     result &= deser.read( basePath + "m_infoPlugType", pPlug->m_infoPlugType );
1906     result &= deser.read( basePath + "m_nrOfChannels", pPlug->m_nrOfChannels );
1907     result &= deser.read( basePath + "m_name", pPlug->m_name );
1908     result &= pPlug->deserializeClusterInfos( basePath + "m_clusterInfos", deser );
1909     result &= deser.read( basePath + "m_samplingFrequency", pPlug->m_samplingFrequency );
1910     result &= pPlug->deserializeFormatInfos( basePath + "m_formatInfos", deser );
1911     // input and output connections can't be processed here because not all plugs might
1912     // deserialized at this point. so we do that in deserializeUpdate.
1913
1914     if ( !result ) {
1915         delete pPlug;
1916         return 0;
1917     }
1918
1919     return pPlug;
1920 }
1921
1922 bool
1923 Plug::deserializeConnections( std::string basePath,
1924                               Util::IODeserialize& deser )
1925 {
1926     bool result;
1927
1928     result  = deserializePlugVector( basePath + "/m_inputConnections", deser,
1929                                      m_unit->getPlugManager(), m_inputConnections );
1930     result &= deserializePlugVector( basePath + "/m_outputConnections", deser,
1931                                      m_unit->getPlugManager(), m_outputConnections );
1932     return result;
1933 }
1934
1935 bool
1936 Plug::deserializeUpdateSubunit()
1937 {
1938     m_subunit = m_unit->getSubunit( m_subunitType, m_subunitId );
1939     return true;
1940 }
1941
1942 /////////////////////////////////////////
1943 /////////////////////////////////////////
1944
1945 const char* avPlugAddressTypeStrings[] =
1946 {
1947     "PCR",
1948     "external",
1949     "asynchronous",
1950     "subunit",
1951     "functionblock",
1952     "undefined",
1953 };
1954
1955 const char* avPlugAddressTypeToString( Plug::EPlugAddressType type )
1956 {
1957     if ( type > ( int )( sizeof( avPlugAddressTypeStrings )
1958                          / sizeof( avPlugAddressTypeStrings[0] ) ) )
1959     {
1960         type = Plug::eAPA_Undefined;
1961     }
1962     return avPlugAddressTypeStrings[type];
1963 }
1964
1965 const char* avPlugTypeStrings[] =
1966 {
1967     "IsoStream",
1968     "AsyncStream",
1969     "MIDI",
1970     "Sync",
1971     "Analog",
1972     "Digital",
1973     "Unknown",
1974 };
1975
1976 const char* avPlugTypeToString( Plug::EPlugType type )
1977 {
1978     if ( type > ( int )( sizeof( avPlugTypeStrings )
1979                          / sizeof( avPlugTypeStrings[0] ) ) )
1980     {
1981         type = Plug::eAPT_Unknown;
1982     }
1983     return avPlugTypeStrings[type];
1984 }
1985
1986 const char* avPlugDirectionStrings[] =
1987 {
1988     "Input",
1989     "Output",
1990     "Unknown",
1991 };
1992
1993 const char* avPlugDirectionToString( Plug::EPlugDirection type )
1994 {
1995     if ( type > ( int )( sizeof( avPlugDirectionStrings )
1996                          / sizeof( avPlugDirectionStrings[0] ) ) )
1997     {
1998         type = Plug::eAPD_Unknown;
1999     }
2000     return avPlugDirectionStrings[type];
2001 }
2002
2003 /////////////////////////////////////
2004
2005
2006 PlugManager::PlugManager(  )
2007 : m_globalIdCounter( 0 )
2008 {
2009
2010 }
2011
2012 PlugManager::PlugManager( const PlugManager& rhs )
2013 : m_globalIdCounter( rhs.m_globalIdCounter )
2014 {
2015     setDebugLevel( rhs.getDebugLevel() );
2016 }
2017
2018 PlugManager::~PlugManager()
2019 {
2020 }
2021
2022 void
2023 PlugManager::setVerboseLevel( int l )
2024 {
2025     setDebugLevel(l);
2026     for ( PlugVector::iterator it = m_plugs.begin();
2027           it !=  m_plugs.end();
2028           ++it )
2029     {
2030         (*it)->setVerboseLevel(l);
2031     }
2032     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
2033 }
2034
2035 bool
2036 PlugManager::addPlug( Plug& plug )
2037 {
2038     m_plugs.push_back( &plug );
2039     // inherit debug level
2040     plug.setVerboseLevel(getDebugLevel());
2041     return true;
2042 }
2043
2044 bool
2045 PlugManager::remPlug( Plug& plug )
2046 {
2047     for ( PlugVector::iterator it = m_plugs.begin();
2048           it !=  m_plugs.end();
2049           ++it )
2050     {
2051         Plug* plugIt = *it;
2052         if ( plugIt == &plug ) {
2053             m_plugs.erase( it );
2054             return true;
2055         }
2056     }
2057     return false;
2058 }
2059
2060 // helper function
2061 static void addConnection( PlugConnectionVector& connections,
2062                            Plug& srcPlug,
2063                            Plug& destPlug )
2064 {
2065     for ( PlugConnectionVector::iterator it = connections.begin();
2066           it != connections.end();
2067           ++it )
2068     {
2069         PlugConnection* con = *it;
2070         if ( ( &( con->getSrcPlug() ) == &srcPlug )
2071              && ( &( con->getDestPlug() ) == &destPlug ) )
2072         {
2073             return;
2074         }
2075     }
2076     connections.push_back( new PlugConnection( srcPlug, destPlug ) );
2077 }
2078
2079 bool
2080 PlugManager::tidyPlugConnections(PlugConnectionVector& connections)
2081 {
2082     connections.clear();
2083     for ( PlugVector::const_iterator it = m_plugs.begin();
2084           it !=  m_plugs.end();
2085           ++it )
2086     {
2087         Plug* plug = *it;
2088         for ( PlugVector::const_iterator it =
2089                   plug->getInputConnections().begin();
2090             it != plug->getInputConnections().end();
2091             ++it )
2092         {
2093             addConnection( connections, *( *it ), *plug );
2094         }
2095         plug->getInputConnections().clear();
2096
2097         for ( PlugVector::const_iterator it =
2098                   plug->getOutputConnections().begin();
2099             it != plug->getOutputConnections().end();
2100             ++it )
2101         {
2102             addConnection( connections, *plug, *( *it ) );
2103         }
2104         plug->getOutputConnections().clear();
2105     }
2106
2107     for ( PlugConnectionVector::iterator it = connections.begin();
2108           it != connections.end();
2109           ++it )
2110     {
2111         PlugConnection * con = *it;
2112         con->getSrcPlug().getOutputConnections().push_back(&( con->getDestPlug() ));
2113         con->getDestPlug().getInputConnections().push_back(&( con->getSrcPlug() ));
2114
2115     }
2116
2117     return true;
2118 }
2119
2120 static void addConnectionOwner( PlugConnectionOwnerVector& connections,
2121                            Plug& srcPlug,
2122                            Plug& destPlug )
2123 {
2124
2125     for ( PlugConnectionOwnerVector::iterator it = connections.begin();
2126           it != connections.end();
2127           ++it )
2128     {
2129         PlugConnection& con = *it;
2130         if ( ( &( con.getSrcPlug() ) == &srcPlug )
2131              && ( &( con.getDestPlug() ) == &destPlug ) )
2132         {
2133             return;
2134         }
2135     }
2136     connections.push_back( PlugConnection( srcPlug, destPlug ) );
2137 }
2138
2139
2140 void
2141 PlugManager::showPlugs() const
2142 {
2143     if(getDebugLevel() < DEBUG_LEVEL_INFO) return;
2144
2145     // \todo The information provided here could be better arranged. For a start it is ok, but
2146     // there is room for improvement. Something for a lazy sunday afternoon (tip: maybe drink some
2147     // beer to get into the mood)
2148
2149     printf( "\nSummary\n" );
2150     printf( "-------\n\n" );
2151     printf( "Nr | AddressType     | Direction | SubUnitType | SubUnitId | FunctionBlockType | FunctionBlockId | Id   | Type         |Name\n" );
2152     printf( "---+-----------------+-----------+-------------+-----------+-------------------+-----------------+------+--------------+------\n" );
2153
2154     for ( PlugVector::const_iterator it = m_plugs.begin();
2155           it !=  m_plugs.end();
2156           ++it )
2157     {
2158         Plug* plug = *it;
2159
2160         printf( "%2d | %15s | %9s | %11s |      0x%02x |              0x%02x |            0x%02x | 0x%02x | %12s | %s\n",
2161                 plug->getGlobalId(),
2162                 avPlugAddressTypeToString( plug->getPlugAddressType() ),
2163                 avPlugDirectionToString( plug->getDirection() ),
2164                 subunitTypeToString( plug->getSubunitType() ),
2165                 plug->getSubunitId(),
2166                 plug->getFunctionBlockType(),
2167                 plug->getFunctionBlockId(),
2168                 plug->getPlugId(),
2169                 avPlugTypeToString( plug->getPlugType() ),
2170                 plug->getName() );
2171     }
2172
2173     printf( "\nConnections\n" );
2174     printf( "-----------\n" );
2175
2176     PlugConnectionOwnerVector connections;
2177
2178     for ( PlugVector::const_iterator it = m_plugs.begin();
2179           it !=  m_plugs.end();
2180           ++it )
2181     {
2182         Plug* plug = *it;
2183         for ( PlugVector::const_iterator it =
2184                   plug->getInputConnections().begin();
2185             it != plug->getInputConnections().end();
2186             ++it )
2187         {
2188             addConnectionOwner( connections, *( *it ), *plug );
2189         }
2190         for ( PlugVector::const_iterator it =
2191                   plug->getOutputConnections().begin();
2192             it != plug->getOutputConnections().end();
2193             ++it )
2194         {
2195             addConnectionOwner( connections, *plug, *( *it ) );
2196         }
2197     }
2198
2199     printf( "digraph avcconnections {\n" );
2200     for ( PlugConnectionOwnerVector::iterator it = connections.begin();
2201           it != connections.end();
2202           ++it )
2203     {
2204         PlugConnection& con = *it;
2205         printf( "\t\"(%d) %s\" -> \"(%d) %s\"\n",
2206                 con.getSrcPlug().getGlobalId(),
2207                 con.getSrcPlug().getName(),
2208                 con.getDestPlug().getGlobalId(),
2209                 con.getDestPlug().getName() );
2210     }
2211     for ( PlugVector::const_iterator it = m_plugs.begin();
2212           it != m_plugs.end();
2213           ++it )
2214     {
2215         Plug* plug = *it;
2216         if ( plug->getFunctionBlockType() != 0xff ) {
2217             std::ostringstream strstrm;
2218             switch(plug->getFunctionBlockType()) {
2219                 case 0x80:
2220                     strstrm << "Selector FB";
2221                     break;
2222                 case 0x81:
2223                     strstrm << "Feature FB";
2224                     break;
2225                 case 0x82:
2226                     strstrm << "Processing FB";
2227                     break;
2228                 case 0x83:
2229                     strstrm << "CODEC FB";
2230                     break;
2231                 default:
2232                     strstrm << plug->getFunctionBlockType();
2233             }
2234
2235             if ( plug->getPlugDirection() == Plug::eAPD_Input ) {
2236                 printf( "\t\"(%d) %s\" -> \"(%s, ID %d)\"\n",
2237                         plug->getGlobalId(),
2238                         plug->getName(),
2239                         strstrm.str().c_str(),
2240                         plug->getFunctionBlockId() );
2241             } else {
2242                 printf( "\t\"(%s, ID %d)\" -> \t\"(%d) %s\"\n",
2243                         strstrm.str().c_str(),
2244                         plug->getFunctionBlockId(),
2245                         plug->getGlobalId(),
2246                         plug->getName() );
2247             }
2248         }
2249     }
2250
2251     const char* colorStrings[] = {
2252         "coral",
2253         "slateblue",
2254         "white",
2255         "green",
2256         "yellow",
2257         "grey",
2258     };
2259
2260     for ( PlugVector::const_iterator it = m_plugs.begin();
2261           it !=  m_plugs.end();
2262           ++it )
2263     {
2264         Plug* plug = *it;
2265         printf( "\t\"(%d) %s\" [color=%s,style=filled];\n",
2266                 plug->getGlobalId(), plug->getName(),
2267                 colorStrings[plug->getPlugAddressType() ] );
2268     }
2269
2270     printf("}\n" );
2271     printf( "Use \"dot -Tps FILENAME.dot -o FILENAME.ps\" "
2272             "to generate graph\n");
2273
2274     debugOutput( DEBUG_LEVEL_VERBOSE, "Plug details\n" );
2275     debugOutput( DEBUG_LEVEL_VERBOSE, "------------\n" );
2276     for ( PlugVector::const_iterator it = m_plugs.begin();
2277           it !=  m_plugs.end();
2278           ++it )
2279     {
2280         Plug* plug = *it;
2281         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d:\n", plug->getGlobalId() );
2282         plug->showPlug();
2283
2284     }
2285 }
2286
2287 Plug*
2288 PlugManager::getPlug( ESubunitType subunitType,
2289                       subunit_id_t subunitId,
2290                       function_block_type_t functionBlockType,
2291                       function_block_id_t functionBlockId,
2292                       Plug::EPlugAddressType plugAddressType,
2293                       Plug::EPlugDirection plugDirection,
2294                       plug_id_t plugId ) const
2295 {
2296     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, ID = "
2297                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
2298                  subunitType,
2299                  subunitId,
2300                  functionBlockType,
2301                  functionBlockId,
2302                  plugAddressType,
2303                  plugDirection,
2304                  plugId );
2305
2306     for ( PlugVector::const_iterator it = m_plugs.begin();
2307           it !=  m_plugs.end();
2308           ++it )
2309     {
2310         Plug* plug = *it;
2311
2312         if (    ( subunitType == plug->getSubunitType() )
2313              && ( subunitId == plug->getSubunitId() )
2314              && ( functionBlockType == plug->getFunctionBlockType() )
2315              && ( functionBlockId == plug->getFunctionBlockId() )
2316              && ( plugAddressType == plug->getPlugAddressType() )
2317              && ( plugDirection == plug->getPlugDirection() )
2318              && ( plugId == plug->getPlugId() ) )
2319         {
2320             return plug;
2321         }
2322     }
2323
2324     return 0;
2325 }
2326
2327 Plug*
2328 PlugManager::getPlug( int iGlobalId ) const
2329 {
2330     for ( PlugVector::const_iterator it = m_plugs.begin();
2331           it !=  m_plugs.end();
2332           ++it )
2333     {
2334         Plug* pPlug = *it;
2335         if ( pPlug->getGlobalId() == iGlobalId ) {
2336             return pPlug;
2337         }
2338     }
2339
2340     return 0;
2341 }
2342
2343 PlugVector
2344 PlugManager::getPlugsByType( ESubunitType subunitType,
2345                              subunit_id_t subunitId,
2346                              function_block_type_t functionBlockType,
2347                              function_block_id_t functionBlockId,
2348                              Plug::EPlugAddressType plugAddressType,
2349                              Plug::EPlugDirection plugDirection,
2350                              Plug::EPlugType type) const
2351 {
2352     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, T = "
2353                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
2354                  subunitType,
2355                  subunitId,
2356                  functionBlockType,
2357                  functionBlockId,
2358                  plugAddressType,
2359                  plugDirection,
2360                  type );
2361
2362     PlugVector plugVector;
2363     for ( PlugVector::const_iterator it = m_plugs.begin();
2364           it !=  m_plugs.end();
2365           ++it )
2366     {
2367         Plug* pPlug = *it;
2368
2369         if (    ( subunitType == pPlug->getSubunitType() )
2370              && ( subunitId == pPlug->getSubunitId() )
2371              && ( functionBlockType == pPlug->getFunctionBlockType() )
2372              && ( functionBlockId == pPlug->getFunctionBlockId() )
2373              && ( plugAddressType == pPlug->getPlugAddressType() )
2374              && ( plugDirection == pPlug->getPlugDirection() )
2375              && ( type == pPlug->getPlugType() ) )
2376         {
2377             plugVector.push_back( pPlug );
2378         }
2379     }
2380
2381     return plugVector;
2382 }
2383
2384 bool
2385 PlugManager::serialize( std::string basePath, Util::IOSerialize& ser ) const
2386 {
2387     bool result = true;
2388     int i = 0;
2389     for ( PlugVector::const_iterator it = m_plugs.begin();
2390           it !=  m_plugs.end();
2391           ++it )
2392     {
2393         Plug* pPlug = *it;
2394         std::ostringstream strstrm;
2395         strstrm << basePath << i;
2396         result &= pPlug->serialize( strstrm.str() + "/", ser );
2397         i++;
2398     }
2399     result &= ser.write( basePath + "m_globalIdCounter", m_globalIdCounter );
2400
2401     return result;
2402 }
2403
2404 PlugManager*
2405 PlugManager::deserialize( std::string basePath,
2406                           Util::IODeserialize& deser,
2407                           Unit& unit )
2408
2409 {
2410     PlugManager* pMgr = new PlugManager;
2411
2412     if ( !pMgr ) {
2413         return 0;
2414     }
2415
2416     if(!deser.read( basePath + "m_globalIdCounter", pMgr->m_globalIdCounter )) {
2417         pMgr->m_globalIdCounter = 0;
2418     }
2419
2420     int i = 0;
2421     Plug* pPlug = 0;
2422     do {
2423         std::ostringstream strstrm;
2424         strstrm << basePath << i;
2425         // unit still holds a null pointer for the plug manager
2426         // therefore we have to *this as additional argument
2427         pPlug = Plug::deserialize( strstrm.str() + "/",
2428                                    deser,
2429                                    unit,
2430                                    *pMgr );
2431         if ( pPlug ) {
2432             pMgr->m_plugs.push_back( pPlug );
2433             i++;
2434         }
2435     } while ( pPlug );
2436
2437     return pMgr;
2438 }
2439
2440 bool
2441 PlugManager::deserializeUpdate( std::string basePath,
2442                                 Util::IODeserialize& deser)
2443 {
2444     bool result = true;
2445
2446     for ( PlugVector::const_iterator it = m_plugs.begin();
2447           it !=  m_plugs.end();
2448           ++it )
2449     {
2450
2451         Plug* pPlug = *it;
2452
2453         std::ostringstream strstrm;
2454         strstrm << basePath << "Plug" << pPlug->getGlobalId();
2455
2456         result &= pPlug->deserializeConnections( strstrm.str(), deser );
2457         result &= pPlug->deserializeUpdateSubunit();
2458     }
2459
2460     return result;
2461 }
2462
2463 ////////////////////////////////////
2464
2465 PlugConnection::PlugConnection( Plug& srcPlug, Plug& destPlug )
2466     : m_srcPlug( &srcPlug )
2467     , m_destPlug( &destPlug )
2468 {
2469 }
2470
2471 PlugConnection::PlugConnection()
2472     : m_srcPlug( 0 )
2473     , m_destPlug( 0 )
2474 {
2475 }
2476
2477 bool
2478 PlugConnection::serialize( std::string basePath, Util::IOSerialize& ser ) const
2479 {
2480     bool result;
2481     result  = ser.write( basePath + "m_srcPlug", m_srcPlug->getGlobalId() );
2482     result &= ser.write( basePath + "m_destPlug", m_destPlug->getGlobalId() );
2483     return result;
2484 }
2485
2486 PlugConnection*
2487 PlugConnection::deserialize( std::string basePath,
2488                                Util::IODeserialize& deser,
2489                                Unit& unit )
2490 {
2491     if ( !deser.isExisting( basePath + "m_srcPlug" ) ) {
2492         return 0;
2493     }
2494     PlugConnection* pConnection = new PlugConnection;
2495     if ( !pConnection ) {
2496         return 0;
2497     }
2498
2499     bool result;
2500     int iSrcPlugId;
2501     int iDestPlugId;
2502     result  = deser.read( basePath + "m_srcPlug", iSrcPlugId );
2503     result &= deser.read( basePath + "m_destPlug",  iDestPlugId );
2504
2505     if ( !result ) {
2506         delete pConnection;
2507         return 0;
2508     }
2509
2510     pConnection->m_srcPlug  = unit.getPlugManager().getPlug( iSrcPlugId );
2511     pConnection->m_destPlug = unit.getPlugManager().getPlug( iDestPlugId );
2512
2513     if ( !pConnection->m_srcPlug || !pConnection->m_destPlug ) {
2514         delete pConnection;
2515         return 0;
2516     }
2517
2518     return pConnection;
2519 }
2520
2521 ExtendedStreamFormatCmd
2522 Plug::setPlugAddrToStreamFormatCmd(
2523     ExtendedStreamFormatCmd::ESubFunction subFunction)
2524 {
2525     ExtendedStreamFormatCmd extStreamFormatInfoCmd(
2526         m_unit->get1394Service(),
2527         subFunction );
2528     switch( getSubunitType() ) {
2529     case eST_Unit:
2530     {
2531             UnitPlugAddress::EPlugType ePlugType =
2532                 UnitPlugAddress::ePT_Unknown;
2533             switch ( m_addressType ) {
2534                 case eAPA_PCR:
2535                     ePlugType = UnitPlugAddress::ePT_PCR;
2536                     break;
2537                 case eAPA_ExternalPlug:
2538                     ePlugType = UnitPlugAddress::ePT_ExternalPlug;
2539                     break;
2540                 case eAPA_AsynchronousPlug:
2541                     ePlugType = UnitPlugAddress::ePT_AsynchronousPlug;
2542                     break;
2543                 default:
2544                     ePlugType = UnitPlugAddress::ePT_Unknown;
2545             }
2546         UnitPlugAddress unitPlugAddress( ePlugType,
2547                                          m_id );
2548         extStreamFormatInfoCmd.setPlugAddress(
2549             PlugAddress( convertPlugDirection( getPlugDirection() ),
2550                          PlugAddress::ePAM_Unit,
2551                          unitPlugAddress ) );
2552         }
2553         break;
2554     case eST_Music:
2555     case eST_Audio:
2556     {
2557         switch( m_addressType ) {
2558         case eAPA_SubunitPlug:
2559         {
2560             SubunitPlugAddress subunitPlugAddress( m_id );
2561             extStreamFormatInfoCmd.setPlugAddress(
2562                 PlugAddress( convertPlugDirection( getPlugDirection() ),
2563                              PlugAddress::ePAM_Subunit,
2564                              subunitPlugAddress ) );
2565         }
2566         break;
2567         case eAPA_FunctionBlockPlug:
2568         {
2569             FunctionBlockPlugAddress functionBlockPlugAddress(
2570                 m_functionBlockType,
2571                 m_functionBlockId,
2572                 m_id );
2573             extStreamFormatInfoCmd.setPlugAddress(
2574                 PlugAddress( convertPlugDirection( getPlugDirection() ),
2575                              PlugAddress::ePAM_FunctionBlock,
2576                              functionBlockPlugAddress ) );
2577         }
2578         break;
2579         default:
2580             extStreamFormatInfoCmd.setPlugAddress(PlugAddress());
2581         }
2582     }
2583     break;
2584     default:
2585         debugError( "Unknown subunit type\n" );
2586     }
2587
2588     extStreamFormatInfoCmd.setNodeId( m_unit->getConfigRom().getNodeId() );
2589     extStreamFormatInfoCmd.setCommandType( AVCCommand::eCT_Status );
2590     extStreamFormatInfoCmd.setSubunitId( getSubunitId() );
2591     extStreamFormatInfoCmd.setSubunitType( getSubunitType() );
2592
2593     return extStreamFormatInfoCmd;
2594 }
2595
2596 bool
2597 serializePlugVector( std::string basePath,
2598                      Util::IOSerialize& ser,
2599                      const PlugVector& vec)
2600 {
2601     bool result = true;
2602     int i = 0;
2603     for ( PlugVector::const_iterator it = vec.begin();
2604           it != vec.end();
2605           ++it )
2606     {
2607         const Plug* pPlug = *it;
2608         std::ostringstream strstrm;
2609         strstrm << basePath << i;
2610
2611         result &= ser.write( strstrm.str() + "/global_id", pPlug->getGlobalId() );
2612         i++;
2613     }
2614     return result;
2615 }
2616
2617 bool
2618 deserializePlugVector( std::string basePath,
2619                        Util::IODeserialize& deser,
2620                        const PlugManager& plugManager,
2621                        PlugVector& vec )
2622 {
2623     int i = 0;
2624     Plug* pPlug = 0;
2625     do {
2626         std::ostringstream strstrm;
2627         unsigned int iPlugId;
2628
2629         strstrm << basePath << i;
2630
2631         if ( !deser.isExisting( strstrm.str() + "/global_id" ) ) {
2632             // no more plugs found, so this is the normal return point
2633             return true;
2634         }
2635
2636         if ( !deser.read( strstrm.str() + "/global_id", iPlugId ) ) {
2637             return false;
2638         }
2639  
2640         pPlug = plugManager.getPlug( iPlugId );
2641         if ( pPlug ) {
2642             vec.push_back( pPlug );
2643             i++;
2644         }
2645     } while ( pPlug );
2646
2647     // if we reach here, the plug manager didn't find any plug with the id iPlugId.
2648     return false;
2649 }
2650
2651 }
Note: See TracBrowser for help on using the browser.