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

Revision 1763, 83.1 kB (checked in by ppalmers, 14 years ago)

Merged revisions 1536,1541,1544-1546,1549,1554-1562,1571,1579-1581,1618,1632,1634-1635,1661,1677-1679,1703-1704,1715,1720-1723,1743-1745,1755 via svnmerge from
svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0

Also fix remaining format string warnings.

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