root/trunk/libfreebob/src/avdevice.cpp

Revision 125, 57.5 kB (checked in by wagi, 18 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* avdevice.cpp
2  * Copyright (C) 2005 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 "avdevice.h"
22 #include "configrom.h"
23 #include "avdevicesubunit.h"
24
25 #include "libfreebobavc/avc_plug_info.h"
26 #include "libfreebobavc/avc_extended_plug_info.h"
27 #include "libfreebobavc/avc_subunit_info.h"
28 #include "libfreebobavc/avc_extended_stream_format.h"
29 #include "libfreebobavc/serialize.h"
30 #include "libfreebobavc/ieee1394service.h"
31
32 #include "debugmodule/debugmodule.h"
33
34 #include <iostream>
35
36 using namespace std;
37
38 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_VERBOSE );
39
40 AvDevice::AvDevice( Ieee1394Service* ieee1394service,
41                     ConfigRom* configRom,
42                     int nodeId )
43     : m_1394Service( ieee1394service )
44     , m_configRom( configRom )
45     , m_nodeId( nodeId )
46 {
47     debugOutput( DEBUG_LEVEL_VERBOSE, "Found AvDevice (NodeID %d)\n", nodeId );
48 }
49
50 AvDevice::~AvDevice()
51 {
52     delete m_configRom;
53     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
54           it != m_subunits.end();
55           ++it )
56     {
57         delete *it;
58     }
59     for ( AvPlugConnectionVector::iterator it = m_plugConnections.begin();
60           it != m_plugConnections.end();
61           ++it )
62     {
63         delete *it;
64     }
65     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
66           it != m_isoInputPlugs.end();
67           ++it )
68     {
69         delete *it;
70     }
71     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
72           it != m_isoOutputPlugs.end();
73           ++it )
74     {
75         delete *it;
76     }
77 }
78
79 bool
80 AvDevice::discover()
81 {
82     if ( !enumerateSubUnits() ) {
83         debugError( "Could not enumarate sub units\n" );
84         return false;
85     }
86
87     if ( !discoverStep1() ) {
88         debugError( "Discover step 1 failed\n" );
89         return false;
90     }
91     if ( !discoverStep2() ) {
92         debugError( "Discover step 2 failed\n" );
93         return false;
94     }
95     if ( !discoverStep3() ) {
96         debugError( "Discover step 3 failed\n" );
97         return false;
98     }
99     if ( !discoverStep4() ) {
100         debugError( "Discover step 4 failed\n" );
101         return false;
102     }
103     if ( !discoverStep5() ) {
104         debugError( "Discover step 5 failed\n" );
105         return false;
106     }
107     if ( !discoverStep6() ) {
108         debugError( "Discover step 6 failed\n" );
109         return false;
110     }
111     if ( !discoverStep7() ) {
112         debugError( "Discover step 7 failed\n" );
113         return false;
114     }
115     if ( !discoverStep8() ) {
116         debugError( "Discover step 8 failed\n" );
117         return false;
118     }
119     if ( !discoverStep9() ) {
120         debugError( "Discover step 9 failed\n" );
121         return false;
122     }
123
124     return true;
125 }
126
127 bool
128 AvDevice::discoverStep1()
129 {
130     //////////////////////////////////////////////
131     // Step 1: Get number of available isochronous input
132     // and output plugs of unit
133
134     PlugInfoCmd plugInfoCmd( m_1394Service );
135     plugInfoCmd.setNodeId( m_nodeId );
136     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
137
138     if ( !plugInfoCmd.fire() ) {
139         debugError( "discover: plug info command failed (step 1)\n" );
140         return false;
141     }
142
143     for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousInputPlugs; ++plugId )
144     {
145         AvPlug* plug        = new AvPlug;
146         plug->m_plugId      = plugId;
147         plug->m_subunitType = PlugAddress::ePAM_Unit;
148         plug->m_direction   = PlugAddress::ePD_Input;
149         plug->m_name        = "IsoStreamInput";
150
151         m_isoInputPlugs.push_back( plug );
152     }
153
154     for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousOutputPlugs; ++plugId )
155     {
156         AvPlug* plug        = new AvPlug;
157         plug->m_plugId      = plugId;
158         plug->m_subunitType = PlugAddress::ePAM_Unit;
159         plug->m_direction   = PlugAddress::ePD_Output;
160         plug->m_name        = "IsoStreamOutput";
161
162         m_isoOutputPlugs.push_back( plug );
163     }
164
165     debugOutput( DEBUG_LEVEL_VERBOSE,
166                  "number of iso input plugs = %d, "
167                  "number of iso output plugs = %d\n",
168                  plugInfoCmd.m_serialBusIsochronousInputPlugs,
169                  plugInfoCmd.m_serialBusIsochronousOutputPlugs );
170
171     return true;
172 }
173
174 bool
175 AvDevice::discoverStep2()
176 {
177     //////////////////////////////////////////////
178     // Step 2: For each ISO input plug: get internal
179     // output connections (data sink) of the ISO input plug
180
181     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
182           it != m_isoInputPlugs.end();
183           ++it )
184     {
185         AvPlug* isoInputPlug = *it;
186
187         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
188         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
189                                          isoInputPlug->getPlugId() );
190         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
191                                                     PlugAddress::ePAM_Unit,
192                                                     unitPlugAddress ) );
193         extPlugInfoCmd.setNodeId( m_nodeId );
194         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
195         //extPlugInfoCmd.setVerbose( true );
196         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
197             ExtendedPlugInfoInfoType::eIT_PlugOutput );
198         extendedPlugInfoInfoType.initialize();
199         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
200
201         if ( !extPlugInfoCmd.fire() ) {
202             debugError( "discoverStep2: plug outputs command failed\n" );
203             return false;
204         }
205
206         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
207         if ( infoType
208              && infoType->m_plugOutput )
209         {
210             debugOutput( DEBUG_LEVEL_VERBOSE,
211                          "number of output plugs is %d for iso input "
212                          "plug %d\n",
213                          infoType->m_plugOutput->m_nrOfOutputPlugs,
214                          isoInputPlug->getPlugId() );
215
216             if ( infoType->m_plugOutput->m_nrOfOutputPlugs
217                  != infoType->m_plugOutput->m_outputPlugAddresses.size() )
218             {
219                 debugError( "number of output plugs (%d) disagree with "
220                             "number of elements in plug address vector (%d)\n",
221                             infoType->m_plugOutput->m_nrOfOutputPlugs,
222                             infoType->m_plugOutput->m_outputPlugAddresses.size());
223             }
224             for ( unsigned int i = 0;
225                   i < infoType->m_plugOutput->m_outputPlugAddresses.size();
226                   ++i )
227             {
228                 PlugAddressSpecificData* plugAddress
229                     = infoType->m_plugOutput->m_outputPlugAddresses[i];
230
231
232                 UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
233                     dynamic_cast<UnitPlugSpecificDataPlugAddress*>
234                     ( plugAddress->m_plugAddressData );
235
236                 if ( pUnitPlugAddress ) {
237                     debugOutput( DEBUG_LEVEL_VERBOSE,
238                                  "unit plug address is not handled\n" );
239                 }
240
241                 SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
242                     dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
243                     ( plugAddress->m_plugAddressData );
244
245                 if ( pSubunitPlugAddress ) {
246                     debugOutput( DEBUG_LEVEL_VERBOSE,
247                                  "output plug %d is owned by subunit_type %d, "
248                                  "subunit_id = %d\n",
249                                  pSubunitPlugAddress->m_plugId,
250                                  pSubunitPlugAddress->m_subunitType,
251                                  pSubunitPlugAddress->m_subunitId );
252
253                     if ( !discoverPlugConnection( *isoInputPlug,
254                                                   *pSubunitPlugAddress ) )
255                     {
256                         debugError( "Discovering of plug connection failed\n" );
257                         return false;
258                     }
259                 }
260
261                 FunctionBlockPlugSpecificDataPlugAddress*
262                     pFunctionBlockPlugAddress =
263                     dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
264                     ( plugAddress->m_plugAddressData );
265
266                 if (  pFunctionBlockPlugAddress  ) {
267                     debugOutput( DEBUG_LEVEL_VERBOSE,
268                                  "function block address is not handled\n" );
269                 }
270             }
271         } else {
272             debugError( "discoverStep2: no valid info type, output plug\n" );
273             return false;
274         }
275     }
276
277     return true;
278 }
279
280 bool
281 AvDevice::discoverStep3()
282 {
283     //////////////////////////////////////////////
284     // Step 3: For each ISO output plug: get internal
285     // intput connections (data source) of the ISO output plug
286
287     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
288           it != m_isoOutputPlugs.end();
289           ++it )
290     {
291         AvPlug* isoOutputPlug = *it;
292
293         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
294         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
295                                          isoOutputPlug->getPlugId() );
296         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
297                                                     PlugAddress::ePAM_Unit,
298                                                     unitPlugAddress ) );
299         extPlugInfoCmd.setNodeId( m_nodeId );
300         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
301         //extPlugInfoCmd.setVerbose( true );
302         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
303             ExtendedPlugInfoInfoType::eIT_PlugInput );
304         extendedPlugInfoInfoType.initialize();
305         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
306
307         if ( !extPlugInfoCmd.fire() ) {
308             debugError( "discoverStep3: plug inputs command failed\n" );
309             return false;
310         }
311
312         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
313         if ( infoType
314              && infoType->m_plugInput )
315         {
316             PlugAddressSpecificData* plugAddress
317                 = infoType->m_plugInput->m_plugAddress;
318
319
320             UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
321                 dynamic_cast<UnitPlugSpecificDataPlugAddress*>
322                 ( plugAddress->m_plugAddressData );
323
324             if ( pUnitPlugAddress ) {
325                 debugOutput( DEBUG_LEVEL_VERBOSE,
326                              "unit plug address is not handled\n" );
327             }
328
329             SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
330                 dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
331                 ( plugAddress->m_plugAddressData );
332
333             if ( pSubunitPlugAddress ) {
334                 debugOutput( DEBUG_LEVEL_VERBOSE,
335                              "output plug %d is owned by subunit_type %d, "
336                              "subunit_id %d\n",
337                              pSubunitPlugAddress->m_plugId,
338                              pSubunitPlugAddress->m_subunitType,
339                              pSubunitPlugAddress->m_subunitId );
340
341                 if ( !discoverPlugConnection( *isoOutputPlug, *pSubunitPlugAddress ) ) {
342                     debugError( "Discovering of plug connection failed\n" );
343                     return false;
344                 }
345             }
346
347             FunctionBlockPlugSpecificDataPlugAddress*
348                 pFunctionBlockPlugAddress =
349                 dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
350                 ( plugAddress->m_plugAddressData );
351
352             if (  pFunctionBlockPlugAddress  ) {
353                 debugOutput( DEBUG_LEVEL_VERBOSE,
354                              "function block address is not handled\n" );
355             }
356         } else {
357             debugError( "discoverStep3: no valid info type, input plug\n" );
358             return false;
359         }
360     }
361
362     return true;
363 }
364
365 bool
366 AvDevice::discoverStep4()
367 {
368     //////////////////////////////////////////////
369     // Step 4: For all ISO plugs with valid internal connections:
370     // get type of data stream flowing through plug.
371     // Stream type of interest: iso stream & sync stream
372
373     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
374           it != m_isoInputPlugs.end();
375           ++it )
376     {
377         AvPlug* isoInputPlug = *it;
378
379         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
380         if ( !plugConnection ) {
381             debugOutput( DEBUG_LEVEL_VERBOSE,
382                          "iso input plug %d has no valid connecton -> skip\n",
383                          isoInputPlug->getPlugId() );
384             continue;
385         }
386
387         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
388         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
389                                          isoInputPlug->getPlugId() );
390         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
391                                                     PlugAddress::ePAM_Unit,
392                                                     unitPlugAddress ) );
393         extPlugInfoCmd.setNodeId( m_nodeId );
394         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
395         //extPlugInfoCmd.setVerbose( true );
396         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
397             ExtendedPlugInfoInfoType::eIT_PlugType );
398         extendedPlugInfoInfoType.initialize();
399         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
400
401         if ( !extPlugInfoCmd.fire() ) {
402             debugError( "discoverStep4: plug type command failed\n" );
403             return false;
404         }
405
406         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
407         if ( infoType
408              && infoType->m_plugType )
409         {
410             plug_type_t plugType = infoType->m_plugType->m_plugType;
411
412             debugOutput( DEBUG_LEVEL_VERBOSE,
413                          "iso input plug %d is of type %d (%s)\n",
414                          isoInputPlug->getPlugId(),
415                          plugType,
416                          extendedPlugInfoPlugTypeToString( plugType ) );
417
418             isoInputPlug->m_plugType = plugType;
419         }
420     }
421
422     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
423           it != m_isoOutputPlugs.end();
424           ++it )
425     {
426         AvPlug* isoOutputPlug = *it;
427
428         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
429         if ( !plugConnection ) {
430             debugOutput( DEBUG_LEVEL_VERBOSE,
431                          "iso input plug %d has no valid connecton -> skip\n",
432                          isoOutputPlug->getPlugId() );
433             continue;
434         }
435
436         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
437         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
438                                          isoOutputPlug->getPlugId() );
439         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
440                                                     PlugAddress::ePAM_Unit,
441                                                     unitPlugAddress ) );
442         extPlugInfoCmd.setNodeId( m_nodeId );
443         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
444         //extPlugInfoCmd.setVerbose( true );
445         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
446             ExtendedPlugInfoInfoType::eIT_PlugType );
447         extendedPlugInfoInfoType.initialize();
448         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
449
450         if ( !extPlugInfoCmd.fire() ) {
451             debugError( "discoverStep4: plug type command failed\n" );
452             return false;
453         }
454
455         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
456         if ( infoType
457              && infoType->m_plugType )
458         {
459             plug_type_t plugType = infoType->m_plugType->m_plugType;
460
461             debugOutput( DEBUG_LEVEL_VERBOSE,
462                          "iso output plug %d is of type %d (%s)\n",
463                          isoOutputPlug->getPlugId(),
464                          plugType,
465                          extendedPlugInfoPlugTypeToString( plugType ) );
466
467             isoOutputPlug->m_plugType = plugType;
468         }
469     }
470
471     return true;
472 }
473
474 bool
475 AvDevice::discoverStep5()
476 {
477     //////////////////////////////////////////////
478     // Step 5: For all ISO plugs with valid internal connections:
479     // get data block size of the stream flowing through the plug
480
481     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
482           it != m_isoInputPlugs.end();
483           ++it )
484     {
485         AvPlug* isoInputPlug = *it;
486
487         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
488         if ( !plugConnection ) {
489             debugOutput( DEBUG_LEVEL_VERBOSE,
490                          "iso input plug %d has no valid connecton -> skip\n",
491                          isoInputPlug->getPlugId() );
492             continue;
493         }
494
495         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
496         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
497                                          isoInputPlug->getPlugId() );
498         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
499                                                     PlugAddress::ePAM_Unit,
500                                                     unitPlugAddress ) );
501         extPlugInfoCmd.setNodeId( m_nodeId );
502         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
503         //extPlugInfoCmd.setVerbose( true );
504         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
505             ExtendedPlugInfoInfoType::eIT_NoOfChannels );
506         extendedPlugInfoInfoType.initialize();
507         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
508
509         if ( !extPlugInfoCmd.fire() ) {
510             debugError( "discoverStep5: number of channels command failed\n" );
511             return false;
512         }
513
514         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
515         if ( infoType
516              && infoType->m_plugNrOfChns )
517         {
518             nr_of_channels_t nrOfChannels
519                 = infoType->m_plugNrOfChns->m_nrOfChannels;
520
521             debugOutput( DEBUG_LEVEL_VERBOSE,
522                          "iso input plug %d has %d channels\n",
523                          isoInputPlug->getPlugId(),
524                          nrOfChannels );
525
526             isoInputPlug->m_nrOfChannels = nrOfChannels;
527         }
528     }
529
530     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
531           it != m_isoOutputPlugs.end();
532           ++it )
533     {
534         AvPlug* isoOutputPlug = *it;
535
536         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
537         if ( !plugConnection ) {
538             debugOutput( DEBUG_LEVEL_VERBOSE,
539                          "iso input plug %d has no valid connecton -> skip\n",
540                          isoOutputPlug->getPlugId() );
541             continue;
542         }
543
544         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
545         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
546                                          isoOutputPlug->getPlugId() );
547         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
548                                                     PlugAddress::ePAM_Unit,
549                                                     unitPlugAddress ) );
550         extPlugInfoCmd.setNodeId( m_nodeId );
551         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
552         //extPlugInfoCmd.setVerbose( true );
553         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
554             ExtendedPlugInfoInfoType::eIT_NoOfChannels );
555         extendedPlugInfoInfoType.initialize();
556         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
557
558         if ( !extPlugInfoCmd.fire() ) {
559             debugError( "discoverStep5: nubmer of channels command failed\n" );
560             return false;
561         }
562
563         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
564         if ( infoType
565              && infoType->m_plugNrOfChns )
566         {
567             nr_of_channels_t nrOfChannels
568                 = infoType->m_plugNrOfChns->m_nrOfChannels;
569
570             debugOutput( DEBUG_LEVEL_VERBOSE,
571                          "iso output plug %d has %d channels\n",
572                          isoOutputPlug->getPlugId(),
573                          nrOfChannels );
574
575             isoOutputPlug->m_nrOfChannels = nrOfChannels;
576         }
577     }
578     return true;
579 }
580
581 bool
582 AvDevice::discoverStep6()
583 {
584     //////////////////////////////////////////////
585     // Step 6: For all ISO plugs with valid internal connections:
586     // get position of channels within data block
587
588     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
589           it != m_isoInputPlugs.end();
590           ++it )
591     {
592         AvPlug* isoInputPlug = *it;
593
594         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
595         if ( !plugConnection ) {
596             debugOutput( DEBUG_LEVEL_VERBOSE,
597                          "iso input plug %d has no valid connecton -> skip\n",
598                          isoInputPlug->getPlugId() );
599             continue;
600         }
601
602         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
603         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
604                                          isoInputPlug->getPlugId() );
605         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
606                                                     PlugAddress::ePAM_Unit,
607                                                     unitPlugAddress ) );
608         extPlugInfoCmd.setNodeId( m_nodeId );
609         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
610         //extPlugInfoCmd.setVerbose( true );
611         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
612             ExtendedPlugInfoInfoType::eIT_ChannelPosition );
613         extendedPlugInfoInfoType.initialize();
614         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
615
616         if ( !extPlugInfoCmd.fire() ) {
617             debugError( "discoverStep6: channels position command failed\n" );
618             return false;
619         }
620
621         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
622         if ( infoType
623              && infoType->m_plugChannelPosition )
624         {
625             if ( !isoInputPlug->copyClusterInfo(
626                      *( infoType->m_plugChannelPosition ) ) )
627             {
628                 debugError( "discoverStep6: Could not copy channel position "
629                             "information\n" );
630                 return false;
631             }
632
633             debugOutput( DEBUG_LEVEL_VERBOSE,
634                          "iso input plug %d: channel position information "
635                          "retrieved\n",
636                          isoInputPlug->getPlugId() );
637
638             isoInputPlug->debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
639         }
640     }
641
642     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
643           it != m_isoOutputPlugs.end();
644           ++it )
645     {
646         AvPlug* isoOutputPlug = *it;
647
648         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
649         if ( !plugConnection ) {
650             debugOutput( DEBUG_LEVEL_VERBOSE,
651                          "iso input plug %d has no valid connecton -> skip\n",
652                          isoOutputPlug->getPlugId() );
653             continue;
654         }
655
656         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
657         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
658                                          isoOutputPlug->getPlugId() );
659         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
660                                                     PlugAddress::ePAM_Unit,
661                                                     unitPlugAddress ) );
662         extPlugInfoCmd.setNodeId( m_nodeId );
663         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
664         //extPlugInfoCmd.setVerbose( true );
665         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
666             ExtendedPlugInfoInfoType::eIT_ChannelPosition );
667         extendedPlugInfoInfoType.initialize();
668         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
669
670         if ( !extPlugInfoCmd.fire() ) {
671             debugError( "discoverStep6: channel position command failed\n" );
672             return false;
673         }
674
675         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
676         if ( infoType
677              && infoType->m_plugChannelPosition )
678         {
679             if ( !isoOutputPlug->copyClusterInfo(
680                      *( infoType->m_plugChannelPosition ) ) )
681             {
682                 debugError( "discoverStep6: Could not copy channel position "
683                             "information\n" );
684                 return false;
685             }
686
687             debugOutput( DEBUG_LEVEL_VERBOSE,
688                          "iso output plug %d: channel position information "
689                          "retrieved\n",
690                          isoOutputPlug->getPlugId() );
691
692             isoOutputPlug->debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
693         }
694     }
695
696     return true;
697 }
698
699 bool
700 AvDevice::discoverStep7()
701 {
702     //////////////////////////////////////////////
703     // Step 7: For all ISO plugs with valid internal connections:
704     // get hardware name of channel
705
706     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
707           it != m_isoInputPlugs.end();
708           ++it )
709     {
710         AvPlug* isoInputPlug = *it;
711
712         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
713         if ( !plugConnection ) {
714             debugOutput( DEBUG_LEVEL_VERBOSE,
715                          "iso input plug %d has no valid connecton -> skip\n",
716                          isoInputPlug->getPlugId() );
717             continue;
718         }
719
720         for ( AvPlug::ClusterInfoVector::iterator clit =
721                   isoInputPlug->m_clusterInfos.begin();
722               clit != isoInputPlug->m_clusterInfos.end();
723               ++clit )
724         {
725             AvPlug::ClusterInfo* clitInfo = &*clit;
726
727             for ( AvPlug::ChannelInfoVector::iterator pit =
728                       clitInfo->m_channelInfos.begin();
729                   pit != clitInfo->m_channelInfos.end();
730                   ++pit )
731             {
732                 AvPlug::ChannelInfo* channelInfo = &*pit;
733
734                 ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
735                 UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
736                                                  isoInputPlug->getPlugId() );
737                 extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
738                                                             PlugAddress::ePAM_Unit,
739                                                             unitPlugAddress ) );
740                 extPlugInfoCmd.setNodeId( m_nodeId );
741                 extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
742                 //extPlugInfoCmd.setVerbose( true );
743                 ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
744                     ExtendedPlugInfoInfoType::eIT_ChannelName );
745                 extendedPlugInfoInfoType.initialize();
746                 extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
747
748                 ExtendedPlugInfoInfoType* infoType =
749                     extPlugInfoCmd.getInfoType();
750                 if ( infoType ) {
751                     infoType->m_plugChannelName->m_streamPosition =
752                         channelInfo->m_streamPosition;
753                 }
754                 if ( !extPlugInfoCmd.fire() ) {
755                     debugError( "discoverStep7: channel name command failed\n" );
756                     return false;
757                 }
758                 infoType = extPlugInfoCmd.getInfoType();
759                 if ( infoType
760                      && infoType->m_plugChannelName )
761                 {
762                     debugOutput( DEBUG_LEVEL_VERBOSE,
763                                  "iso input plug %d stream "
764                                  "position %d: channel name = %s\n",
765                                  isoInputPlug->getPlugId(),
766                                  channelInfo->m_streamPosition,
767                                  infoType->m_plugChannelName->m_plugChannelName.c_str() );
768                     channelInfo->m_name =
769                         infoType->m_plugChannelName->m_plugChannelName;
770                 }
771
772             }
773         }
774     }
775
776     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
777           it != m_isoOutputPlugs.end();
778           ++it )
779     {
780         AvPlug* isoOutputPlug = *it;
781
782         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
783         if ( !plugConnection ) {
784             debugOutput( DEBUG_LEVEL_VERBOSE,
785                          "iso output plug %d has no valid connecton -> skip\n",
786                          isoOutputPlug->getPlugId() );
787             continue;
788         }
789
790
791         for ( AvPlug::ClusterInfoVector::iterator clit =
792                   isoOutputPlug->m_clusterInfos.begin();
793               clit != isoOutputPlug->m_clusterInfos.end();
794               ++clit )
795         {
796             AvPlug::ClusterInfo* clitInfo = &*clit;
797
798             for ( AvPlug::ChannelInfoVector::iterator pit =
799                       clitInfo->m_channelInfos.begin();
800                   pit != clitInfo->m_channelInfos.end();
801                   ++pit )
802             {
803                 AvPlug::ChannelInfo* channelInfo = &*pit;
804
805                 ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
806                 UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
807                                                  isoOutputPlug->getPlugId() );
808                 extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
809                                                             PlugAddress::ePAM_Unit,
810                                                             unitPlugAddress ) );
811                 extPlugInfoCmd.setNodeId( m_nodeId );
812                 extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
813                 //extPlugInfoCmd.setVerbose( true );
814                 ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
815                     ExtendedPlugInfoInfoType::eIT_ChannelName );
816                 extendedPlugInfoInfoType.initialize();
817                 extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
818
819                 ExtendedPlugInfoInfoType* infoType =
820                     extPlugInfoCmd.getInfoType();
821                 if ( infoType ) {
822                     infoType->m_plugChannelName->m_streamPosition =
823                         channelInfo->m_streamPosition;
824                 }
825                 if ( !extPlugInfoCmd.fire() ) {
826                     debugError( "discoverStep7: channel name command failed\n" );
827                     return false;
828                 }
829                 infoType = extPlugInfoCmd.getInfoType();
830                 if ( infoType
831                      && infoType->m_plugChannelName )
832                 {
833                     debugOutput( DEBUG_LEVEL_VERBOSE,
834                                  "iso output plug %d stream "
835                                  "position %d: channel name = %s\n",
836                                  isoOutputPlug->getPlugId(),
837                                  channelInfo->m_streamPosition,
838                                  infoType->m_plugChannelName->m_plugChannelName.c_str() );
839                     channelInfo->m_name =
840                         infoType->m_plugChannelName->m_plugChannelName;
841                 }
842             }
843         }
844     }
845
846     return true;
847 }
848
849 bool
850 AvDevice::discoverStep8()
851 {
852     //////////////////////////////////////////////
853     // Step 8: For all ISO plugs with valid internal connections:
854     // get logical input and output streams provided by the device
855
856     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
857           it != m_isoInputPlugs.end();
858           ++it )
859     {
860         AvPlug* isoInputPlug = *it;
861
862         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
863         if ( !plugConnection ) {
864             debugOutput( DEBUG_LEVEL_VERBOSE,
865                          "iso input plug %d has no valid connecton -> skip\n",
866                          isoInputPlug->getPlugId() );
867             continue;
868         }
869
870         for ( AvPlug::ClusterInfoVector::iterator clit =
871                   isoInputPlug->m_clusterInfos.begin();
872               clit != isoInputPlug->m_clusterInfos.end();
873               ++clit )
874         {
875             AvPlug::ClusterInfo* clusterInfo = &*clit;
876
877             ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
878             UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
879                                              isoInputPlug->getPlugId() );
880             extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
881                                                         PlugAddress::ePAM_Unit,
882                                                         unitPlugAddress ) );
883             extPlugInfoCmd.setNodeId( m_nodeId );
884             extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
885             //extPlugInfoCmd.setVerbose( true );
886             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
887                 ExtendedPlugInfoInfoType::eIT_ClusterInfo );
888             extendedPlugInfoInfoType.initialize();
889             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
890
891             extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
892                 clusterInfo->m_index;
893
894             if ( !extPlugInfoCmd.fire() ) {
895                 debugError( "discoverStep8: cluster info command failed\n" );
896                 return false;
897             }
898
899             ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
900             if ( infoType
901                  && infoType->m_plugClusterInfo )
902             {
903                 debugOutput( DEBUG_LEVEL_VERBOSE,
904                              "iso input plug %d: cluster index = %d, "
905                              "portType %s, cluster name = %s\n",
906                              isoInputPlug->getPlugId(),
907                              infoType->m_plugClusterInfo->m_clusterIndex,
908                              extendedPlugInfoClusterInfoPortTypeToString(
909                                  infoType->m_plugClusterInfo->m_portType ),
910                              infoType->m_plugClusterInfo->m_clusterName.c_str() );
911
912                 clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
913                 clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
914             }
915         }
916     }
917
918     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
919           it != m_isoOutputPlugs.end();
920           ++it )
921     {
922         AvPlug* isoOutputPlug = *it;
923
924         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
925         if ( !plugConnection ) {
926             debugOutput( DEBUG_LEVEL_VERBOSE,
927                          "iso output plug %d has no valid connecton -> skip\n",
928                          isoOutputPlug->getPlugId() );
929             continue;
930         }
931
932         // XXX Don't know why plug 1 can't be questioned about the cluster info.
933         // Until I know why this is not working, it's better to skip this then to
934         // break the discovering.
935         if ( isoOutputPlug->getPlugId() > 0 ) {
936             debugWarning( "Skipping plugs with id > 0. Further investigation needed\n" );
937             continue;
938         }
939
940         for ( AvPlug::ClusterInfoVector::iterator clit =
941                   isoOutputPlug->m_clusterInfos.begin();
942               clit != isoOutputPlug->m_clusterInfos.end();
943               ++clit )
944         {
945             AvPlug::ClusterInfo* clusterInfo = &*clit;
946
947             ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
948             UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
949                                              isoOutputPlug->getPlugId() );
950             extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
951                                                         PlugAddress::ePAM_Unit,
952                                                         unitPlugAddress ) );
953             extPlugInfoCmd.setNodeId( m_nodeId );
954             extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
955             //extPlugInfoCmd.setVerbose( true );
956             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
957                 ExtendedPlugInfoInfoType::eIT_ClusterInfo );
958             extendedPlugInfoInfoType.initialize();
959             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
960
961             extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
962                 clusterInfo->m_index;
963
964             if ( !extPlugInfoCmd.fire() ) {
965                 debugError( "discoverStep8: cluster info command failed\n" );
966                 return false;
967             }
968
969             ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
970             if ( infoType
971                  && infoType->m_plugClusterInfo )
972             {
973                 debugOutput( DEBUG_LEVEL_VERBOSE,
974                              "iso output plug %d: cluster index = %d, "
975                              "portType %s, cluster name = %s\n",
976                              isoOutputPlug->getPlugId(),
977                              infoType->m_plugClusterInfo->m_clusterIndex,
978                              extendedPlugInfoClusterInfoPortTypeToString(
979                                  infoType->m_plugClusterInfo->m_portType ),
980                              infoType->m_plugClusterInfo->m_clusterName.c_str() );
981
982                 clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
983                 clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
984             }
985         }
986     }
987
988     return true;
989 }
990
991 bool
992 AvDevice::discoverStep9()
993 {
994     //////////////////////////////////////////////
995     // Step 9: For all ISO plugs with valid internal connections:
996     // get current stream format
997
998     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
999           it != m_isoInputPlugs.end();
1000           ++it )
1001     {
1002         AvPlug* isoInputPlug = *it;
1003
1004         AvPlugConnection* plugConnection = getPlugConnection( *isoInputPlug );
1005         if ( !plugConnection ) {
1006             debugOutput( DEBUG_LEVEL_VERBOSE,
1007                          "iso input plug %d has no valid connecton -> skip\n",
1008                          isoInputPlug->getPlugId() );
1009             continue;
1010         }
1011
1012         ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service );
1013         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
1014                                          isoInputPlug->getPlugId() );
1015         extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
1016                                                         PlugAddress::ePAM_Unit,
1017                                                         unitPlugAddress ) );
1018
1019         extStreamFormatCmd.setNodeId( m_nodeId );
1020         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
1021         //extStreamFormatCmd.setVerbose( true );
1022
1023         if ( !extStreamFormatCmd.fire() ) {
1024             debugError( "discoverStep9: stream format command failed\n" );
1025             return false;
1026         }
1027
1028         FormatInformation* formatInfo =
1029             extStreamFormatCmd.getFormatInformation();
1030         FormatInformationStreamsCompound* compoundStream
1031             = dynamic_cast< FormatInformationStreamsCompound* > (
1032                 formatInfo->m_streams );
1033         if ( compoundStream ) {
1034             isoInputPlug->m_samplingFrequency =
1035                 compoundStream->m_samplingFrequency;
1036             debugOutput( DEBUG_LEVEL_VERBOSE,
1037                          "discoverStep9: iso input plug %d uses "
1038                          "sampling frequency %d\n",
1039                          isoInputPlug->getPlugId(),
1040                          isoInputPlug->m_samplingFrequency );
1041
1042             for ( int i = 1;
1043                   i <= compoundStream->m_numberOfStreamFormatInfos;
1044                   ++i )
1045             {
1046                 AvPlug::ClusterInfo* clusterInfo =
1047                     isoInputPlug->getClusterInfoByIndex( i );
1048
1049                 if ( !clusterInfo ) {
1050                     debugError( "discoverStep9: No matching cluster info found "
1051                                 "for index %d\n",  i );
1052                     return false;
1053                 }
1054                 StreamFormatInfo* streamFormatInfo =
1055                     compoundStream->m_streamFormatInfos[ i - 1 ];
1056
1057                 // sanity checks
1058                 if ( clusterInfo->m_nrOfChannels !=
1059                      streamFormatInfo->m_numberOfChannels )
1060                 {
1061                     debugError( "discoverStep9: Number of channels mismatch\n" );
1062                     return false;
1063                 }
1064                 clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat;
1065
1066                 debugOutput( DEBUG_LEVEL_VERBOSE,
1067                              "iso input plug %d cluster info %d: stream format %d\n",
1068                              isoInputPlug->getPlugId(),
1069                              i,
1070                              clusterInfo->m_streamFormat );
1071             }
1072         }
1073
1074         FormatInformationStreamsSync* syncStream
1075             = dynamic_cast< FormatInformationStreamsSync* > (
1076                 formatInfo->m_streams );
1077         if ( syncStream ) {
1078             isoInputPlug->m_samplingFrequency =
1079                 syncStream->m_samplingFrequency;
1080                 debugOutput( DEBUG_LEVEL_VERBOSE,
1081                              "iso input plug %d is sync stream with sampling frequency %d\n",
1082                              isoInputPlug->getPlugId(),
1083                              isoInputPlug->m_samplingFrequency );
1084         }
1085
1086         if ( !compoundStream && !syncStream ) {
1087             debugError( "discoverStep9: Unsupported stream format\n" );
1088             return false;
1089         }
1090     }
1091
1092     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
1093           it != m_isoOutputPlugs.end();
1094           ++it )
1095     {
1096         AvPlug* isoOutputPlug = *it;
1097
1098         AvPlugConnection* plugConnection = getPlugConnection( *isoOutputPlug );
1099         if ( !plugConnection ) {
1100             debugOutput( DEBUG_LEVEL_VERBOSE,
1101                          "iso output plug %d has no valid connecton -> skip\n",
1102                          isoOutputPlug->getPlugId() );
1103             continue;
1104         }
1105
1106         ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service );
1107         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
1108                                          isoOutputPlug->getPlugId() );
1109         extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
1110                                                         PlugAddress::ePAM_Unit,
1111                                                         unitPlugAddress ) );
1112
1113         extStreamFormatCmd.setNodeId( m_nodeId );
1114         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
1115         //extStreamFormatCmd.setVerbose( true );
1116
1117         if ( !extStreamFormatCmd.fire() ) {
1118             debugError( "discoverStep9: stream format command failed\n" );
1119             return false;
1120         }
1121
1122         FormatInformation* formatInfo =
1123             extStreamFormatCmd.getFormatInformation();
1124         FormatInformationStreamsCompound* compoundStream
1125             = dynamic_cast< FormatInformationStreamsCompound* > (
1126                 formatInfo->m_streams );
1127         if ( compoundStream ) {
1128             isoOutputPlug->m_samplingFrequency =
1129                 compoundStream->m_samplingFrequency;
1130             debugOutput( DEBUG_LEVEL_VERBOSE,
1131                          "discoverStep9: iso output plug %d uses "
1132                          "sampling frequency %d\n",
1133                          isoOutputPlug->getPlugId(),
1134                          isoOutputPlug->m_samplingFrequency );
1135
1136             for ( int i = 1;
1137                   i <= compoundStream->m_numberOfStreamFormatInfos;
1138                   ++i )
1139             {
1140                 AvPlug::ClusterInfo* clusterInfo =
1141                     isoOutputPlug->getClusterInfoByIndex( i );
1142
1143                 if ( !clusterInfo ) {
1144                     debugError( "discoverStep9: No matching cluster info found "
1145                                 "for index %d\n",  i );
1146                     return false;
1147                 }
1148                 StreamFormatInfo* streamFormatInfo =
1149                     compoundStream->m_streamFormatInfos[ i - 1 ];
1150
1151                 // sanity checks
1152                 if ( clusterInfo->m_nrOfChannels !=
1153                      streamFormatInfo->m_numberOfChannels )
1154                 {
1155                     debugError( "discoverStep9: Number of channels mismatch\n" );
1156                     return false;
1157                 }
1158                 clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat;
1159
1160                 debugOutput( DEBUG_LEVEL_VERBOSE,
1161                              "iso output plug %d cluster info %d: stream format %d\n",
1162                              isoOutputPlug->getPlugId(),
1163                              i,
1164                              clusterInfo->m_streamFormat );
1165             }
1166         }
1167
1168         FormatInformationStreamsSync* syncStream
1169             = dynamic_cast< FormatInformationStreamsSync* > (
1170                 formatInfo->m_streams );
1171         if ( syncStream ) {
1172             isoOutputPlug->m_samplingFrequency =
1173                 syncStream->m_samplingFrequency;
1174                 debugOutput( DEBUG_LEVEL_VERBOSE,
1175                              "iso output plug %d is sync stream with sampling frequency %d\n",
1176                              isoOutputPlug->getPlugId(),
1177                              isoOutputPlug->m_samplingFrequency );
1178         }
1179
1180         if ( !compoundStream && !syncStream ) {
1181             debugError( "discoverStep9: Unsupported stream format\n" );
1182             return false;
1183         }
1184     }
1185
1186     return true;
1187 }
1188
1189 bool AvDevice::discoverPlugConnection( AvPlug& srcPlug,
1190                                        SubunitPlugSpecificDataPlugAddress& subunitPlugAddress )
1191 {
1192     AvDeviceSubunit* subunit = getSubunit( subunitPlugAddress.m_subunitType,
1193                                            subunitPlugAddress.m_subunitId );
1194
1195     if ( subunit ) {
1196         debugOutput( DEBUG_LEVEL_VERBOSE,
1197                      "%s plug %d has a valid connection to plug %d of "
1198                      "%s subunit %d \n",
1199                      srcPlug.getName(),
1200                      srcPlug.getPlugId(),
1201                      subunitPlugAddress.m_plugId,
1202                      subunit->getName(),
1203                      subunit->getSubunitId() );
1204
1205         AvPlug* destPlug        = new AvPlug;
1206         destPlug->m_plugId      = subunitPlugAddress.m_plugId;
1207         destPlug->m_subunitType = subunitPlugAddress.m_subunitType;
1208         destPlug->m_subunitId   = subunitPlugAddress.m_subunitId;
1209
1210         if ( !subunit->addPlug( *destPlug ) ) {
1211             debugError( "Could not add plug %d to subunit %d\n",
1212                         destPlug->getPlugId(), subunit->getSubunitId() );
1213             return false;
1214         }
1215
1216         AvPlugConnection* plugConnection = new AvPlugConnection;
1217         plugConnection->m_srcPlug = &srcPlug;
1218         plugConnection->m_destPlug = destPlug;
1219         m_plugConnections.push_back( plugConnection );
1220
1221         return true;
1222     } else {
1223         debugOutput( DEBUG_LEVEL_VERBOSE,
1224                      "found plug address points to unhandled  "
1225                      "subunit -> ignored\n" );
1226     }
1227
1228     return true;
1229 }
1230
1231 bool
1232 AvDevice::enumerateSubUnits()
1233 {
1234     SubUnitInfoCmd subUnitInfoCmd( m_1394Service );
1235     //subUnitInfoCmd.setVerbose( 1 );
1236     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
1237
1238     // BeBob has always exactly one audio and one music subunit. This
1239     // means is fits into the first page of the SubUnitInfo command.
1240     // So there is no need to do more than needed
1241
1242     subUnitInfoCmd.m_page = 0;
1243     subUnitInfoCmd.setNodeId( m_nodeId );
1244     if ( !subUnitInfoCmd.fire() ) {
1245         debugError( "Subunit info command failed\n" );
1246     }
1247
1248     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
1249         subunit_type_t subunit_type
1250             = subUnitInfoCmd.m_table[i].m_subunit_type;
1251         max_subunit_id_t max_subunit_id
1252             = subUnitInfoCmd.m_table[i].m_max_subunit_id;
1253
1254         unsigned int subunitId = getNrOfSubunits( subunit_type );
1255
1256         debugOutput( DEBUG_LEVEL_VERBOSE,
1257                      "subunit_id = %2d, subunit_type = %2d (%s), "
1258                      "max_subunit_ID = %d\n",
1259                      subunitId,
1260                      subunit_type,
1261                      subunitTypeToString( subunit_type ),
1262                      max_subunit_id );
1263
1264         AvDeviceSubunit* subunit = 0;
1265         switch( subunit_type ) {
1266         case AVCCommand::eST_Audio:
1267             subunit = new AvDeviceSubunitAudio( this, subunitId );
1268             if ( !subunit ) {
1269                 debugFatal( "Could not allocate AvDeviceSubunitAudio\n" );
1270                 return false;
1271             }
1272             break;
1273         case AVCCommand::eST_Music:
1274             subunit = new AvDeviceSubunitMusic( this, subunitId );
1275             if ( !subunit ) {
1276                 debugFatal( "Could not allocate AvDeviceSubunitMusic\n" );
1277                 return false;
1278             }
1279             break;
1280         default:
1281             debugOutput( DEBUG_LEVEL_NORMAL,
1282                          "Unsupported subunit found, subunit_type = %d (%s)\n",
1283                          subunit_type,
1284                          subunitTypeToString( subunit_type ) );
1285
1286         }
1287
1288         m_subunits.push_back( subunit );
1289     }
1290
1291     return true;
1292 }
1293
1294
1295 AvDeviceSubunit*
1296 AvDevice::getSubunit( subunit_type_t subunitType,
1297                       subunit_id_t subunitId ) const
1298 {
1299     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
1300           it != m_subunits.end();
1301           ++it )
1302     {
1303         AvDeviceSubunit* subunit = *it;
1304         if ( ( subunitType == subunit->getSubunitType() )
1305              && ( subunitId == subunit->getSubunitId() ) )
1306         {
1307             return subunit;
1308         }
1309     }
1310
1311     return 0;
1312 }
1313
1314
1315 unsigned int
1316 AvDevice::getNrOfSubunits( subunit_type_t subunitType ) const
1317 {
1318     unsigned int nrOfSubunits = 0;
1319
1320     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
1321           it != m_subunits.end();
1322           ++it )
1323     {
1324         AvDeviceSubunit* subunit = *it;
1325         if ( subunitType == subunit->getSubunitType() ) {
1326             nrOfSubunits++;
1327         }
1328     }
1329
1330     return nrOfSubunits;
1331 }
1332
1333 AvPlugConnection*
1334 AvDevice::getPlugConnection( AvPlug& srcPlug ) const
1335 {
1336     for ( AvPlugConnectionVector::const_iterator it
1337               = m_plugConnections.begin();
1338           it != m_plugConnections.end();
1339           ++it )
1340     {
1341         AvPlugConnection* plugConnection = *it;
1342         if ( plugConnection->m_srcPlug == &srcPlug ) {
1343             return plugConnection;
1344         }
1345     }
1346
1347     return 0;
1348 }
1349
1350 AvPlug*
1351 AvDevice::getPlugById( AvPlugVector& plugs, int id )
1352 {
1353     for ( AvPlugVector::iterator it = plugs.begin();
1354           it != plugs.end();
1355           ++it )
1356     {
1357         AvPlug* plug = *it;
1358         if ( id == plug->getPlugId() ) {
1359             return plug;
1360         }
1361     }
1362
1363     return 0;
1364 }
1365
1366 std::string
1367 AvDevice::getVendorName()
1368 {
1369     return m_configRom->getModelName();
1370 }
1371
1372 std::string
1373 AvDevice::getModelName()
1374 {
1375     return m_configRom->getVendorName();
1376 }
1377
1378 bool
1379 AvDevice::addPlugToXmlDescription( AvPlug& plug,
1380                                    xmlNodePtr connectionSet )
1381 {
1382     char* result;
1383     asprintf( &result, "%d", plug.getPlugDirection() );
1384     if ( !xmlNewChild( connectionSet,
1385                        0,
1386                        BAD_CAST "Direction",
1387                        BAD_CAST result ) )
1388     {
1389         debugError( "Couldn't create direction node\n" );
1390         return false;
1391     }
1392
1393     xmlNodePtr connection = xmlNewChild( connectionSet, 0,
1394                                          BAD_CAST "Connection", 0 );
1395     if ( !connection ) {
1396         debugError( "Couldn't create 'Connection' node for "
1397                     "direction %d\n", plug.getPlugDirection() );
1398         return false;
1399     }
1400
1401     asprintf( &result, "%08x%08x",
1402               ( quadlet_t )( m_configRom->getGuid() >> 32 ),
1403               ( quadlet_t )( m_configRom->getGuid() & 0xfffffff ) );
1404     if ( !xmlNewChild( connection,  0,
1405                        BAD_CAST "GUID",  BAD_CAST result ) ) {
1406         debugError( "Couldn't create 'GUID' node\n" );
1407         return false;
1408     }
1409
1410     asprintf( &result, "%d", m_1394Service->getPort() );
1411     if ( !xmlNewChild( connection,  0,
1412                        BAD_CAST "Port",  BAD_CAST result ) ) {
1413         debugError( "Couldn't create 'Port' node\n" );
1414         return false;
1415     }
1416
1417     asprintf( &result, "%d",  m_nodeId);
1418     if ( !xmlNewChild( connection,  0,
1419                        BAD_CAST "NodeId",  BAD_CAST result ) ) {
1420         debugError( "Couldn't create 'NodeId' node\n" );
1421         return false;
1422     }
1423
1424     asprintf( &result, "%d",  plug.getNrOfChannels() );
1425     if ( !xmlNewChild( connection,  0,
1426                        BAD_CAST "Dimension",  BAD_CAST result ) ) {
1427         debugError( "Couldn't create 'Dimension' node\n" );
1428         return false;
1429     }
1430
1431     asprintf( &result, "%d",  plug.getSampleRate() );
1432     if ( !xmlNewChild( connection,  0,
1433                        BAD_CAST "Samplerate",  BAD_CAST result ) ) {
1434         debugError( "Couldn't create 'Samplerate' node\n" );
1435         return false;
1436     }
1437
1438     xmlNodePtr streams = xmlNewChild( connection,  0,
1439                                       BAD_CAST "Streams",  0 );
1440     if ( !streams ) {
1441         debugError( "Couldn't create 'Streams' node for "
1442                     "direction %d\n", plug.getPlugDirection() );
1443         return false;
1444     }
1445
1446     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
1447     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
1448           it != clusterInfos.end();
1449           ++it )
1450     {
1451         const AvPlug::ClusterInfo* clusterInfo = &( *it );
1452
1453         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1454         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1455               it != channelInfos.end();
1456               ++it )
1457         {
1458             const AvPlug::ChannelInfo* channelInfo = &( *it );
1459
1460             xmlNodePtr stream = xmlNewChild( streams,  0,
1461                                              BAD_CAST "Stream",  0 );
1462             if ( !stream ) {
1463                 debugError( "Coulnd't create 'Stream' node" );
1464                 return false;
1465             }
1466
1467             // \todo: iec61883 backend expects indexing starting from 0
1468             // but bebob reports it starting from 1. Decide where
1469             // and how to handle this
1470             asprintf( &result, "%d", channelInfo->m_streamPosition - 1 );
1471             if ( !xmlNewChild( stream,  0,
1472                                BAD_CAST "Position",  BAD_CAST result ) )
1473             {
1474                 debugError( "Couldn't create 'Position' node" );
1475                 return false;
1476             }
1477
1478             asprintf( &result, "%d", channelInfo->m_location );
1479             if ( !xmlNewChild( stream,  0,
1480                                BAD_CAST "Location",  BAD_CAST result ) )
1481             {
1482                 debugError( "Couldn't create 'Location' node" );
1483                 return false;
1484             }
1485
1486             asprintf( &result, "%d", clusterInfo->m_streamFormat );
1487             if ( !xmlNewChild( stream,  0,
1488                                BAD_CAST "Format",  BAD_CAST result ) )
1489             {
1490                 debugError( "Couldn't create 'Format' node" );
1491                 return false;
1492             }
1493
1494             asprintf( &result, "%d", clusterInfo->m_portType );
1495             if ( !xmlNewChild( stream,  0,
1496                                BAD_CAST "Type",  BAD_CAST result ) )
1497             {
1498                 debugError( "Couldn't create 'Type' node" );
1499                 return false;
1500             }
1501
1502             // \todo XXX: What do to do with DestinationPort value??
1503             asprintf( &result, "%d", 0 );
1504             if ( !xmlNewChild( stream,  0,
1505                                BAD_CAST "DestinationPort",  BAD_CAST result ) )
1506             {
1507                 debugError( "Couldn't create 'DestinationPort' node" );
1508                 return false;
1509             }
1510
1511             if ( !xmlNewChild( stream,  0,
1512                                BAD_CAST "Name",
1513                                BAD_CAST channelInfo->m_name.c_str() ) )
1514             {
1515                 debugError( "Couldn't create 'Name' node" );
1516                 return false;
1517             }
1518         }
1519     }
1520
1521     return true;
1522 }
1523
1524 bool
1525 AvDevice::addXmlDescription( xmlNodePtr deviceNode )
1526 {
1527     // connection set
1528     //  direction
1529     //  connection
1530     //    id
1531     //    port
1532     //    node
1533     //    plug
1534     //    dimension
1535     //    samplerate
1536     //    streams
1537     //      stream
1538
1539     xmlNodePtr connectionSet = xmlNewChild( deviceNode, 0,
1540                                             BAD_CAST "ConnectionSet", 0 );
1541     if ( !connectionSet ) {
1542         debugError( "Couldn't create connection set node for "
1543                     "direction 1 (playback)\n" );
1544         return false;
1545     }
1546
1547     AvPlug* inputPlug = getPlugById( m_isoInputPlugs, 0 );
1548     if ( !inputPlug ) {
1549         debugError( "No iso input plug found with id %d\n" );
1550         return false;
1551     }
1552     if ( !addPlugToXmlDescription( *inputPlug, connectionSet ) ) {
1553         debugError( "Could not add iso input plug 0 to XML description\n" );
1554         return false;
1555     }
1556
1557     connectionSet = xmlNewChild( deviceNode, 0,
1558                                  BAD_CAST "ConnectionSet", 0 );
1559     if ( !connectionSet ) {
1560         debugError( "Couldn't create connection set node for "
1561                     "direction 0 (recorder)\n" );
1562         return false;
1563     }
1564
1565     AvPlug* outputPlug = getPlugById( m_isoOutputPlugs, 0 );
1566     if ( !outputPlug ) {
1567         debugError( "No iso output plug found with id %d\n" );
1568         return false;
1569     }
1570     if ( !addPlugToXmlDescription( *outputPlug, connectionSet ) ) {
1571         debugError( "Could not add iso output plug 0 to XML description\n" );
1572         return false;
1573     }
1574
1575     return true;
1576 }
Note: See TracBrowser for help on using the browser.