root/branches/libfreebob-2.0/src/bebob/bebob_avplug.cpp

Revision 341, 57.3 kB (checked in by pieterpalmers, 17 years ago)

- changed bebob avdevice to use debugmodule instead of printf/cout
- fixed some minor merge side-effects
- implement a RT safe mechanism to obtain the cycle counter.

Line 
1 /* bebob_avplug.cpp
2  * Copyright (C) 2005,06 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "bebob/bebob_avplug.h"
22
23 #include "libfreebobavc/ieee1394service.h"
24 #include "libfreebobavc/serialize.h"
25
26 namespace BeBoB {
27
28 int AvPlug::m_globalIdCounter = 0;
29
30 IMPL_DEBUG_MODULE( AvPlug, AvPlug, DEBUG_LEVEL_NORMAL );
31 IMPL_DEBUG_MODULE( AvPlugManager, AvPlugManager, DEBUG_LEVEL_NORMAL );
32
33 AvPlug::AvPlug( Ieee1394Service& ieee1394Service,
34                 int nodeId,
35                 AvPlugManager& plugManager,
36                 AVCCommand::ESubunitType subunitType,
37                 subunit_id_t subunitId,
38                 function_block_type_t functionBlockType,
39                 function_block_id_t functionBlockId,
40                 EAvPlugAddressType plugAddressType,
41                 EAvPlugDirection plugDirection,
42                 plug_id_t plugId,
43                 int verboseLevel )
44     : m_1394Service( &ieee1394Service )
45     , m_nodeId( nodeId )
46     , m_subunitType( subunitType )
47     , m_subunitId( subunitId )
48     , m_functionBlockType( functionBlockType )
49     , m_functionBlockId( functionBlockId )
50     , m_addressType( plugAddressType )
51     , m_direction( plugDirection )
52     , m_id( plugId )
53     , m_infoPlugType( eAPT_Unknown )
54     , m_nrOfChannels( 0 )
55     , m_plugManager( &plugManager )
56     , m_verboseLevel( verboseLevel )
57     , m_globalId( m_globalIdCounter++ )
58 {
59     setDebugLevel( m_verboseLevel );
60     debugOutput( DEBUG_LEVEL_VERBOSE,
61                  "nodeId = %d, subunitType = %d, "
62                  "subunitId = %d, functionBlockType = %d, "
63                  "functionBlockId = %d, addressType = %d, "
64                  "direction = %d, id = %d\n",
65                  m_nodeId,
66                  m_subunitType,
67                  m_subunitId,
68                  m_functionBlockType,
69                  m_functionBlockId,
70                  m_addressType,
71                  m_direction,
72                  m_id );
73 }
74
75 AvPlug::AvPlug( const AvPlug& rhs )
76     : m_1394Service( rhs.m_1394Service )
77     , m_nodeId( rhs.m_nodeId )
78     , m_subunitType( rhs.m_subunitType )
79     , m_subunitId( rhs.m_subunitId )
80     , m_functionBlockType( rhs.m_functionBlockType )
81     , m_functionBlockId( rhs.m_functionBlockId )
82     , m_addressType( rhs.m_addressType )
83     , m_direction( rhs.m_direction )
84     , m_id( rhs.m_id )
85     , m_infoPlugType( rhs.m_infoPlugType )
86     , m_nrOfChannels( rhs.m_nrOfChannels )
87     , m_name( rhs.m_name )
88     , m_clusterInfos( rhs.m_clusterInfos )
89     , m_formatInfos( rhs.m_formatInfos )
90     , m_plugManager( rhs.m_plugManager )
91     , m_verboseLevel( rhs.m_verboseLevel )
92 {
93     if ( m_verboseLevel ) {
94         setDebugLevel( DEBUG_LEVEL_VERBOSE );
95      }
96 }
97
98 AvPlug::~AvPlug()
99 {
100     m_plugManager->remPlug( *this );
101 }
102
103 bool
104 AvPlug::discover()
105 {
106     if ( !discoverPlugType() ) {
107         debugError( "discover: Could not discover plug type (%d,%d,%d,%d,%d)\n",
108                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
109         return false;
110     }
111
112     if ( !discoverName() ) {
113         debugError( "Could not discover name (%d,%d,%d,%d,%d)\n",
114                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
115         return false;
116     }
117
118     if ( !discoverNoOfChannels() ) {
119         debugError( "Could not discover number of channels "
120                     "(%d,%d,%d,%d,%d)\n",
121                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
122         return false;
123     }
124
125     if ( !discoverChannelPosition() ) {
126         debugError( "Could not discover channel positions "
127                     "(%d,%d,%d,%d,%d)\n",
128                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
129         return false;
130     }
131
132     if ( !discoverChannelName() ) {
133         debugError( "Could not discover channel name "
134                     "(%d,%d,%d,%d,%d)\n",
135                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
136         return false;
137     }
138
139     if ( !discoverClusterInfo() ) {
140         debugError( "Could not discover channel name "
141                     "(%d,%d,%d,%d,%d)\n",
142                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
143         return false;
144     }
145
146     if ( !discoverStreamFormat() ) {
147         debugError( "Could not discover stream format "
148                     "(%d,%d,%d,%d,%d)\n",
149                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
150         return false;
151     }
152
153     if ( !discoverSupportedStreamFormats() ) {
154         debugError( "Could not discover supported stream formats "
155                     "(%d,%d,%d,%d,%d)\n",
156                     m_nodeId, m_subunitType, m_subunitId, m_direction, m_id );
157         return false;
158     }
159
160     return m_plugManager->addPlug( *this );
161 }
162
163 bool
164 AvPlug::discoverConnections()
165 {
166     return discoverConnectionsInput() && discoverConnectionsOutput();
167 }
168
169 bool
170 AvPlug::inquireConnnection( AvPlug& plug )
171 {
172     SignalSourceCmd signalSourceCmd = setSrcPlugAddrToSignalCmd();
173     setDestPlugAddrToSignalCmd( signalSourceCmd, plug );
174     signalSourceCmd.setCommandType( AVCCommand::eCT_SpecificInquiry );
175     signalSourceCmd.setVerbose( m_verboseLevel );
176
177     if ( !signalSourceCmd.fire() ) {
178         debugError( "Could not inquire connection between '%s' and '%s'\n",
179                     getName(), plug.getName() );
180         return false;
181     }
182
183     if ( signalSourceCmd.getResponse() == AVCCommand::eR_Implemented ) {
184         debugOutput( DEBUG_LEVEL_VERBOSE,
185                      "Connection possible between '%s' and '%s'\n",
186                      getName(),  plug.getName() );
187         return true;
188     }
189     debugOutput( DEBUG_LEVEL_VERBOSE,
190                  "Connection not possible between '%s' and '%s'\n",
191                  getName(),  plug.getName() );
192     return false;
193 }
194
195 bool
196 AvPlug::setConnection( AvPlug& plug )
197 {
198     SignalSourceCmd signalSourceCmd = setSrcPlugAddrToSignalCmd();
199     setDestPlugAddrToSignalCmd( signalSourceCmd, plug );
200     signalSourceCmd.setCommandType( AVCCommand::eCT_Control );
201     signalSourceCmd.setVerbose( m_verboseLevel );
202
203     if ( !signalSourceCmd.fire() ) {
204         debugError( "Could not set connection between '%s' and '%s'\n",
205                     getName(), plug.getName() );
206         return false;
207     }
208
209     if ( signalSourceCmd.getResponse() == AVCCommand::eR_Accepted ) {
210         debugOutput( DEBUG_LEVEL_VERBOSE,
211                      "Could set connection between '%s' and '%s'\n",
212                      getName(), plug.getName() );
213         return true;
214     }
215     debugOutput( DEBUG_LEVEL_VERBOSE,
216                  "Could not set connection between '%s' and '%s'\n",
217                  getName(),  plug.getName() );
218     return false;
219 }
220
221 int
222 AvPlug::getNrOfStreams() const
223 {
224     int nrOfChannels = 0;
225     for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
226           it != m_clusterInfos.end();
227           ++it )
228     {
229         const ClusterInfo* clusterInfo = &( *it );
230         nrOfChannels += clusterInfo->m_nrOfChannels;
231     }
232     return nrOfChannels;
233 }
234
235 int
236 AvPlug::getNrOfChannels() const
237 {
238     return m_nrOfChannels;
239 }
240
241 int
242 AvPlug::getSampleRate() const
243 {
244     return convertESamplingFrequency( static_cast<ESamplingFrequency>( m_samplingFrequency ) );
245 }
246
247 bool
248 AvPlug::discoverPlugType()
249 {
250     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
251     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
252         ExtendedPlugInfoInfoType::eIT_PlugType );
253     extendedPlugInfoInfoType.initialize();
254     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
255     extPlugInfoCmd.setVerbose( m_verboseLevel );
256
257     if ( !extPlugInfoCmd.fire() ) {
258         debugError( "plug type command failed\n" );
259         return false;
260     }
261
262     m_infoPlugType = eAPT_Unknown;
263
264     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Implemented ) {
265
266         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
267         if ( infoType
268              && infoType->m_plugType )
269         {
270             plug_type_t plugType = infoType->m_plugType->m_plugType;
271
272             debugOutput( DEBUG_LEVEL_VERBOSE,
273                          "plug %d is of type %d (%s)\n",
274                          m_id,
275                          plugType,
276                          extendedPlugInfoPlugTypeToString( plugType ) );
277             switch ( plugType ) {
278             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_IsoStream:
279                 m_infoPlugType = eAPT_IsoStream;
280                 break;
281             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_AsyncStream:
282                 m_infoPlugType = eAPT_AsyncStream;
283                 break;
284             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Midi:
285                 m_infoPlugType = eAPT_Midi;
286                 break;
287             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Sync:
288                 m_infoPlugType = eAPT_Sync;
289                 break;
290             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Analog:
291                 m_infoPlugType = eAPT_Analog;
292                 break;
293             case ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Digital:
294                 m_infoPlugType = eAPT_Digital;
295                 break;
296             default:
297                 m_infoPlugType = eAPT_Unknown;
298
299             }
300         }
301     } else {
302         debugError( "Plug does not implement extended plug info plug "
303                     "type info command\n" );
304         return false;
305     }
306
307    return true;
308 }
309
310 bool
311 AvPlug::discoverName()
312 {
313     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
314     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
315         ExtendedPlugInfoInfoType::eIT_PlugName );
316     extendedPlugInfoInfoType.initialize();
317     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
318     extPlugInfoCmd.setVerbose( m_verboseLevel );
319
320     if ( !extPlugInfoCmd.fire() ) {
321         debugError( "name command failed\n" );
322         return false;
323     }
324
325     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
326     if ( infoType
327          && infoType->m_plugName )
328     {
329         std::string name =
330             infoType->m_plugName->m_name;
331
332         debugOutput( DEBUG_LEVEL_VERBOSE,
333                      "plug %d has name '%s'\n",
334                      m_id,
335                      name.c_str() );
336
337         m_name = name;
338     }
339     return true;
340 }
341
342 bool
343 AvPlug::discoverNoOfChannels()
344 {
345     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
346     //extPlugInfoCmd.setVerbose( true );
347     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
348         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
349     extendedPlugInfoInfoType.initialize();
350     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
351     extPlugInfoCmd.setVerbose( m_verboseLevel );
352
353     if ( !extPlugInfoCmd.fire() ) {
354         debugError( "number of channels command failed\n" );
355         return false;
356     }
357
358     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
359     if ( infoType
360          && infoType->m_plugNrOfChns )
361     {
362         nr_of_channels_t nrOfChannels
363             = infoType->m_plugNrOfChns->m_nrOfChannels;
364
365         debugOutput( DEBUG_LEVEL_VERBOSE,
366                      "plug %d has %d channels\n",
367                      m_id,
368                      nrOfChannels );
369
370         m_nrOfChannels = nrOfChannels;
371     }
372     return true;
373 }
374
375 bool
376 AvPlug::discoverChannelPosition()
377 {
378     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
379     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
380         ExtendedPlugInfoInfoType::eIT_ChannelPosition );
381     extendedPlugInfoInfoType.initialize();
382     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
383     extPlugInfoCmd.setVerbose( m_verboseLevel );
384
385     if ( !extPlugInfoCmd.fire() ) {
386         debugError( "channel position command failed\n" );
387         return false;
388     }
389
390     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
391     if ( infoType
392          && infoType->m_plugChannelPosition )
393     {
394         if ( !copyClusterInfo( *( infoType->m_plugChannelPosition ) ) ) {
395             debugError( "Could not copy channel position "
396                         "information\n" );
397             return false;
398         }
399
400         debugOutput( DEBUG_LEVEL_VERBOSE,
401                      "plug %d: channel position information "
402                      "retrieved\n",
403                      m_id );
404
405         debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
406     }
407
408     return true;
409 }
410
411 bool
412 AvPlug::discoverChannelName()
413 {
414     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
415           clit != m_clusterInfos.end();
416           ++clit )
417     {
418         ClusterInfo* clitInfo = &*clit;
419
420         for ( ChannelInfoVector::iterator pit =  clitInfo->m_channelInfos.begin();
421               pit != clitInfo->m_channelInfos.end();
422               ++pit )
423         {
424             ChannelInfo* channelInfo = &*pit;
425
426             ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
427             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
428                 ExtendedPlugInfoInfoType::eIT_ChannelName );
429             extendedPlugInfoInfoType.initialize();
430             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
431             extPlugInfoCmd.setVerbose( m_verboseLevel );
432
433             ExtendedPlugInfoInfoType* infoType =
434                 extPlugInfoCmd.getInfoType();
435             if ( infoType ) {
436                 infoType->m_plugChannelName->m_streamPosition =
437                     channelInfo->m_streamPosition;
438             }
439             if ( !extPlugInfoCmd.fire() ) {
440                 debugError( "channel name command failed\n" );
441                 return false;
442             }
443             infoType = extPlugInfoCmd.getInfoType();
444             if ( infoType
445                  && infoType->m_plugChannelName )
446             {
447                 debugOutput( DEBUG_LEVEL_VERBOSE,
448                              "plug %d stream "
449                              "position %d: channel name = %s\n",
450                              m_id,
451                              channelInfo->m_streamPosition,
452                              infoType->m_plugChannelName->m_plugChannelName.c_str() );
453                 channelInfo->m_name =
454                     infoType->m_plugChannelName->m_plugChannelName;
455             }
456
457         }
458     }
459
460     return true;
461 }
462
463 bool
464 AvPlug::discoverClusterInfo()
465 {
466     if ( m_infoPlugType == eAPT_Sync )
467     {
468         // If the plug is of type sync it is either a normal 2 channel
469         // stream (not compound stream) or it is a compound stream
470         // with exactly one cluster. This depends on the
471         // extended stream format command version which is used.
472         // We are not interested in this plug so we skip it.
473         debugOutput( DEBUG_LEVEL_VERBOSE,
474                      "%s plug %d is of type sync -> skip\n",
475                      getName(),
476                      m_id );
477         return true;
478     }
479
480     for ( ClusterInfoVector::iterator clit = m_clusterInfos.begin();
481           clit != m_clusterInfos.end();
482           ++clit )
483     {
484         ClusterInfo* clusterInfo = &*clit;
485
486         ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
487         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
488             ExtendedPlugInfoInfoType::eIT_ClusterInfo );
489         extendedPlugInfoInfoType.initialize();
490         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
491         extPlugInfoCmd.setVerbose( m_verboseLevel );
492
493         extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
494             clusterInfo->m_index;
495
496         if ( !extPlugInfoCmd.fire() ) {
497             debugError( "cluster info command failed\n" );
498             return false;
499         }
500
501         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
502         if ( infoType
503              && infoType->m_plugClusterInfo )
504         {
505             debugOutput( DEBUG_LEVEL_VERBOSE,
506                          "%s plug %d: cluster index = %d, "
507                          "portType %s, cluster name = %s\n",
508                          getName(),
509                          m_id,
510                          infoType->m_plugClusterInfo->m_clusterIndex,
511                          extendedPlugInfoClusterInfoPortTypeToString(
512                              infoType->m_plugClusterInfo->m_portType ),
513                          infoType->m_plugClusterInfo->m_clusterName.c_str() );
514
515             clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
516             clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
517         }
518     }
519
520     return true;
521 }
522
523 bool
524 AvPlug::discoverStreamFormat()
525 {
526     ExtendedStreamFormatCmd extStreamFormatCmd =
527         setPlugAddrToStreamFormatCmd( ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand );
528     extStreamFormatCmd.setVerbose( m_verboseLevel );
529
530     if ( !extStreamFormatCmd.fire() ) {
531         debugError( "stream format command failed\n" );
532         return false;
533     }
534
535     if ( ( extStreamFormatCmd.getStatus() ==  ExtendedStreamFormatCmd::eS_NoStreamFormat )
536          || ( extStreamFormatCmd.getStatus() ==  ExtendedStreamFormatCmd::eS_NotUsed ) )
537     {
538         debugOutput( DEBUG_LEVEL_VERBOSE,
539                      "No stream format information available\n" );
540         return true;
541     }
542
543     if ( !extStreamFormatCmd.getFormatInformation() ) {
544         debugWarning( "No stream format information for plug found -> skip\n" );
545         return true;
546     }
547
548     if ( extStreamFormatCmd.getFormatInformation()->m_root
549            != FormatInformation::eFHR_AudioMusic  )
550     {
551         debugWarning( "Format hierarchy root is not Audio&Music -> skip\n" );
552         return true;
553     }
554
555     FormatInformation* formatInfo =
556         extStreamFormatCmd.getFormatInformation();
557     FormatInformationStreamsCompound* compoundStream
558         = dynamic_cast< FormatInformationStreamsCompound* > (
559             formatInfo->m_streams );
560     if ( compoundStream ) {
561         m_samplingFrequency =
562             compoundStream->m_samplingFrequency;
563         debugOutput( DEBUG_LEVEL_VERBOSE,
564                      "%s plug %d uses "
565                      "sampling frequency %d, nr of stream infos = %d\n",
566                      getName(),
567                      m_id,
568                      m_samplingFrequency,
569                      compoundStream->m_numberOfStreamFormatInfos );
570
571         for ( int i = 1;
572               i <= compoundStream->m_numberOfStreamFormatInfos;
573               ++i )
574         {
575             ClusterInfo* clusterInfo =
576                 const_cast<ClusterInfo*>( getClusterInfoByIndex( i ) );
577
578             if ( !clusterInfo ) {
579                 debugError( "No matching cluster "
580                             "info found for index %d\n",  i );
581                     return false;
582             }
583             StreamFormatInfo* streamFormatInfo =
584                 compoundStream->m_streamFormatInfos[ i - 1 ];
585
586             debugOutput( DEBUG_LEVEL_VERBOSE,
587                          "number of channels = %d, stream format = %d\n",
588                          streamFormatInfo->m_numberOfChannels,
589                          streamFormatInfo->m_streamFormat );
590
591             int nrOfChannels = clusterInfo->m_nrOfChannels;
592             if ( streamFormatInfo->m_streamFormat ==
593                  FormatInformation::eFHL2_AM824_MIDI_CONFORMANT )
594             {
595                 // 8 logical midi channels fit into 1 channel
596                 nrOfChannels = ( ( nrOfChannels + 7 ) / 8 );
597             }
598             // sanity check
599             if ( nrOfChannels != streamFormatInfo->m_numberOfChannels )
600             {
601                 debugWarning( "Number of channels "
602                               "mismatch: '%s' plug discovering reported "
603                               "%d channels for cluster '%s', while stream "
604                               "format reported %d\n",
605                               getName(),
606                               nrOfChannels,
607                               clusterInfo->m_name.c_str(),
608                               streamFormatInfo->m_numberOfChannels);
609             }
610             clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat;
611
612             debugOutput( DEBUG_LEVEL_VERBOSE,
613                          "%s plug %d cluster info %d ('%s'): "
614                          "stream format %d\n",
615                          getName(),
616                          m_id,
617                          i,
618                          clusterInfo->m_name.c_str(),
619                          clusterInfo->m_streamFormat );
620         }
621     }
622
623     FormatInformationStreamsSync* syncStream
624         = dynamic_cast< FormatInformationStreamsSync* > (
625             formatInfo->m_streams );
626     if ( syncStream ) {
627         m_samplingFrequency =
628             syncStream->m_samplingFrequency;
629         debugOutput( DEBUG_LEVEL_VERBOSE,
630                      "%s plug %d is sync stream with sampling frequency %d\n",
631                      getName(),
632                      m_id,
633                      m_samplingFrequency );
634     }
635
636
637     if ( !compoundStream && !syncStream )
638     {
639         debugError( "Unsupported stream format\n" );
640         return false;
641     }
642
643     return true;
644 }
645
646 bool
647 AvPlug::discoverSupportedStreamFormats()
648 {
649     ExtendedStreamFormatCmd extStreamFormatCmd =
650         setPlugAddrToStreamFormatCmd(
651             ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList);
652     extStreamFormatCmd.setVerbose( m_verboseLevel );
653
654     int i = 0;
655     bool cmdSuccess = false;
656
657     do {
658         extStreamFormatCmd.setIndexInStreamFormat( i );
659         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
660         cmdSuccess = extStreamFormatCmd.fire();
661         if ( cmdSuccess
662              && ( extStreamFormatCmd.getResponse()
663                   == AVCCommand::eR_Implemented ) )
664         {
665             FormatInfo formatInfo;
666             formatInfo.m_index = i;
667             bool formatInfoIsValid = true;
668
669             FormatInformationStreamsSync* syncStream
670                 = dynamic_cast< FormatInformationStreamsSync* >
671                 ( extStreamFormatCmd.getFormatInformation()->m_streams );
672             if ( syncStream ) {
673                 formatInfo.m_samplingFrequency =
674                     syncStream->m_samplingFrequency;
675                 formatInfo.m_isSyncStream = true ;
676             }
677
678             FormatInformationStreamsCompound* compoundStream
679                 = dynamic_cast< FormatInformationStreamsCompound* >
680                 ( extStreamFormatCmd.getFormatInformation()->m_streams );
681             if ( compoundStream ) {
682                 formatInfo.m_samplingFrequency =
683                     compoundStream->m_samplingFrequency;
684                 formatInfo.m_isSyncStream = false;
685                 for ( int j = 0;
686                       j < compoundStream->m_numberOfStreamFormatInfos;
687                       ++j )
688                 {
689                     switch ( compoundStream->m_streamFormatInfos[j]->m_streamFormat ) {
690                     case AVC1394_STREAM_FORMAT_AM824_IEC60968_3:
691                         formatInfo.m_audioChannels +=
692                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
693                         break;
694                     case AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_RAW:
695                         formatInfo.m_audioChannels +=
696                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
697                         break;
698                     case AVC1394_STREAM_FORMAT_AM824_MIDI_CONFORMANT:
699                         formatInfo.m_midiChannels +=
700                             compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
701                         break;
702                     default:
703                         formatInfoIsValid = false;
704                         debugWarning("unknown stream format (0x%02x) for channel "
705                                       "(%d)\n",
706                                      compoundStream->m_streamFormatInfos[j]->m_streamFormat,
707                                      j );
708                     }
709                 }
710             }
711
712             if ( formatInfoIsValid ) {
713                 debugOutput( DEBUG_LEVEL_VERBOSE,
714                              "[%s:%d] formatInfo[%d].m_samplingFrequency "
715                              "= %d\n",
716                              getName(), m_id,
717                              i, formatInfo.m_samplingFrequency );
718                 debugOutput( DEBUG_LEVEL_VERBOSE,
719                              "[%s:%d] formatInfo[%d].m_isSyncStream = %d\n",
720                              getName(), m_id,
721                              i, formatInfo.m_isSyncStream );
722                 debugOutput( DEBUG_LEVEL_VERBOSE,
723                              "[%s:%d] formatInfo[%d].m_audioChannels = %d\n",
724                              getName(), m_id,
725                              i, formatInfo.m_audioChannels );
726                 debugOutput( DEBUG_LEVEL_VERBOSE,
727                              "[%s:%d] formatInfo[%d].m_midiChannels = %d\n",
728                              getName(), m_id,
729                              i, formatInfo.m_midiChannels );
730                 m_formatInfos.push_back( formatInfo );
731             }
732         }
733
734         ++i;
735     } while ( cmdSuccess && ( extStreamFormatCmd.getResponse()
736                               == ExtendedStreamFormatCmd::eR_Implemented ) );
737
738     return true;
739 }
740
741
742 bool
743 AvPlug::discoverConnectionsInput()
744 {
745     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
746     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
747         ExtendedPlugInfoInfoType::eIT_PlugInput );
748     extendedPlugInfoInfoType.initialize();
749     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
750     extPlugInfoCmd.setVerbose( m_verboseLevel );
751
752     if ( !extPlugInfoCmd.fire() ) {
753         debugError( "plug type command failed\n" );
754         return false;
755     }
756
757     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
758         // Plugs does not like to be asked about connections
759         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
760                      "connections command\n",
761                      getName() );
762         return true;
763     }
764
765     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
766     if ( infoType
767          && infoType->m_plugInput )
768     {
769         PlugAddressSpecificData* plugAddress
770             = infoType->m_plugInput->m_plugAddress;
771
772         if ( plugAddress->m_addressMode ==
773              PlugAddressSpecificData::ePAM_Undefined )
774         {
775             // This plug has no input connection
776             return true;
777         }
778
779         if ( !discoverConnectionsFromSpecificData( eAPD_Input,
780                                                    plugAddress,
781                                                    m_inputConnections ) )
782         {
783             debugWarning( "Could not discover connnections for plug '%s'\n",
784                           getName() );
785         }
786     } else {
787         debugError( "no valid info type for plug '%s'\n", getName() );
788         return false;
789     }
790
791     return true;
792 }
793
794 bool
795 AvPlug::discoverConnectionsOutput()
796 {
797     ExtendedPlugInfoCmd extPlugInfoCmd = setPlugAddrToPlugInfoCmd();
798     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
799         ExtendedPlugInfoInfoType::eIT_PlugOutput );
800     extendedPlugInfoInfoType.initialize();
801     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
802     extPlugInfoCmd.setVerbose( m_verboseLevel );
803
804     if ( !extPlugInfoCmd.fire() ) {
805         debugError( "plug type command failed\n" );
806         return false;
807     }
808
809     if ( extPlugInfoCmd.getResponse() == AVCCommand::eR_Rejected ) {
810         // Plugs does not like to be asked about connections
811         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug '%s' rejects "
812                      "connections command\n",
813                      getName() );
814         return true;
815     }
816
817     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
818     if ( infoType
819          && infoType->m_plugOutput )
820     {
821         if ( infoType->m_plugOutput->m_nrOfOutputPlugs
822              != infoType->m_plugOutput->m_outputPlugAddresses.size() )
823         {
824             debugError( "number of output plugs (%d) disagree with "
825                         "number of elements in plug address vector (%d)\n",
826                         infoType->m_plugOutput->m_nrOfOutputPlugs,
827                         infoType->m_plugOutput->m_outputPlugAddresses.size());
828         }
829
830         if ( infoType->m_plugOutput->m_nrOfOutputPlugs == 0 ) {
831             // This plug has no output connections
832             return true;
833         }
834
835         for ( unsigned int i = 0;
836               i < infoType->m_plugOutput->m_outputPlugAddresses.size();
837               ++i )
838         {
839             PlugAddressSpecificData* plugAddress
840                 = infoType->m_plugOutput->m_outputPlugAddresses[i];
841
842             if ( !discoverConnectionsFromSpecificData( eAPD_Output,
843                                                        plugAddress,
844                                                        m_outputConnections ) )
845             {
846                 debugWarning( "Could not discover connnections for "
847                               "plug '%s'\n", getName() );
848             }
849         }
850     } else {
851         debugError( "no valid info type for plug '%s'\n", getName() );
852         return false;
853     }
854
855     return true;
856 }
857
858 bool
859 AvPlug::discoverConnectionsFromSpecificData(
860     EAvPlugDirection discoverDirection,
861     PlugAddressSpecificData* plugAddress,
862     AvPlugVector& connections )
863 {
864     UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
865         dynamic_cast<UnitPlugSpecificDataPlugAddress*>
866         ( plugAddress->m_plugAddressData );
867
868     SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
869         dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
870         ( plugAddress->m_plugAddressData );
871
872     FunctionBlockPlugSpecificDataPlugAddress*
873         pFunctionBlockPlugAddress =
874         dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
875         ( plugAddress->m_plugAddressData );
876
877     AvPlug* plug = getPlugDefinedBySpecificData(
878         pUnitPlugAddress,
879         pSubunitPlugAddress,
880         pFunctionBlockPlugAddress );
881
882     if ( plug ) {
883         debugOutput( DEBUG_LEVEL_VERBOSE,
884                      "'(%d) %s' has a connection to '(%d) %s'\n",
885                      getGlobalId(),
886                      getName(),
887                      plug->getGlobalId(),
888                      plug->getName() );
889         addPlugConnection( connections, *plug );
890     } else {
891         debugError( "no corresponding plug found for '(%d) %s'\n",
892                     getGlobalId(),
893                     getName() );
894         return false;
895     }
896
897     return true;
898 }
899
900 bool
901 AvPlug::addPlugConnection( AvPlugVector& connections,
902                            AvPlug& plug )
903
904 {
905     for ( AvPlugVector::iterator it = connections.begin();
906           it != connections.end();
907           ++it )
908     {
909         AvPlug* cPlug = *it;
910         if ( cPlug == &plug ) {
911             debugOutput( DEBUG_LEVEL_VERBOSE,
912                          "plug '%s' already in connection list\n",
913                          plug.getName() );
914             return true;
915         }
916     }
917
918     connections.push_back( &plug );
919     return true;
920 }
921
922 ExtendedPlugInfoCmd
923 AvPlug::setPlugAddrToPlugInfoCmd()
924 {
925     ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
926
927     switch( m_subunitType ) {
928     case AVCCommand::eST_Unit:
929         {
930             UnitPlugAddress::EPlugType ePlugType =
931                 UnitPlugAddress::ePT_Unknown;
932             switch ( m_addressType ) {
933                 case eAPA_PCR:
934                     ePlugType = UnitPlugAddress::ePT_PCR;
935                     break;
936                 case eAPA_ExternalPlug:
937                     ePlugType = UnitPlugAddress::ePT_ExternalPlug;
938                     break;
939                 case eAPA_AsynchronousPlug:
940                     ePlugType = UnitPlugAddress::ePT_AsynchronousPlug;
941                     break;
942                 default:
943                     ePlugType = UnitPlugAddress::ePT_Unknown;
944             }
945             UnitPlugAddress unitPlugAddress( ePlugType,
946                                              m_id );
947             extPlugInfoCmd.setPlugAddress(
948                 PlugAddress( convertPlugDirection( getPlugDirection() ),
949                              PlugAddress::ePAM_Unit,
950                              unitPlugAddress ) );
951         }
952         break;
953     case AVCCommand::eST_Music:
954     case AVCCommand::eST_Audio:
955         {
956             switch( m_addressType ) {
957             case eAPA_SubunitPlug:
958             {
959                 SubunitPlugAddress subunitPlugAddress( m_id );
960                 extPlugInfoCmd.setPlugAddress(
961                     PlugAddress(
962                         convertPlugDirection( getPlugDirection() ),
963                         PlugAddress::ePAM_Subunit,
964                         subunitPlugAddress ) );
965             }
966             break;
967             case eAPA_FunctionBlockPlug:
968             {
969                 FunctionBlockPlugAddress functionBlockPlugAddress(
970                     m_functionBlockType,
971                     m_functionBlockId,
972                     m_id );
973                 extPlugInfoCmd.setPlugAddress(
974                     PlugAddress(
975                         convertPlugDirection( getPlugDirection() ),
976                         PlugAddress::ePAM_FunctionBlock,
977                         functionBlockPlugAddress ) );
978             }
979             break;
980             default:
981                 extPlugInfoCmd.setPlugAddress(PlugAddress());
982             }
983         }
984         break;
985     default:
986         debugError( "Unknown subunit type\n" );
987     }
988
989     extPlugInfoCmd.setNodeId( m_nodeId );
990     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
991     extPlugInfoCmd.setSubunitId( m_subunitId );
992     extPlugInfoCmd.setSubunitType( m_subunitType );
993
994     return extPlugInfoCmd;
995 }
996
997 ExtendedStreamFormatCmd
998 AvPlug::setPlugAddrToStreamFormatCmd(
999     ExtendedStreamFormatCmd::ESubFunction subFunction)
1000 {
1001     ExtendedStreamFormatCmd extStreamFormatInfoCmd(
1002         m_1394Service,
1003         subFunction );
1004     switch( m_subunitType ) {
1005     case AVCCommand::eST_Unit:
1006     {
1007             UnitPlugAddress::EPlugType ePlugType =
1008                 UnitPlugAddress::ePT_Unknown;
1009             switch ( m_addressType ) {
1010                 case eAPA_PCR:
1011                     ePlugType = UnitPlugAddress::ePT_PCR;
1012                     break;
1013                 case eAPA_ExternalPlug:
1014                     ePlugType = UnitPlugAddress::ePT_ExternalPlug;
1015                     break;
1016                 case eAPA_AsynchronousPlug:
1017                     ePlugType = UnitPlugAddress::ePT_AsynchronousPlug;
1018                     break;
1019                 default:
1020                     ePlugType = UnitPlugAddress::ePT_Unknown;
1021             }
1022         UnitPlugAddress unitPlugAddress( ePlugType,
1023                                          m_id );
1024         extStreamFormatInfoCmd.setPlugAddress(
1025             PlugAddress( convertPlugDirection( getPlugDirection() ),
1026                          PlugAddress::ePAM_Unit,
1027                          unitPlugAddress ) );
1028         }
1029         break;
1030     case AVCCommand::eST_Music:
1031     case AVCCommand::eST_Audio:
1032     {
1033         switch( m_addressType ) {
1034         case eAPA_SubunitPlug:
1035         {
1036             SubunitPlugAddress subunitPlugAddress( m_id );
1037             extStreamFormatInfoCmd.setPlugAddress(
1038                 PlugAddress( convertPlugDirection( getPlugDirection() ),
1039                              PlugAddress::ePAM_Subunit,
1040                              subunitPlugAddress ) );
1041         }
1042         break;
1043         case eAPA_FunctionBlockPlug:
1044         {
1045             FunctionBlockPlugAddress functionBlockPlugAddress(
1046                 m_functionBlockType,
1047                 m_functionBlockId,
1048                 m_id );
1049             extStreamFormatInfoCmd.setPlugAddress(
1050                 PlugAddress( convertPlugDirection( getPlugDirection() ),
1051                              PlugAddress::ePAM_FunctionBlock,
1052                              functionBlockPlugAddress ) );
1053         }
1054         break;
1055         default:
1056             extStreamFormatInfoCmd.setPlugAddress(PlugAddress());
1057         }
1058     }
1059     break;
1060     default:
1061         debugError( "Unknown subunit type\n" );
1062     }
1063
1064     extStreamFormatInfoCmd.setNodeId( m_nodeId );
1065     extStreamFormatInfoCmd.setCommandType( AVCCommand::eCT_Status );
1066     extStreamFormatInfoCmd.setSubunitId( m_subunitId );
1067     extStreamFormatInfoCmd.setSubunitType( m_subunitType );
1068
1069     return extStreamFormatInfoCmd;
1070 }
1071
1072 SignalSourceCmd
1073 AvPlug::setSrcPlugAddrToSignalCmd()
1074 {
1075     SignalSourceCmd signalSourceCmd( m_1394Service );
1076
1077     switch( m_subunitType ) {
1078     case AVCCommand::eST_Unit:
1079     {
1080         SignalUnitAddress signalUnitAddr;
1081         if ( getPlugAddressType() == eAPA_ExternalPlug ) {
1082             signalUnitAddr.m_plugId = m_id + 0x80;
1083         } else {
1084             signalUnitAddr.m_plugId = m_id;
1085         }
1086         signalSourceCmd.setSignalSource( signalUnitAddr );
1087     }
1088     break;
1089     case AVCCommand::eST_Music:
1090     case AVCCommand::eST_Audio:
1091     {
1092         SignalSubunitAddress signalSubunitAddr;
1093         signalSubunitAddr.m_subunitType = m_subunitType;
1094         signalSubunitAddr.m_subunitId = m_subunitId;
1095         signalSubunitAddr.m_plugId = m_id;
1096         signalSourceCmd.setSignalSource( signalSubunitAddr );
1097     }
1098     break;
1099     default:
1100         debugError( "Unknown subunit type\n" );
1101     }
1102
1103     signalSourceCmd.setNodeId( m_nodeId );
1104     signalSourceCmd.setSubunitType( AVCCommand::eST_Unit  );
1105     signalSourceCmd.setSubunitId( 0xff );
1106
1107     return signalSourceCmd;
1108 }
1109
1110 void
1111 AvPlug::setDestPlugAddrToSignalCmd(SignalSourceCmd& signalSourceCmd,
1112                                    AvPlug& plug)
1113 {
1114     switch( plug.m_subunitType ) {
1115     case AVCCommand::eST_Unit:
1116     {
1117         SignalUnitAddress signalUnitAddr;
1118         if ( plug.getPlugAddressType() == eAPA_ExternalPlug ) {
1119             signalUnitAddr.m_plugId = plug.m_id + 0x80;
1120         } else {
1121             signalUnitAddr.m_plugId = plug.m_id;
1122         }
1123         signalSourceCmd.setSignalDestination( signalUnitAddr );
1124     }
1125     break;
1126     case AVCCommand::eST_Music:
1127     case AVCCommand::eST_Audio:
1128     {
1129         SignalSubunitAddress signalSubunitAddr;
1130         signalSubunitAddr.m_subunitType = plug.m_subunitType;
1131         signalSubunitAddr.m_subunitId = plug.m_subunitId;
1132         signalSubunitAddr.m_plugId = plug.m_id;
1133         signalSourceCmd.setSignalDestination( signalSubunitAddr );
1134     }
1135     break;
1136     default:
1137         debugError( "Unknown subunit type\n" );
1138     }
1139 }
1140
1141
1142 bool
1143 AvPlug::copyClusterInfo(ExtendedPlugInfoPlugChannelPositionSpecificData&
1144                         channelPositionData )
1145 {
1146     int index = 1;
1147     for ( ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfoVector::const_iterator it
1148               = channelPositionData.m_clusterInfos.begin();
1149           it != channelPositionData.m_clusterInfos.end();
1150           ++it )
1151     {
1152         const ExtendedPlugInfoPlugChannelPositionSpecificData::ClusterInfo*
1153             extPlugSpClusterInfo = &( *it );
1154
1155         ClusterInfo clusterInfo;
1156         clusterInfo.m_nrOfChannels = extPlugSpClusterInfo->m_nrOfChannels;
1157         clusterInfo.m_index = index;
1158         index++;
1159
1160         for (  ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfoVector::const_iterator cit
1161                   = extPlugSpClusterInfo->m_channelInfos.begin();
1162               cit != extPlugSpClusterInfo->m_channelInfos.end();
1163               ++cit )
1164         {
1165             const ExtendedPlugInfoPlugChannelPositionSpecificData::ChannelInfo*
1166                 extPlugSpChannelInfo = &( *cit );
1167
1168             ChannelInfo channelInfo;
1169             channelInfo.m_streamPosition =
1170                 extPlugSpChannelInfo->m_streamPosition;
1171             channelInfo.m_location =
1172                 extPlugSpChannelInfo->m_location;
1173
1174             clusterInfo.m_channelInfos.push_back( channelInfo );
1175         }
1176         m_clusterInfos.push_back( clusterInfo );
1177     }
1178
1179     return true;
1180 }
1181
1182 void
1183 AvPlug::debugOutputClusterInfos( int debugLevel )
1184 {
1185     for ( ClusterInfoVector::const_iterator it = m_clusterInfos.begin();
1186           it != m_clusterInfos.end();
1187           ++it )
1188     {
1189         const ClusterInfo* clusterInfo = &( *it );
1190
1191         debugOutput( debugLevel, "number of channels: %d\n",
1192                      clusterInfo->m_nrOfChannels );
1193
1194         for ( ChannelInfoVector::const_iterator cit
1195                   = clusterInfo->m_channelInfos.begin();
1196               cit != clusterInfo->m_channelInfos.end();
1197               ++cit )
1198         {
1199             const ChannelInfo* channelInfo = &( *cit );
1200             channelInfo = channelInfo;
1201             debugOutput( debugLevel,
1202                          "stream position: %d\n",
1203                          channelInfo->m_streamPosition );
1204             debugOutput( debugLevel,
1205                          "location: %d\n",
1206                          channelInfo->m_location );
1207         }
1208     }
1209 }
1210
1211 const AvPlug::ClusterInfo*
1212 AvPlug::getClusterInfoByIndex(int index) const
1213 {
1214     for ( AvPlug::ClusterInfoVector::const_iterator clit =
1215               m_clusterInfos.begin();
1216           clit != m_clusterInfos.end();
1217           ++clit )
1218     {
1219         const ClusterInfo* info = &*clit;
1220         if ( info->m_index == index ) {
1221             return info;
1222         }
1223     }
1224     return 0;
1225 }
1226
1227 PlugAddress::EPlugDirection
1228 AvPlug::convertPlugDirection( EAvPlugDirection direction )
1229 {
1230     PlugAddress::EPlugDirection dir;
1231     switch ( direction ) {
1232     case AvPlug::eAPD_Input:
1233         dir = PlugAddress::ePD_Input;
1234         break;
1235     case AvPlug::eAPD_Output:
1236         dir = PlugAddress::ePD_Output;
1237         break;
1238     default:
1239         dir = PlugAddress::ePD_Undefined;
1240     }
1241     return dir;
1242 }
1243
1244 void
1245 AvPlug::showPlug() const
1246 {
1247     debugOutput( DEBUG_LEVEL_VERBOSE, "\tName               = %s\n",
1248                  getName() );
1249     debugOutput( DEBUG_LEVEL_VERBOSE, "\tType               = %s\n",
1250                  extendedPlugInfoPlugTypeToString( getPlugType() ) );
1251     debugOutput( DEBUG_LEVEL_VERBOSE, "\tAddress Type       = %s\n",
1252                  avPlugAddressTypeToString( getPlugAddressType() ) );
1253     debugOutput( DEBUG_LEVEL_VERBOSE, "\tId                 = %d\n",
1254                  getPlugId() );
1255     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitType        = %d\n",
1256                  getSubunitType() );
1257     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSubunitId          = %d\n",
1258                  getSubunitId() );
1259     debugOutput( DEBUG_LEVEL_VERBOSE, "\tDirection          = %s\n",
1260                  avPlugDirectionToString( getPlugDirection() ) );
1261     debugOutput( DEBUG_LEVEL_VERBOSE, "\tSampling Rate      = %d\n",
1262                  getSampleRate() );
1263     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Channels = %d\n",
1264                  getNrOfChannels() );
1265     debugOutput( DEBUG_LEVEL_VERBOSE, "\tNumber of Streams  = %d\n",
1266                  getNrOfStreams() );
1267 }
1268
1269
1270 AvPlug*
1271 AvPlug::getPlugDefinedBySpecificData(
1272     UnitPlugSpecificDataPlugAddress* pUnitPlugAddress,
1273     SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress,
1274     FunctionBlockPlugSpecificDataPlugAddress* pFunctionBlockPlugAddress )
1275 {
1276     subunit_type_t        subunitType       = 0xff;
1277     subunit_id_t          subunitId         = 0xff;
1278     function_block_type_t functionBlockType = 0xff;
1279     function_block_id_t   functionBlockId   = 0xff;
1280     EAvPlugAddressType    addressType       = eAPA_Undefined;
1281     EAvPlugDirection      direction         = eAPD_Unknown;
1282     plug_id_t             plugId            = 0xff;
1283
1284     if ( !pUnitPlugAddress
1285          && !pSubunitPlugAddress
1286          && !pFunctionBlockPlugAddress )
1287     {
1288         debugError( "No correct specific data found\n" );
1289         return 0;
1290     }
1291
1292     if ( pUnitPlugAddress ) {
1293         subunitType = AVCCommand::eST_Unit;
1294         switch ( pUnitPlugAddress->m_plugType ) {
1295         case UnitPlugSpecificDataPlugAddress::ePT_PCR:
1296             addressType = eAPA_PCR;
1297             break;
1298         case UnitPlugSpecificDataPlugAddress::ePT_ExternalPlug:
1299             addressType = eAPA_ExternalPlug;
1300             break;
1301         case UnitPlugSpecificDataPlugAddress::ePT_AsynchronousPlug:
1302             addressType = eAPA_AsynchronousPlug;
1303             break;
1304         }
1305         // unit plug have only connections to subunits
1306         if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1307             direction = getDirection();
1308         } else {
1309             debugError( "Function block has connection from/to unknown "
1310                         "plug type\n" );
1311             direction = eAPD_Unknown;
1312         }
1313         plugId = pUnitPlugAddress->m_plugId;
1314
1315         debugOutput( DEBUG_LEVEL_VERBOSE,
1316                      "'(%d) %s': Remote plug is a unit plug "
1317                      "(%s, %s, %d)\n",
1318                      getGlobalId(),
1319                      getName(),
1320                      avPlugAddressTypeToString( addressType ),
1321                      avPlugDirectionToString( direction ),
1322                      plugId );
1323     }
1324
1325     if ( pSubunitPlugAddress ) {
1326         subunitType = pSubunitPlugAddress->m_subunitType;
1327         subunitId = pSubunitPlugAddress->m_subunitId;
1328         addressType = eAPA_SubunitPlug;
1329
1330         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1331             direction = getDirection();
1332         } else if ( getPlugAddressType() == eAPA_SubunitPlug ) {
1333             direction = toggleDirection( getDirection() );
1334         } else {
1335             // unit
1336             direction = getDirection();
1337         }
1338
1339         plugId = pSubunitPlugAddress->m_plugId;
1340         debugOutput( DEBUG_LEVEL_VERBOSE,
1341                      "'(%d) %s': Remote plug is a subunit plug "
1342                      "(%d, %d, %s, %d)\n",
1343                      getGlobalId(),
1344                      getName(),
1345                      subunitType,
1346                      subunitId,
1347                      avPlugDirectionToString( direction ),
1348                      plugId );
1349     }
1350
1351     if ( pFunctionBlockPlugAddress ) {
1352         subunitType = pFunctionBlockPlugAddress->m_subunitType;
1353         subunitId = pFunctionBlockPlugAddress->m_subunitId;
1354         functionBlockType = pFunctionBlockPlugAddress->m_functionBlockType;
1355         functionBlockId = pFunctionBlockPlugAddress->m_functionBlockId;
1356         addressType = eAPA_FunctionBlockPlug;
1357
1358         if ( getPlugAddressType() == eAPA_FunctionBlockPlug ) {
1359             direction = toggleDirection( getDirection() );
1360         } else if ( getPlugAddressType() == eAPA_SubunitPlug ){
1361             direction = getDirection();
1362         } else {
1363             debugError( "Function block has connection from/to unknown "
1364                         "plug type\n" );
1365             direction = eAPD_Unknown;
1366         }
1367
1368         plugId = pFunctionBlockPlugAddress->m_plugId;
1369
1370         debugOutput( DEBUG_LEVEL_VERBOSE,
1371                      "'(%d) %s': Remote plug is a functionblock plug "
1372                      "(%d, %d, %d, %d, %s, %d)\n",
1373                      getGlobalId(),
1374                      getName(),
1375                      subunitType,
1376                      subunitId,
1377                      functionBlockType,
1378                      functionBlockId,
1379                      avPlugDirectionToString( direction ),
1380                      plugId );
1381     }
1382
1383     AVCCommand::ESubunitType enumSubunitType =
1384         static_cast<AVCCommand::ESubunitType>( subunitType );
1385
1386     return m_plugManager->getPlug(
1387         enumSubunitType,
1388         subunitId,
1389         functionBlockType,
1390         functionBlockId,
1391         addressType,
1392         direction,
1393         plugId );
1394 }
1395
1396 AvPlug::EAvPlugDirection
1397 AvPlug::toggleDirection( EAvPlugDirection direction ) const
1398 {
1399     EAvPlugDirection newDirection;
1400     switch ( direction ) {
1401     case eAPD_Output:
1402         newDirection = eAPD_Input;
1403         break;
1404     case eAPD_Input:
1405         newDirection = eAPD_Output;
1406         break;
1407     default:
1408         newDirection = direction;
1409     }
1410
1411     return newDirection;
1412 }
1413
1414 /////////////////////////////////////////
1415 /////////////////////////////////////////
1416
1417 const char* avPlugAddressTypeStrings[] =
1418 {
1419     "PCR",
1420     "external",
1421     "asynchronous",
1422     "subunit",
1423     "functionblock",
1424     "undefined",
1425 };
1426
1427 const char* avPlugAddressTypeToString( AvPlug::EAvPlugAddressType type )
1428 {
1429     if ( type > ( int )( sizeof( avPlugAddressTypeStrings )
1430                          / sizeof( avPlugAddressTypeStrings[0] ) ) )
1431     {
1432         type = AvPlug::eAPA_Undefined;
1433     }
1434     return avPlugAddressTypeStrings[type];
1435 }
1436
1437 const char* avPlugTypeStrings[] =
1438 {
1439     "IsoStream",
1440     "AsyncStream",
1441     "MIDI",
1442     "Sync",
1443     "Analog",
1444     "Digital",
1445     "Unknown",
1446 };
1447
1448 const char* avPlugTypeToString( AvPlug::EAvPlugType type )
1449 {
1450     if ( type > ( int )( sizeof( avPlugTypeStrings )
1451                          / sizeof( avPlugTypeStrings[0] ) ) )
1452     {
1453         type = AvPlug::eAPT_Unknown;
1454     }
1455     return avPlugTypeStrings[type];
1456 }
1457
1458 const char* avPlugDirectionStrings[] =
1459 {
1460     "Input",
1461     "Output",
1462     "Unknown",
1463 };
1464
1465 const char* avPlugDirectionToString( AvPlug::EAvPlugDirection type )
1466 {
1467     if ( type > ( int )( sizeof( avPlugDirectionStrings )
1468                          / sizeof( avPlugDirectionStrings[0] ) ) )
1469     {
1470         type = AvPlug::eAPD_Unknown;
1471     }
1472     return avPlugDirectionStrings[type];
1473 }
1474
1475 /////////////////////////////////////
1476
1477
1478 AvPlugManager::AvPlugManager( int verboseLevel )
1479     : m_verboseLevel( verboseLevel )
1480 {
1481     setDebugLevel( m_verboseLevel );
1482 }
1483
1484 AvPlugManager::AvPlugManager( const AvPlugManager& rhs )
1485     : m_verboseLevel( rhs.m_verboseLevel )
1486 {
1487     setDebugLevel( m_verboseLevel );
1488 }
1489
1490 AvPlugManager::~AvPlugManager()
1491 {
1492 }
1493
1494 bool
1495 AvPlugManager::addPlug( AvPlug& plug )
1496 {
1497     m_plugs.push_back( &plug );
1498     return true;
1499 }
1500
1501 bool
1502 AvPlugManager::remPlug( AvPlug& plug )
1503 {
1504     for ( AvPlugVector::iterator it = m_plugs.begin();
1505           it !=  m_plugs.end();
1506           ++it )
1507     {
1508         AvPlug* plugIt = *it;
1509         if ( plugIt == &plug ) {
1510             m_plugs.erase( it );
1511             return true;
1512         }
1513     }
1514     return false;
1515 }
1516
1517 // helper function
1518 static void addConnection( AvPlugConnectionOwnerVector& connections,
1519                            AvPlug& srcPlug,
1520                            AvPlug& destPlug )
1521 {
1522     for ( AvPlugConnectionOwnerVector::iterator it = connections.begin();
1523           it != connections.end();
1524           ++it )
1525     {
1526         AvPlugConnection& con = *it;
1527         if ( ( &( con.getSrcPlug() ) == &srcPlug )
1528              && ( &( con.getDestPlug() ) == &destPlug ) )
1529         {
1530             return;
1531         }
1532     }
1533     connections.push_back( AvPlugConnection( srcPlug, destPlug ) );
1534 }
1535
1536 void
1537 AvPlugManager::showPlugs() const
1538 {
1539     // \todo The information provided here could be better arranged. For a start it is ok, but
1540     // there is room for improvement. Something for a lazy sunday afternoon (tip: maybe drink some
1541     // beer to get into the mood)
1542
1543     printf( "\nSummary\n" );
1544     printf( "-------\n\n" );
1545     printf( "Nr | AddressType     | Direction | SubUnitType | SubUnitId | FunctionBlockType | FunctionBlockId | Id   | Type         |Name\n" );
1546     printf( "---+-----------------+-----------+-------------+-----------+-------------------+-----------------+------+--------------+------\n" );
1547
1548     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1549           it !=  m_plugs.end();
1550           ++it )
1551     {
1552         AvPlug* plug = *it;
1553
1554         printf( "%2d | %15s | %9s | %11s |      0x%02x |              0x%02x |            0x%02x | 0x%02x | %12s | %s\n",
1555                 plug->getGlobalId(),
1556                 avPlugAddressTypeToString( plug->getPlugAddressType() ),
1557                 avPlugDirectionToString( plug->getDirection() ),
1558                 subunitTypeToString( plug->getSubunitType() ),
1559                 plug->getSubunitId(),
1560                 plug->getFunctionBlockType(),
1561                 plug->getFunctionBlockId(),
1562                 plug->getPlugId(),
1563                 avPlugTypeToString( plug->getPlugType() ),
1564                 plug->getName() );
1565     }
1566
1567     printf( "\nConnections\n" );
1568     printf( "-----------\n" );
1569
1570     AvPlugConnectionOwnerVector connections;
1571
1572     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1573           it !=  m_plugs.end();
1574           ++it )
1575     {
1576         AvPlug* plug = *it;
1577         for ( AvPlugVector::const_iterator it =
1578                   plug->getInputConnections().begin();
1579             it != plug->getInputConnections().end();
1580             ++it )
1581         {
1582             addConnection( connections, *( *it ), *plug );
1583         }
1584         for ( AvPlugVector::const_iterator it =
1585                   plug->getOutputConnections().begin();
1586             it != plug->getOutputConnections().end();
1587             ++it )
1588         {
1589             addConnection( connections, *plug, *( *it ) );
1590         }
1591     }
1592
1593     printf( "digraph avcconnections {\n" );
1594     for ( AvPlugConnectionOwnerVector::iterator it = connections.begin();
1595           it != connections.end();
1596           ++it )
1597     {
1598         AvPlugConnection& con = *it;
1599         printf( "\t\"(%d) %s\" -> \"(%d) %s\"\n",
1600                 con.getSrcPlug().getGlobalId(),
1601                 con.getSrcPlug().getName(),
1602                 con.getDestPlug().getGlobalId(),
1603                 con.getDestPlug().getName() );
1604     }
1605     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1606           it != m_plugs.end();
1607           ++it )
1608     {
1609         AvPlug* plug = *it;
1610         if ( plug->getFunctionBlockType() != 0xff ) {
1611             if ( plug->getPlugDirection() == AvPlug::eAPD_Input ) {
1612                 printf( "\t\"(%d) %s\" -> \"(0x%02x,%d)\"\n",
1613                         plug->getGlobalId(),
1614                         plug->getName(),
1615                         plug->getFunctionBlockType(),
1616                         plug->getFunctionBlockId() );
1617             } else {
1618                 printf( "\t\"(0x%02x,%d)\" -> \t\"(%d) %s\"\n",
1619                         plug->getFunctionBlockType(),
1620                         plug->getFunctionBlockId(),
1621                         plug->getGlobalId(),
1622                         plug->getName() );
1623             }
1624         }
1625     }
1626
1627     const char* colorStrings[] = {
1628         "coral",
1629         "slateblue",
1630         "white",
1631         "green",
1632         "yellow",
1633         "grey",
1634     };
1635
1636     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1637           it !=  m_plugs.end();
1638           ++it )
1639     {
1640         AvPlug* plug = *it;
1641         printf( "\t\"(%d) %s\" [color=%s,style=filled];\n",
1642                 plug->getGlobalId(), plug->getName(),
1643                 colorStrings[plug->getPlugAddressType() ] );
1644     }
1645
1646     printf("}\n" );
1647     printf( "Use \"dot -Tps FILENAME.dot -o FILENAME.ps\" "
1648             "to generate graph\n");
1649
1650     debugOutput( DEBUG_LEVEL_VERBOSE, "Plug details\n" );
1651     debugOutput( DEBUG_LEVEL_VERBOSE, "------------\n" );
1652     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1653           it !=  m_plugs.end();
1654           ++it )
1655     {
1656         AvPlug* plug = *it;
1657         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d:\n", plug->getGlobalId() );
1658         plug->showPlug();
1659
1660     }
1661 }
1662
1663 AvPlug*
1664 AvPlugManager::getPlug( AVCCommand::ESubunitType subunitType,
1665                         subunit_id_t subunitId,
1666                         function_block_type_t functionBlockType,
1667                         function_block_id_t functionBlockId,
1668                         AvPlug::EAvPlugAddressType plugAddressType,
1669                         AvPlug::EAvPlugDirection plugDirection,
1670                         plug_id_t plugId ) const
1671 {
1672     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, ID = "
1673                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
1674                  subunitType,
1675                  subunitId,
1676                  functionBlockType,
1677                  functionBlockId,
1678                  plugAddressType,
1679                  plugDirection,
1680                  plugId );
1681
1682     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1683           it !=  m_plugs.end();
1684           ++it )
1685     {
1686         AvPlug* plug = *it;
1687
1688         if (    ( subunitType == plug->getSubunitType() )
1689              && ( subunitId == plug->getSubunitId() )
1690              && ( functionBlockType == plug->getFunctionBlockType() )
1691              && ( functionBlockId == plug->getFunctionBlockId() )
1692              && ( plugAddressType == plug->getPlugAddressType() )
1693              && ( plugDirection == plug->getPlugDirection() )
1694              && ( plugId == plug->getPlugId() ) )
1695         {
1696             return plug;
1697         }
1698     }
1699
1700     return 0;
1701 }
1702
1703 AvPlugVector
1704 AvPlugManager::getPlugsByType( AVCCommand::ESubunitType subunitType,
1705                                subunit_id_t subunitId,
1706                                function_block_type_t functionBlockType,
1707                                function_block_id_t functionBlockId,
1708                                AvPlug::EAvPlugAddressType plugAddressType,
1709                                AvPlug::EAvPlugDirection plugDirection,
1710                                AvPlug::EAvPlugType type) const
1711 {
1712     debugOutput( DEBUG_LEVEL_VERBOSE, "SBT, SBID, FBT, FBID, AT, PD, T = "
1713                  "(0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x)\n",
1714                  subunitType,
1715                  subunitId,
1716                  functionBlockType,
1717                  functionBlockId,
1718                  plugAddressType,
1719                  plugDirection,
1720                  type );
1721
1722     AvPlugVector plugVector;
1723     for ( AvPlugVector::const_iterator it = m_plugs.begin();
1724           it !=  m_plugs.end();
1725           ++it )
1726     {
1727         AvPlug* plug = *it;
1728
1729         if (    ( subunitType == plug->getSubunitType() )
1730              && ( subunitId == plug->getSubunitId() )
1731              && ( functionBlockType == plug->getFunctionBlockType() )
1732              && ( functionBlockId == plug->getFunctionBlockId() )
1733              && ( plugAddressType == plug->getPlugAddressType() )
1734              && ( plugDirection == plug->getPlugDirection() )
1735              && ( type == plug->getPlugType() ) )
1736         {
1737             plugVector.push_back( plug );
1738         }
1739     }
1740
1741     return plugVector;
1742 }
1743
1744 ////////////////////////////////////
1745
1746 AvPlugCluster::AvPlugCluster()
1747 {
1748 }
1749
1750 AvPlugCluster::~AvPlugCluster()
1751 {
1752 }
1753
1754 ////////////////////////////////////
1755
1756 AvPlugConnection::AvPlugConnection( AvPlug& srcPlug, AvPlug& destPlug )
1757     : m_srcPlug( &srcPlug )
1758     , m_destPlug( &destPlug )
1759 {
1760 }
1761
1762 }
Note: See TracBrowser for help on using the browser.