root/branches/libfreebob-2.0/src/bebob_light/bebob_light_avdevice.cpp

Revision 230, 65.9 kB (checked in by pieterpalmers, 18 years ago)

- xrun handling now works

Line 
1 /* bebob_light_avdevice.cpp
2  * Copyright (C) 2006 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_light/bebob_light_avdevice.h"
22 #include "bebob_light/bebob_light_avdevicesubunit.h"
23
24 #include "configrom.h"
25
26 #include "libfreebobavc/avc_plug_info.h"
27 #include "libfreebobavc/avc_extended_plug_info.h"
28 #include "libfreebobavc/avc_subunit_info.h"
29 #include "libfreebobavc/avc_extended_stream_format.h"
30 #include "libfreebobavc/serialize.h"
31 #include "libfreebobavc/ieee1394service.h"
32 #include "libfreebobavc/avc_definitions.h"
33
34 #include "debugmodule/debugmodule.h"
35
36 #include <iostream>
37 #include <stdint.h>
38
39 namespace BeBoB_Light {
40
41 using namespace std;
42
43 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_VERBOSE );
44
45 AvDevice::AvDevice( Ieee1394Service& ieee1394service,
46                     int nodeId,
47                     int verboseLevel )
48     : m_1394Service( &ieee1394service )
49     , m_nodeId( nodeId )
50     , m_verboseLevel( verboseLevel )
51     , m_receiveProcessor ( 0 )
52     , m_receiveProcessorBandwidth ( -1 )
53     , m_transmitProcessor ( 0 )
54     , m_transmitProcessorBandwidth ( -1 )
55 {
56     if ( m_verboseLevel ) {
57         setDebugLevel( DEBUG_LEVEL_VERBOSE );
58     }
59     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB_Light::AvDevice "
60                  "(NodeID %d)\n", nodeId );
61
62     m_configRom = new ConfigRom( m_1394Service, m_nodeId );
63     m_configRom->initialize();
64 }
65
66 AvDevice::~AvDevice()
67 {
68     delete m_configRom;
69     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
70           it != m_subunits.end();
71           ++it )
72     {
73         delete *it;
74     }
75     for ( AvPlugConnectionVector::iterator it = m_plugConnections.begin();
76           it != m_plugConnections.end();
77           ++it )
78     {
79         delete *it;
80     }
81     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
82           it != m_isoInputPlugs.end();
83           ++it )
84     {
85         delete *it;
86     }
87     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
88           it != m_isoOutputPlugs.end();
89           ++it )
90     {
91         delete *it;
92     }
93 }
94
95 bool
96 AvDevice::discover()
97 {
98     if ( !enumerateSubUnits() ) {
99         debugError( "Could not enumarate sub units\n" );
100         return false;
101     }
102
103     if ( !discoverStep1() ) {
104         debugError( "Discover step 1 failed\n" );
105         return false;
106     }
107     if ( !discoverStep2() ) {
108         debugError( "Discover step 2 failed\n" );
109         return false;
110     }
111     if ( !discoverStep3() ) {
112         debugError( "Discover step 3 failed\n" );
113         return false;
114     }
115     if ( !discoverStep4() ) {
116         debugError( "Discover step 4 failed\n" );
117         return false;
118     }
119     if ( !discoverStep5() ) {
120         debugError( "Discover step 5 failed\n" );
121         return false;
122     }
123     if ( !discoverStep6() ) {
124         debugError( "Discover step 6 failed\n" );
125         return false;
126     }
127     if ( !discoverStep7() ) {
128         debugError( "Discover step 7 failed\n" );
129         return false;
130     }
131     if ( !discoverStep8() ) {
132         debugError( "Discover step 8 failed\n" );
133         return false;
134     }
135     if ( !discoverStep9() ) {
136         debugError( "Discover step 9 failed\n" );
137         return false;
138     }
139     if ( !discoverStep10() ) {
140         debugError( "Discover step 10 failed\n" );
141         return false;
142     }
143
144     return true;
145 }
146
147 bool
148 AvDevice::discoverStep1()
149 {
150     //////////////////////////////////////////////
151     // Step 1: Get number of available isochronous input
152     // and output plugs of unit
153
154     PlugInfoCmd plugInfoCmd( m_1394Service );
155     plugInfoCmd.setNodeId( m_nodeId );
156     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
157
158     if ( !plugInfoCmd.fire() ) {
159         debugError( "discover: plug info command failed (step 1)\n" );
160         return false;
161     }
162
163     for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousInputPlugs; ++plugId )
164     {
165         AvPlug* plug        = new AvPlug;
166         plug->m_plugId      = plugId;
167         plug->m_subunitType = PlugAddress::ePAM_Unit;
168         plug->m_direction   = PlugAddress::ePD_Input;
169         plug->m_name        = "IsoStreamInput";
170
171         m_isoInputPlugs.push_back( plug );
172     }
173
174     for ( int plugId = 0; plugId < plugInfoCmd.m_serialBusIsochronousOutputPlugs; ++plugId )
175     {
176         AvPlug* plug        = new AvPlug;
177         plug->m_plugId      = plugId;
178         plug->m_subunitType = PlugAddress::ePAM_Unit;
179         plug->m_direction   = PlugAddress::ePD_Output;
180         plug->m_name        = "IsoStreamOutput";
181
182         m_isoOutputPlugs.push_back( plug );
183     }
184
185     debugOutput( DEBUG_LEVEL_VERBOSE,
186                  "number of iso input plugs = %d, "
187                  "number of iso output plugs = %d\n",
188                  plugInfoCmd.m_serialBusIsochronousInputPlugs,
189                  plugInfoCmd.m_serialBusIsochronousOutputPlugs );
190
191     return true;
192 }
193
194 bool
195 AvDevice::discoverStep2()
196 {
197     //////////////////////////////////////////////
198     // Step 2: For each ISO input plug: get internal
199     // output connections (data sink) of the ISO input plug
200
201     for ( AvPlugVector::iterator it = m_isoInputPlugs.begin();
202           it != m_isoInputPlugs.end();
203           ++it )
204     {
205         AvPlug* isoInputPlug = *it;
206
207         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
208         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
209                                          isoInputPlug->getPlugId() );
210         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
211                                                     PlugAddress::ePAM_Unit,
212                                                     unitPlugAddress ) );
213         extPlugInfoCmd.setNodeId( m_nodeId );
214         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
215         //extPlugInfoCmd.setVerbose( true );
216         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
217             ExtendedPlugInfoInfoType::eIT_PlugOutput );
218         extendedPlugInfoInfoType.initialize();
219         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
220
221         if ( !extPlugInfoCmd.fire() ) {
222             debugError( "discoverStep2: plug outputs command failed\n" );
223             return false;
224         }
225
226         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
227         if ( infoType
228              && infoType->m_plugOutput )
229         {
230             debugOutput( DEBUG_LEVEL_VERBOSE,
231                          "number of output plugs is %d for iso input "
232                          "plug %d\n",
233                          infoType->m_plugOutput->m_nrOfOutputPlugs,
234                          isoInputPlug->getPlugId() );
235
236             if ( infoType->m_plugOutput->m_nrOfOutputPlugs
237                  != infoType->m_plugOutput->m_outputPlugAddresses.size() )
238             {
239                 debugError( "number of output plugs (%d) disagree with "
240                             "number of elements in plug address vector (%d)\n",
241                             infoType->m_plugOutput->m_nrOfOutputPlugs,
242                             infoType->m_plugOutput->m_outputPlugAddresses.size());
243             }
244             for ( unsigned int i = 0;
245                   i < infoType->m_plugOutput->m_outputPlugAddresses.size();
246                   ++i )
247             {
248                 PlugAddressSpecificData* plugAddress
249                     = infoType->m_plugOutput->m_outputPlugAddresses[i];
250
251
252                 UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
253                     dynamic_cast<UnitPlugSpecificDataPlugAddress*>
254                     ( plugAddress->m_plugAddressData );
255
256                 if ( pUnitPlugAddress ) {
257                     debugOutput( DEBUG_LEVEL_VERBOSE,
258                                  "unit plug address is not handled\n" );
259                 }
260
261                 SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
262                     dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
263                     ( plugAddress->m_plugAddressData );
264
265                 if ( pSubunitPlugAddress ) {
266                     debugOutput( DEBUG_LEVEL_VERBOSE,
267                                  "output plug %d is owned by subunit_type %d, "
268                                  "subunit_id = %d\n",
269                                  pSubunitPlugAddress->m_plugId,
270                                  pSubunitPlugAddress->m_subunitType,
271                                  pSubunitPlugAddress->m_subunitId );
272
273                     if ( !discoverPlugConnection( *isoInputPlug,
274                                                   *pSubunitPlugAddress ) )
275                     {
276                         debugError( "Discovering of plug connection failed\n" );
277                         return false;
278                     }
279                 }
280
281                 FunctionBlockPlugSpecificDataPlugAddress*
282                     pFunctionBlockPlugAddress =
283                     dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
284                     ( plugAddress->m_plugAddressData );
285
286                 if (  pFunctionBlockPlugAddress  ) {
287                     debugOutput( DEBUG_LEVEL_VERBOSE,
288                                  "function block address is not handled\n" );
289                 }
290             }
291         } else {
292             debugError( "discoverStep2: no valid info type, output plug\n" );
293             return false;
294         }
295     }
296
297     return true;
298 }
299
300 bool
301 AvDevice::discoverStep3()
302 {
303     //////////////////////////////////////////////
304     // Step 3: For each ISO output plug: get internal
305     // intput connections (data source) of the ISO output plug
306
307     for ( AvPlugVector::iterator it = m_isoOutputPlugs.begin();
308           it != m_isoOutputPlugs.end();
309           ++it )
310     {
311         AvPlug* isoOutputPlug = *it;
312
313         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
314         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
315                                          isoOutputPlug->getPlugId() );
316         extPlugInfoCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Output,
317                                                     PlugAddress::ePAM_Unit,
318                                                     unitPlugAddress ) );
319         extPlugInfoCmd.setNodeId( m_nodeId );
320         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
321         //extPlugInfoCmd.setVerbose( true );
322         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
323             ExtendedPlugInfoInfoType::eIT_PlugInput );
324         extendedPlugInfoInfoType.initialize();
325         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
326
327         if ( !extPlugInfoCmd.fire() ) {
328             debugError( "discoverStep3: plug inputs command failed\n" );
329             return false;
330         }
331
332         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
333         if ( infoType
334              && infoType->m_plugInput )
335         {
336             PlugAddressSpecificData* plugAddress
337                 = infoType->m_plugInput->m_plugAddress;
338
339
340             UnitPlugSpecificDataPlugAddress* pUnitPlugAddress =
341                 dynamic_cast<UnitPlugSpecificDataPlugAddress*>
342                 ( plugAddress->m_plugAddressData );
343
344             if ( pUnitPlugAddress ) {
345                 debugOutput( DEBUG_LEVEL_VERBOSE,
346                              "unit plug address is not handled\n" );
347             }
348
349             SubunitPlugSpecificDataPlugAddress* pSubunitPlugAddress =
350                 dynamic_cast<SubunitPlugSpecificDataPlugAddress*>
351                 ( plugAddress->m_plugAddressData );
352
353             if ( pSubunitPlugAddress ) {
354                 debugOutput( DEBUG_LEVEL_VERBOSE,
355                              "output plug %d is owned by subunit_type %d, "
356                              "subunit_id %d\n",
357                              pSubunitPlugAddress->m_plugId,
358                              pSubunitPlugAddress->m_subunitType,
359                              pSubunitPlugAddress->m_subunitId );
360
361                 if ( !discoverPlugConnection( *isoOutputPlug, *pSubunitPlugAddress ) ) {
362                     debugError( "Discovering of plug connection failed\n" );
363                     return false;
364                 }
365             }
366
367             FunctionBlockPlugSpecificDataPlugAddress*
368                 pFunctionBlockPlugAddress =
369                 dynamic_cast<FunctionBlockPlugSpecificDataPlugAddress*>
370                 ( plugAddress->m_plugAddressData );
371
372             if (  pFunctionBlockPlugAddress  ) {
373                 debugOutput( DEBUG_LEVEL_VERBOSE,
374                              "function block address is not handled\n" );
375             }
376         } else {
377             debugError( "discoverStep3: no valid info type, input plug\n" );
378             return false;
379         }
380     }
381
382     return true;
383 }
384
385 bool
386 AvDevice::discoverStep4Plug( AvPlugVector& isoPlugs )
387 {
388     //////////////////////////////////////////////
389     // Step 4: For all ISO plugs with valid internal connections:
390     // get type of data stream flowing through plug.
391     // Stream type of interest: iso stream & sync stream
392
393     for ( AvPlugVector::iterator it = isoPlugs.begin();
394           it != isoPlugs.end();
395           ++it )
396     {
397         AvPlug* isoPlug = *it;
398
399         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
400         if ( !plugConnection ) {
401             debugOutput( DEBUG_LEVEL_VERBOSE,
402                          "plug %d has no valid connecton -> skip\n",
403                          isoPlug->getPlugId() );
404             continue;
405         }
406
407         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
408         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
409                                          isoPlug->getPlugId() );
410         PlugAddress::EPlugDirection direction =
411             static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
412         extPlugInfoCmd.setPlugAddress( PlugAddress( direction,
413                                                     PlugAddress::ePAM_Unit,
414                                                     unitPlugAddress ) );
415         extPlugInfoCmd.setNodeId( m_nodeId );
416         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
417         //extPlugInfoCmd.setVerbose( true );
418         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
419             ExtendedPlugInfoInfoType::eIT_PlugType );
420         extendedPlugInfoInfoType.initialize();
421         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
422
423         if ( !extPlugInfoCmd.fire() ) {
424             debugError( "discoverStep4Plug: plug type command failed\n" );
425             return false;
426         }
427
428         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
429         if ( infoType
430              && infoType->m_plugType )
431         {
432             plug_type_t plugType = infoType->m_plugType->m_plugType;
433
434             debugOutput( DEBUG_LEVEL_VERBOSE,
435                          "plug %d is of type %d (%s)\n",
436                          isoPlug->getPlugId(),
437                          plugType,
438                          extendedPlugInfoPlugTypeToString( plugType ) );
439
440             isoPlug->m_plugType = plugType;
441         }
442     }
443
444    return true;
445 }
446
447 bool
448 AvDevice::discoverStep4()
449 {
450     bool success;
451     success  = discoverStep4Plug( m_isoInputPlugs );
452     success &= discoverStep4Plug( m_isoOutputPlugs );
453
454     return success;
455 }
456
457 bool
458 AvDevice::discoverStep5Plug( AvPlugVector& isoPlugs )
459 {
460     //////////////////////////////////////////////
461     // Step 5: For all ISO plugs with valid internal connections:
462     // get data block size of the stream flowing through the plug
463
464     for ( AvPlugVector::iterator it = isoPlugs.begin();
465           it != isoPlugs.end();
466           ++it )
467     {
468         AvPlug* isoPlug = *it;
469
470         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
471         if ( !plugConnection ) {
472             debugOutput( DEBUG_LEVEL_VERBOSE,
473                          "plug %d has no valid connecton -> skip\n",
474                          isoPlug->getPlugId() );
475             continue;
476         }
477
478         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
479         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
480                                          isoPlug->getPlugId() );
481         PlugAddress::EPlugDirection direction =
482             static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
483         extPlugInfoCmd.setPlugAddress( PlugAddress( direction,
484                                                     PlugAddress::ePAM_Unit,
485                                                     unitPlugAddress ) );
486         extPlugInfoCmd.setNodeId( m_nodeId );
487         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
488         //extPlugInfoCmd.setVerbose( true );
489         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
490             ExtendedPlugInfoInfoType::eIT_NoOfChannels );
491         extendedPlugInfoInfoType.initialize();
492         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
493
494         if ( !extPlugInfoCmd.fire() ) {
495             debugError( "discoverStep5Plug: number of channels command failed\n" );
496             return false;
497         }
498
499         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
500         if ( infoType
501              && infoType->m_plugNrOfChns )
502         {
503             nr_of_channels_t nrOfChannels
504                 = infoType->m_plugNrOfChns->m_nrOfChannels;
505
506             debugOutput( DEBUG_LEVEL_VERBOSE,
507                          "plug %d has %d channels\n",
508                          isoPlug->getPlugId(),
509                          nrOfChannels );
510
511             isoPlug->m_nrOfChannels = nrOfChannels;
512         }
513     }
514
515     return true;
516 }
517
518
519 bool
520 AvDevice::discoverStep5()
521 {
522     bool success;
523     success  = discoverStep5Plug( m_isoInputPlugs );
524     success &= discoverStep5Plug( m_isoOutputPlugs );
525
526     return success;
527 }
528
529 bool
530 AvDevice::discoverStep6Plug( AvPlugVector& isoPlugs )
531 {
532     //////////////////////////////////////////////
533     // Step 6: For all ISO plugs with valid internal connections:
534     // get position of channels within data block
535
536     for ( AvPlugVector::iterator it = isoPlugs.begin();
537           it != isoPlugs.end();
538           ++it )
539     {
540         AvPlug* isoPlug = *it;
541
542         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
543         if ( !plugConnection ) {
544             debugOutput( DEBUG_LEVEL_VERBOSE,
545                          "plug %d has no valid connecton -> skip\n",
546                          isoPlug->getPlugId() );
547             continue;
548         }
549
550         ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
551         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
552                                          isoPlug->getPlugId() );
553         PlugAddress::EPlugDirection direction =
554             static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
555         extPlugInfoCmd.setPlugAddress( PlugAddress( direction,
556                                                     PlugAddress::ePAM_Unit,
557                                                     unitPlugAddress ) );
558         extPlugInfoCmd.setNodeId( m_nodeId );
559         extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
560         //extPlugInfoCmd.setVerbose( true );
561         ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
562             ExtendedPlugInfoInfoType::eIT_ChannelPosition );
563         extendedPlugInfoInfoType.initialize();
564         extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
565
566         if ( !extPlugInfoCmd.fire() ) {
567             debugError( "discoverStep6Plug: channels position command failed\n" );
568             return false;
569         }
570
571         ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
572         if ( infoType
573              && infoType->m_plugChannelPosition )
574         {
575             if ( !isoPlug->copyClusterInfo(
576                      *( infoType->m_plugChannelPosition ) ) )
577             {
578                 debugError( "discoverStep6Plug: Could not copy channel position "
579                             "information\n" );
580                 return false;
581             }
582
583             debugOutput( DEBUG_LEVEL_VERBOSE,
584                          "plug %d: channel position information "
585                          "retrieved\n",
586                          isoPlug->getPlugId() );
587
588             isoPlug->debugOutputClusterInfos( DEBUG_LEVEL_VERBOSE );
589         }
590     }
591
592     return true;
593 }
594
595 bool
596 AvDevice::discoverStep6()
597 {
598     bool success;
599     success  = discoverStep6Plug( m_isoInputPlugs );
600     success &= discoverStep6Plug( m_isoOutputPlugs );
601
602     return success;
603 }
604
605 bool
606 AvDevice::discoverStep7Plug( AvPlugVector& isoPlugs )
607 {
608     //////////////////////////////////////////////
609     // Step 7: For all ISO plugs with valid internal connections:
610     // get hardware name of channel
611
612     for ( AvPlugVector::iterator it = isoPlugs.begin();
613           it != isoPlugs.end();
614           ++it )
615     {
616         AvPlug* isoPlug = *it;
617
618         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
619         if ( !plugConnection ) {
620             debugOutput( DEBUG_LEVEL_VERBOSE,
621                          "plug %d has no valid connecton -> skip\n",
622                          isoPlug->getPlugId() );
623             continue;
624         }
625
626         for ( AvPlug::ClusterInfoVector::iterator clit =
627                   isoPlug->m_clusterInfos.begin();
628               clit != isoPlug->m_clusterInfos.end();
629               ++clit )
630         {
631             AvPlug::ClusterInfo* clitInfo = &*clit;
632
633             for ( AvPlug::ChannelInfoVector::iterator pit =
634                       clitInfo->m_channelInfos.begin();
635                   pit != clitInfo->m_channelInfos.end();
636                   ++pit )
637             {
638                 AvPlug::ChannelInfo* channelInfo = &*pit;
639
640                 ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
641                 UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
642                                                  isoPlug->getPlugId() );
643                 PlugAddress::EPlugDirection direction =
644                     static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
645                 extPlugInfoCmd.setPlugAddress( PlugAddress( direction,
646                                                             PlugAddress::ePAM_Unit,
647                                                             unitPlugAddress ) );
648                 extPlugInfoCmd.setNodeId( m_nodeId );
649                 extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
650                 //extPlugInfoCmd.setVerbose( true );
651                 ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
652                     ExtendedPlugInfoInfoType::eIT_ChannelName );
653                 extendedPlugInfoInfoType.initialize();
654                 extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
655
656                 ExtendedPlugInfoInfoType* infoType =
657                     extPlugInfoCmd.getInfoType();
658                 if ( infoType ) {
659                     infoType->m_plugChannelName->m_streamPosition =
660                         channelInfo->m_streamPosition;
661                 }
662                 if ( !extPlugInfoCmd.fire() ) {
663                     debugError( "discoverStep7: channel name command failed\n" );
664                     return false;
665                 }
666                 infoType = extPlugInfoCmd.getInfoType();
667                 if ( infoType
668                      && infoType->m_plugChannelName )
669                 {
670                     debugOutput( DEBUG_LEVEL_VERBOSE,
671                                  "plug %d stream "
672                                  "position %d: channel name = %s\n",
673                                  isoPlug->getPlugId(),
674                                  channelInfo->m_streamPosition,
675                                  infoType->m_plugChannelName->m_plugChannelName.c_str() );
676                     channelInfo->m_name =
677                         infoType->m_plugChannelName->m_plugChannelName;
678                 }
679
680             }
681         }
682     }
683
684     return true;
685 }
686 bool
687 AvDevice::discoverStep7()
688 {
689     bool success;
690     success  = discoverStep7Plug( m_isoInputPlugs );
691     success &= discoverStep7Plug( m_isoOutputPlugs );
692
693     return success;
694 }
695
696 bool
697 AvDevice::discoverStep8Plug( AvPlugVector& isoPlugs )
698 {
699     //////////////////////////////////////////////
700     // Step 8: For all ISO plugs with valid internal connections:
701     // get logical input and output streams provided by the device
702
703     for ( AvPlugVector::iterator it = isoPlugs.begin();
704           it != isoPlugs.end();
705           ++it )
706     {
707         AvPlug* isoPlug = *it;
708
709         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
710         if ( !plugConnection ) {
711             debugOutput( DEBUG_LEVEL_VERBOSE,
712                          "%s plug %d has no valid connecton -> skip\n",
713                          isoPlug->getName(),
714                          isoPlug->getPlugId() );
715             continue;
716         }
717
718         if ( isoPlug->getPlugType()
719              == ExtendedPlugInfoPlugTypeSpecificData::eEPIPT_Sync )
720         {
721             // If the plug is of type sync it is either a normal 2 channel
722             // stream (not compound stream) or it is a compound stream
723             // with exactly one cluster. This depends on the
724             // extended stream format command version which is used.
725             // We are not interested in this plug so we skip it.
726             debugOutput( DEBUG_LEVEL_VERBOSE,
727                          "%s plug %d is of type sync -> skip\n",
728                          isoPlug->getName(),
729                          isoPlug->getPlugId() );
730             continue;
731         }
732
733         for ( AvPlug::ClusterInfoVector::iterator clit =
734                   isoPlug->m_clusterInfos.begin();
735               clit != isoPlug->m_clusterInfos.end();
736               ++clit )
737         {
738             AvPlug::ClusterInfo* clusterInfo = &*clit;
739
740             ExtendedPlugInfoCmd extPlugInfoCmd( m_1394Service );
741             UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
742                                              isoPlug->getPlugId() );
743             PlugAddress::EPlugDirection direction =
744                 static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
745             extPlugInfoCmd.setPlugAddress( PlugAddress( direction,
746                                                         PlugAddress::ePAM_Unit,
747                                                         unitPlugAddress ) );
748             extPlugInfoCmd.setNodeId( m_nodeId );
749             extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
750             //extPlugInfoCmd.setVerbose( true );
751             ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
752                 ExtendedPlugInfoInfoType::eIT_ClusterInfo );
753             extendedPlugInfoInfoType.initialize();
754             extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
755
756             extPlugInfoCmd.getInfoType()->m_plugClusterInfo->m_clusterIndex =
757                 clusterInfo->m_index;
758
759             if ( !extPlugInfoCmd.fire() ) {
760                 debugError( "discoverStep8Plug: cluster info command failed\n" );
761                 return false;
762             }
763
764             ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
765             if ( infoType
766                  && infoType->m_plugClusterInfo )
767             {
768                 debugOutput( DEBUG_LEVEL_VERBOSE,
769                              "%s plug %d: cluster index = %d, "
770                              "portType %s, cluster name = %s\n",
771                              isoPlug->getName(),
772                              isoPlug->getPlugId(),
773                              infoType->m_plugClusterInfo->m_clusterIndex,
774                              extendedPlugInfoClusterInfoPortTypeToString(
775                                  infoType->m_plugClusterInfo->m_portType ),
776                              infoType->m_plugClusterInfo->m_clusterName.c_str() );
777
778                 clusterInfo->m_portType = infoType->m_plugClusterInfo->m_portType;
779                 clusterInfo->m_name = infoType->m_plugClusterInfo->m_clusterName;
780             }
781         }
782     }
783
784     return true;
785 }
786
787 bool
788 AvDevice::discoverStep8()
789 {
790     bool success;
791     success  = discoverStep8Plug( m_isoInputPlugs );
792     success &= discoverStep8Plug( m_isoOutputPlugs );
793
794     return success;
795 }
796
797 bool
798 AvDevice::discoverStep9Plug( AvPlugVector& isoPlugs )
799 {
800     //////////////////////////////////////////////
801     // Step 9: For all ISO plugs with valid internal connections:
802     // get current stream format
803
804     for ( AvPlugVector::iterator it = isoPlugs.begin();
805           it != isoPlugs.end();
806           ++it )
807     {
808         AvPlug* isoPlug = *it;
809
810         AvPlugConnection* plugConnection = getPlugConnection( *isoPlug );
811         if ( !plugConnection ) {
812             debugOutput( DEBUG_LEVEL_VERBOSE,
813                          "%s plug %d has no valid connecton -> skip\n",
814                          isoPlug->getName(),
815                          isoPlug->getPlugId() );
816             continue;
817         }
818
819         ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service );
820         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
821                                          isoPlug->getPlugId() );
822         PlugAddress::EPlugDirection direction =
823             static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
824         extStreamFormatCmd.setPlugAddress( PlugAddress( direction,
825                                                         PlugAddress::ePAM_Unit,
826                                                         unitPlugAddress ) );
827
828         extStreamFormatCmd.setNodeId( m_nodeId );
829         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
830         //extStreamFormatCmd.setVerbose( true );
831
832         if ( !extStreamFormatCmd.fire() ) {
833             debugError( "discoverStep9Plug: stream format command failed\n" );
834             return false;
835         }
836
837         FormatInformation* formatInfo =
838             extStreamFormatCmd.getFormatInformation();
839         FormatInformationStreamsCompound* compoundStream
840             = dynamic_cast< FormatInformationStreamsCompound* > (
841                 formatInfo->m_streams );
842         if ( compoundStream ) {
843             isoPlug->m_samplingFrequency =
844                 compoundStream->m_samplingFrequency;
845             debugOutput( DEBUG_LEVEL_VERBOSE,
846                          "discoverStep9Plug: %s plug %d uses "
847                          "sampling frequency %d\n",
848                          isoPlug->getName(),
849                          isoPlug->getPlugId(),
850                          isoPlug->m_samplingFrequency );
851
852             for ( int i = 1;
853                   i <= compoundStream->m_numberOfStreamFormatInfos;
854                   ++i )
855             {
856                 AvPlug::ClusterInfo* clusterInfo =
857                     isoPlug->getClusterInfoByIndex( i );
858
859                 if ( !clusterInfo ) {
860                     debugError( "discoverStep9Plug: No matching cluster info found "
861                                 "for index %d\n",  i );
862                     return false;
863                 }
864                 StreamFormatInfo* streamFormatInfo =
865                     compoundStream->m_streamFormatInfos[ i - 1 ];
866
867                 int nrOfChannels = clusterInfo->m_nrOfChannels;
868                 if ( streamFormatInfo->m_streamFormat ==
869                      FormatInformation::eFHL2_AM824_MIDI_CONFORMANT )
870                 {
871                     // 8 logical midi channels fit into 1 channel
872                     nrOfChannels = ( ( nrOfChannels + 7 ) / 8 );
873                 }
874                 // sanity checks
875                 if (  nrOfChannels !=
876                      streamFormatInfo->m_numberOfChannels )
877                 {
878                     debugError( "discoverStep9Plug: Number of channels "
879                                 "mismatch: %s plug %d discovering reported "
880                                 "%d channels for cluster '%s', while stream format "
881                                 "reported %d\n",
882                                 isoPlug->getName(),
883                                 isoPlug->getPlugId(),
884                                 nrOfChannels,
885                                 clusterInfo->m_name.c_str(),
886                                 streamFormatInfo->m_numberOfChannels);
887                     return false;
888                 }
889                 clusterInfo->m_streamFormat = streamFormatInfo->m_streamFormat;
890
891                 debugOutput( DEBUG_LEVEL_VERBOSE,
892                              "%s plug %d cluster info %d ('%s'): stream format %d\n",
893                              isoPlug->getName(),
894                              isoPlug->getPlugId(),
895                              i,
896                              clusterInfo->m_name.c_str(),
897                              clusterInfo->m_streamFormat );
898             }
899         }
900
901         FormatInformationStreamsSync* syncStream
902             = dynamic_cast< FormatInformationStreamsSync* > (
903                 formatInfo->m_streams );
904         if ( syncStream ) {
905             isoPlug->m_samplingFrequency =
906                 syncStream->m_samplingFrequency;
907                 debugOutput( DEBUG_LEVEL_VERBOSE,
908                              "%s plug %d is sync stream with sampling frequency %d\n",
909                              isoPlug->getName(),
910                              isoPlug->getPlugId(),
911                              isoPlug->m_samplingFrequency );
912         }
913
914         if ( !compoundStream && !syncStream ) {
915             debugError( "discoverStep9Plug: Unsupported stream format\n" );
916             return false;
917         }
918     }
919
920     return true;
921 }
922
923 bool
924 AvDevice::discoverStep9()
925 {
926     bool success;
927     success  = discoverStep9Plug( m_isoInputPlugs );
928     success &= discoverStep9Plug( m_isoOutputPlugs );
929
930     return success;
931 }
932
933 bool
934 AvDevice::discoverStep10Plug( AvPlugVector& isoPlugs )
935 {
936    for ( AvPlugVector::iterator it = isoPlugs.begin();
937           it != isoPlugs.end();
938           ++it )
939     {
940         AvPlug* isoPlug = *it;
941         ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service,
942                                                     ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList);
943         UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
944                                          isoPlug->getPlugId() );
945         PlugAddress::EPlugDirection direction =
946             static_cast<PlugAddress::EPlugDirection>( isoPlug->getPlugDirection() );
947         extStreamFormatCmd.setPlugAddress( PlugAddress( direction,
948                                                         PlugAddress::ePAM_Unit,
949                                                         unitPlugAddress ) );
950
951         extStreamFormatCmd.setNodeId( m_nodeId );
952         //extStreamFormatCmd.setVerbose( true );
953
954         int i = 0;
955         bool cmdSuccess = false;
956
957         do {
958             extStreamFormatCmd.setIndexInStreamFormat( i );
959             extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
960             cmdSuccess = extStreamFormatCmd.fire();
961             if ( cmdSuccess
962                  && ( extStreamFormatCmd.getResponse() == AVCCommand::eR_Implemented ) )
963             {
964                 AvPlug::FormatInfo formatInfo;
965                 formatInfo.m_index = i;
966
967                 FormatInformationStreamsSync* syncStream
968                     = dynamic_cast< FormatInformationStreamsSync* >
969                     ( extStreamFormatCmd.getFormatInformation()->m_streams );
970                 if ( syncStream ) {
971                     formatInfo.m_samplingFrequency =
972                         syncStream->m_samplingFrequency;
973                     formatInfo.m_isSyncStream = true ;
974                 }
975
976                 FormatInformationStreamsCompound* compoundStream
977                     = dynamic_cast< FormatInformationStreamsCompound* >
978                     ( extStreamFormatCmd.getFormatInformation()->m_streams );
979                 if ( compoundStream ) {
980                     formatInfo.m_samplingFrequency =
981                         compoundStream->m_samplingFrequency;
982                     formatInfo.m_isSyncStream = false;
983                     for ( int j = 0;
984                           j < compoundStream->m_numberOfStreamFormatInfos;
985                           ++j )
986                     {
987                         switch ( compoundStream->m_streamFormatInfos[j]->m_streamFormat ) {
988                         case AVC1394_STREAM_FORMAT_AM824_MULTI_BIT_LINEAR_AUDIO_RAW:
989                             formatInfo.m_audioChannels +=
990                                 compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
991                             break;
992                         case AVC1394_STREAM_FORMAT_AM824_MIDI_CONFORMANT:
993                             formatInfo.m_midiChannels +=
994                                 compoundStream->m_streamFormatInfos[j]->m_numberOfChannels;
995                             break;
996                         default:
997                             debugWarning( "discoverStep10Plug: unknown stream "
998                                           "format for channel (%d)\n", j );
999                         }
1000                     }
1001                 }
1002
1003                 debugOutput( DEBUG_LEVEL_VERBOSE,
1004                              "[%s:%d] formatInfo[%d].m_samplingFrequency = %d\n",
1005                              isoPlug->getName(), isoPlug->getPlugId(),
1006                              i, formatInfo.m_samplingFrequency );
1007                 debugOutput( DEBUG_LEVEL_VERBOSE,
1008                              "[%s:%d] formatInfo[%d].m_isSyncStream = %d\n",
1009                              isoPlug->getName(), isoPlug->getPlugId(),
1010                              i, formatInfo.m_isSyncStream );
1011                 debugOutput( DEBUG_LEVEL_VERBOSE,
1012                              "[%s:%d] formatInfo[%d].m_audioChannels = %d\n",
1013                              isoPlug->getName(), isoPlug->getPlugId(),
1014                              i, formatInfo.m_audioChannels );
1015                 debugOutput( DEBUG_LEVEL_VERBOSE,
1016                              "[%s:%d] formatInfo[%d].m_midiChannels = %d\n",
1017                              isoPlug->getName(), isoPlug->getPlugId(),
1018                              i, formatInfo.m_midiChannels );
1019
1020                 isoPlug->m_formatInfos.push_back( formatInfo );
1021             }
1022
1023             ++i;
1024         } while ( cmdSuccess && ( extStreamFormatCmd.getResponse()
1025                                   == ExtendedStreamFormatCmd::eR_Implemented ) );
1026     }
1027
1028    return true;
1029 }
1030
1031
1032 bool
1033 AvDevice::discoverStep10()
1034 {
1035     //////////////////////////////////////////////
1036     // Step 10: For all ISO plugs: get all stream
1037     // supported formats
1038
1039     bool success;
1040
1041     success  = discoverStep10Plug( m_isoInputPlugs );
1042     success &= discoverStep10Plug( m_isoOutputPlugs );
1043
1044     return success;
1045 }
1046
1047 bool
1048 AvDevice::discoverPlugConnection( AvPlug& srcPlug,
1049                                   SubunitPlugSpecificDataPlugAddress& subunitPlugAddress )
1050 {
1051     AvDeviceSubunit* subunit = getSubunit( subunitPlugAddress.m_subunitType,
1052                                            subunitPlugAddress.m_subunitId );
1053
1054     if ( subunit ) {
1055         debugOutput( DEBUG_LEVEL_VERBOSE,
1056                      "%s plug %d has a valid connection to plug %d of "
1057                      "%s subunit %d \n",
1058                      srcPlug.getName(),
1059                      srcPlug.getPlugId(),
1060                      subunitPlugAddress.m_plugId,
1061                      subunit->getName(),
1062                      subunit->getSubunitId() );
1063
1064         AvPlug* destPlug        = new AvPlug;
1065         destPlug->m_plugId      = subunitPlugAddress.m_plugId;
1066         destPlug->m_subunitType = subunitPlugAddress.m_subunitType;
1067         destPlug->m_subunitId   = subunitPlugAddress.m_subunitId;
1068
1069         if ( !subunit->addPlug( *destPlug ) ) {
1070             debugError( "Could not add plug %d to subunit %d\n",
1071                         destPlug->getPlugId(), subunit->getSubunitId() );
1072             return false;
1073         }
1074
1075         AvPlugConnection* plugConnection = new AvPlugConnection;
1076         plugConnection->m_srcPlug = &srcPlug;
1077         plugConnection->m_destPlug = destPlug;
1078         m_plugConnections.push_back( plugConnection );
1079
1080         return true;
1081     } else {
1082         debugOutput( DEBUG_LEVEL_VERBOSE,
1083                      "found plug address points to unhandled  "
1084                      "subunit -> ignored\n" );
1085     }
1086
1087     return true;
1088 }
1089
1090 bool
1091 AvDevice::enumerateSubUnits()
1092 {
1093     SubUnitInfoCmd subUnitInfoCmd( m_1394Service );
1094     //subUnitInfoCmd.setVerbose( 1 );
1095     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
1096
1097     // BeBob has always exactly one audio and one music subunit. This
1098     // means is fits into the first page of the SubUnitInfo command.
1099     // So there is no need to do more than needed
1100
1101     subUnitInfoCmd.m_page = 0;
1102     subUnitInfoCmd.setNodeId( m_nodeId );
1103     if ( !subUnitInfoCmd.fire() ) {
1104         debugError( "Subunit info command failed\n" );
1105     }
1106
1107     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
1108         subunit_type_t subunit_type
1109             = subUnitInfoCmd.m_table[i].m_subunit_type;
1110
1111         unsigned int subunitId = getNrOfSubunits( subunit_type );
1112
1113         debugOutput( DEBUG_LEVEL_VERBOSE,
1114                      "subunit_id = %2d, subunit_type = %2d (%s)\n",
1115                      subunitId,
1116                      subunit_type,
1117                      subunitTypeToString( subunit_type ) );
1118
1119         AvDeviceSubunit* subunit = 0;
1120         switch( subunit_type ) {
1121         case AVCCommand::eST_Audio:
1122             subunit = new AvDeviceSubunitAudio( this, subunitId );
1123             if ( !subunit ) {
1124                 debugFatal( "Could not allocate AvDeviceSubunitAudio\n" );
1125                 return false;
1126             }
1127             break;
1128         case AVCCommand::eST_Music:
1129             subunit = new AvDeviceSubunitMusic( this, subunitId );
1130             if ( !subunit ) {
1131                 debugFatal( "Could not allocate AvDeviceSubunitMusic\n" );
1132                 return false;
1133             }
1134             break;
1135         default:
1136             debugOutput( DEBUG_LEVEL_NORMAL,
1137                          "Unsupported subunit found, subunit_type = %d (%s)\n",
1138                          subunit_type,
1139                          subunitTypeToString( subunit_type ) );
1140
1141         }
1142
1143         m_subunits.push_back( subunit );
1144     }
1145
1146     return true;
1147 }
1148
1149
1150 AvDeviceSubunit*
1151 AvDevice::getSubunit( subunit_type_t subunitType,
1152                       subunit_id_t subunitId ) const
1153 {
1154     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
1155           it != m_subunits.end();
1156           ++it )
1157     {
1158         AvDeviceSubunit* subunit = *it;
1159         if ( ( subunitType == subunit->getSubunitType() )
1160              && ( subunitId == subunit->getSubunitId() ) )
1161         {
1162             return subunit;
1163         }
1164     }
1165
1166     return 0;
1167 }
1168
1169
1170 unsigned int
1171 AvDevice::getNrOfSubunits( subunit_type_t subunitType ) const
1172 {
1173     unsigned int nrOfSubunits = 0;
1174
1175     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
1176           it != m_subunits.end();
1177           ++it )
1178     {
1179         AvDeviceSubunit* subunit = *it;
1180         if ( subunitType == subunit->getSubunitType() ) {
1181             nrOfSubunits++;
1182         }
1183     }
1184
1185     return nrOfSubunits;
1186 }
1187
1188 AvPlugConnection*
1189 AvDevice::getPlugConnection( AvPlug& srcPlug ) const
1190 {
1191     for ( AvPlugConnectionVector::const_iterator it
1192               = m_plugConnections.begin();
1193           it != m_plugConnections.end();
1194           ++it )
1195     {
1196         AvPlugConnection* plugConnection = *it;
1197         if ( plugConnection->m_srcPlug == &srcPlug ) {
1198             return plugConnection;
1199         }
1200     }
1201
1202     return 0;
1203 }
1204
1205 AvPlug*
1206 AvDevice::getPlugById( AvPlugVector& plugs, int id )
1207 {
1208     for ( AvPlugVector::iterator it = plugs.begin();
1209           it != plugs.end();
1210           ++it )
1211     {
1212         AvPlug* plug = *it;
1213         if ( id == plug->getPlugId() ) {
1214             return plug;
1215         }
1216     }
1217
1218     return 0;
1219 }
1220
1221 bool
1222 AvDevice::addXmlDescriptionPlug( AvPlug& plug,
1223                                  xmlNodePtr connectionSet )
1224 {
1225     char* result;
1226
1227     int direction;
1228     switch ( plug.getPlugDirection() ) {
1229         case 0:
1230             direction = FREEBOB_PLAYBACK;
1231             break;
1232         case 1:
1233             direction = FREEBOB_CAPTURE;
1234             break;
1235     default:
1236         debugError( "plug direction invalid (%d)\n",
1237                     plug.getPlugDirection() );
1238         return false;
1239     }
1240
1241     asprintf( &result, "%d",  direction );
1242     if ( !xmlNewChild( connectionSet,
1243                        0,
1244                        BAD_CAST "Direction",
1245                        BAD_CAST result ) )
1246     {
1247         debugError( "Couldn't create 'Direction' node\n" );
1248         return false;
1249     }
1250
1251     xmlNodePtr connection = xmlNewChild( connectionSet, 0,
1252                                          BAD_CAST "Connection", 0 );
1253     if ( !connection ) {
1254         debugError( "Couldn't create 'Connection' node for "
1255                     "direction %d\n", plug.getPlugDirection() );
1256         return false;
1257     }
1258
1259     asprintf( &result, "%08x%08x",
1260               ( quadlet_t )( m_configRom->getGuid() >> 32 ),
1261               ( quadlet_t )( m_configRom->getGuid() & 0xfffffff ) );
1262     if ( !xmlNewChild( connection,  0,
1263                        BAD_CAST "GUID",  BAD_CAST result ) ) {
1264         debugError( "Couldn't create 'GUID' node\n" );
1265         return false;
1266     }
1267
1268     asprintf( &result, "%d", m_1394Service->getPort() );
1269     if ( !xmlNewChild( connection,  0,
1270                        BAD_CAST "Port",  BAD_CAST result ) ) {
1271         debugError( "Couldn't create 'Port' node\n" );
1272         return false;
1273     }
1274
1275     asprintf( &result, "%d",  m_nodeId);
1276     if ( !xmlNewChild( connection,  0,
1277                        BAD_CAST "Node",  BAD_CAST result ) ) {
1278         debugError( "Couldn't create 'Node' node\n" );
1279         return false;
1280     }
1281
1282     asprintf( &result, "%d",  plug.getNrOfChannels() );
1283     if ( !xmlNewChild( connection,  0,
1284                        BAD_CAST "Dimension",  BAD_CAST result ) ) {
1285         debugError( "Couldn't create 'Dimension' node\n" );
1286         return false;
1287     }
1288
1289     asprintf( &result, "%d",  plug.getSampleRate() );
1290     if ( !xmlNewChild( connection,  0,
1291                        BAD_CAST "Samplerate",  BAD_CAST result ) ) {
1292         debugError( "Couldn't create 'Samplerate' node\n" );
1293         return false;
1294     }
1295
1296     if ( !xmlNewChild( connection,  0,
1297                        BAD_CAST "IsoChannel", BAD_CAST "-1" ) )
1298     {
1299         debugError( "Couldn't create 'IsoChannel' node\n" );
1300         return false;
1301     }
1302
1303     xmlNodePtr streams = xmlNewChild( connection,  0,
1304                                       BAD_CAST "Streams",  0 );
1305     if ( !streams ) {
1306         debugError( "Couldn't create 'Streams' node for "
1307                     "direction %d\n", plug.getPlugDirection() );
1308         return false;
1309     }
1310
1311     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
1312     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
1313           it != clusterInfos.end();
1314           ++it )
1315     {
1316         const AvPlug::ClusterInfo* clusterInfo = &( *it );
1317
1318         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1319         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1320               it != channelInfos.end();
1321               ++it )
1322         {
1323             const AvPlug::ChannelInfo* channelInfo = &( *it );
1324
1325             xmlNodePtr stream = xmlNewChild( streams,  0,
1326                                              BAD_CAST "Stream",  0 );
1327             if ( !stream ) {
1328                 debugError( "Coulnd't create 'Stream' node" );
1329                 return false;
1330             }
1331
1332             // \todo: iec61883 backend expects indexing starting from 0
1333             // but bebob reports it starting from 1. Decide where
1334             // and how to handle this
1335             asprintf( &result, "%d", channelInfo->m_streamPosition - 1 );
1336             if ( !xmlNewChild( stream,  0,
1337                                BAD_CAST "Position",  BAD_CAST result ) )
1338             {
1339                 debugError( "Couldn't create 'Position' node" );
1340                 return false;
1341             }
1342
1343             asprintf( &result, "%d", channelInfo->m_location );
1344             if ( !xmlNewChild( stream,  0,
1345                                BAD_CAST "Location",  BAD_CAST result ) )
1346             {
1347                 debugError( "Couldn't create 'Location' node" );
1348                 return false;
1349             }
1350
1351             asprintf( &result, "%d", clusterInfo->m_streamFormat );
1352             if ( !xmlNewChild( stream,  0,
1353                                BAD_CAST "Format",  BAD_CAST result ) )
1354             {
1355                 debugError( "Couldn't create 'Format' node" );
1356                 return false;
1357             }
1358
1359             asprintf( &result, "%d", clusterInfo->m_portType );
1360             if ( !xmlNewChild( stream,  0,
1361                                BAD_CAST "Type",  BAD_CAST result ) )
1362             {
1363                 debugError( "Couldn't create 'Type' node" );
1364                 return false;
1365             }
1366
1367             // \todo XXX: What do to do with DestinationPort value??
1368             asprintf( &result, "%d", 0 );
1369             if ( !xmlNewChild( stream,  0,
1370                                BAD_CAST "DestinationPort",  BAD_CAST result ) )
1371             {
1372                 debugError( "Couldn't create 'DestinationPort' node" );
1373                 return false;
1374             }
1375
1376             if ( !xmlNewChild( stream,  0,
1377                                BAD_CAST "Name",
1378                                BAD_CAST channelInfo->m_name.c_str() ) )
1379             {
1380                 debugError( "Couldn't create 'Name' node" );
1381                 return false;
1382             }
1383         }
1384     }
1385
1386     return true;
1387 }
1388
1389 bool
1390 AvDevice::addXmlDescriptionStreamFormats( AvPlug& plug,
1391                                           xmlNodePtr streamFormatNode )
1392 {
1393     int direction;
1394     switch ( plug.getPlugDirection() ) {
1395         case 0:
1396             direction = FREEBOB_PLAYBACK;
1397             break;
1398         case 1:
1399             direction = FREEBOB_CAPTURE;
1400             break;
1401     default:
1402         debugError( "addXmlDescriptionStreamFormats: plug direction invalid (%d)\n",
1403                     plug.getPlugDirection() );
1404         return false;
1405     }
1406
1407     char* result;
1408     asprintf( &result, "%d",  direction );
1409     if ( !xmlNewChild( streamFormatNode,
1410                        0,
1411                        BAD_CAST "Direction",
1412                        BAD_CAST result ) )
1413     {
1414         debugError( "addXmlDescriptionStreamFormats: Could not  create 'Direction' node\n" );
1415         return false;
1416     }
1417
1418     for ( AvPlug::FormatInfoVector::iterator it =
1419               plug.m_formatInfos.begin();
1420           it != plug.m_formatInfos.end();
1421           ++it )
1422     {
1423         AvPlug::FormatInfo formatInfo = *it;
1424         xmlNodePtr formatNode = xmlNewChild( streamFormatNode, 0,
1425                                              BAD_CAST "Format", 0 );
1426         if ( !formatNode ) {
1427             debugError( "addXmlDescriptionStreamFormats: Could not create 'Format' node\n" );
1428             return false;
1429         }
1430
1431         asprintf( &result, "%d",
1432                   convertESamplingFrequency( static_cast<ESamplingFrequency>( formatInfo.m_samplingFrequency ) ) );
1433         if ( !xmlNewChild( formatNode,  0,
1434                            BAD_CAST "Samplerate",  BAD_CAST result ) )
1435         {
1436             debugError( "Couldn't create 'Samplerate' node\n" );
1437             return false;
1438         }
1439
1440         asprintf( &result, "%d",  formatInfo.m_audioChannels );
1441         if ( !xmlNewChild( formatNode,  0,
1442                            BAD_CAST "AudioChannels",  BAD_CAST result ) )
1443         {
1444             debugError( "Couldn't create 'AudioChannels' node\n" );
1445             return false;
1446         }
1447
1448         asprintf( &result, "%d",  formatInfo.m_midiChannels );
1449         if ( !xmlNewChild( formatNode,  0,
1450                            BAD_CAST "MidiChannels",  BAD_CAST result ) )
1451         {
1452             debugError( "Couldn't create 'MidiChannels' node\n" );
1453             return false;
1454         }
1455     }
1456
1457     return true;
1458 }
1459
1460 bool
1461 AvDevice::addXmlDescription( xmlNodePtr deviceNode )
1462 {
1463     // connection set
1464     //  direction
1465     //  connection
1466     //    id
1467     //    port
1468     //    node
1469     //    plug
1470     //    dimension
1471     //    samplerate
1472     //    streams
1473     //      stream
1474
1475
1476     ///////////
1477     // get plugs
1478
1479     AvPlug* inputPlug = getPlugById( m_isoInputPlugs, 0 );
1480     if ( !inputPlug ) {
1481         debugError( "addXmlDescription: No iso input plug found with id %d\n" );
1482         return false;
1483     }
1484     AvPlug* outputPlug = getPlugById( m_isoOutputPlugs, 0 );
1485     if ( !outputPlug ) {
1486         debugError( "addXmlDescription: No iso output plug found with id %d\n" );
1487         return false;
1488     }
1489
1490     ///////////
1491     // add connection set output
1492
1493     xmlNodePtr connectionSet = xmlNewChild( deviceNode, 0,
1494                                             BAD_CAST "ConnectionSet", 0 );
1495     if ( !connectionSet ) {
1496         debugError( "addXmlDescription:: Could not create 'ConnnectionSet' node for "
1497                     "direction 1 (playback)\n" );
1498         return false;
1499     }
1500
1501     if ( !addXmlDescriptionPlug( *inputPlug, connectionSet ) ) {
1502         debugError( "addXmlDescription: Could not add iso input plug 0 to XML description\n" );
1503         return false;
1504     }
1505
1506     // add connection set input
1507
1508     connectionSet = xmlNewChild( deviceNode, 0,
1509                                  BAD_CAST "ConnectionSet", 0 );
1510     if ( !connectionSet ) {
1511         debugError( "addXmlDescription: Couldn't create 'ConnectionSet' node for "
1512                     "direction 0 (recorder)\n" );
1513         return false;
1514     }
1515
1516     if ( !addXmlDescriptionPlug( *outputPlug, connectionSet ) ) {
1517         debugError( "addXmlDescription: Could not add iso output plug 0 to XML description\n" );
1518         return false;
1519     }
1520
1521     ////////////
1522     // add stream format
1523
1524     xmlNodePtr streamFormatNode = xmlNewChild( deviceNode, 0,
1525                                                BAD_CAST "StreamFormats", 0 );
1526     if ( !streamFormatNode ) {
1527         debugError( "addXmlDescription: Could not create 'StreamFormats' node\n" );
1528         return false;
1529     }
1530
1531     if ( !addXmlDescriptionStreamFormats( *inputPlug, streamFormatNode ) ) {
1532         debugError( "addXmlDescription:: Could not add stream format info\n" );
1533         return false;
1534     }
1535
1536     streamFormatNode= xmlNewChild( deviceNode, 0,
1537                                  BAD_CAST "StreamFormats", 0 );
1538     if ( !streamFormatNode ) {
1539         debugError( "addXmlDescription: Could not create 'StreamFormat' node\n" );
1540         return false;
1541     }
1542
1543     if ( !addXmlDescriptionStreamFormats( *outputPlug, streamFormatNode ) ) {
1544         debugError( "addXmlDescription:: Could not add stream format info\n" );
1545         return false;
1546     }
1547
1548     return true;
1549 }
1550
1551 bool
1552 AvDevice::setSamplingFrequencyPlug( AvPlug& plug,
1553                                     PlugAddress::EPlugDirection direction,
1554                                     ESamplingFrequency samplingFrequency )
1555 {
1556     ExtendedStreamFormatCmd extStreamFormatCmd( m_1394Service,
1557                                                 ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList );
1558     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
1559                                      plug.getPlugId() );
1560     extStreamFormatCmd.setPlugAddress( PlugAddress( direction,
1561                                                     PlugAddress::ePAM_Unit,
1562                                                     unitPlugAddress ) );
1563
1564     extStreamFormatCmd.setNodeId( m_nodeId );
1565     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
1566     //extStreamFormatCmd.setVerbose( true );
1567
1568     int i = 0;
1569     bool cmdSuccess = false;
1570     bool correctFormatFound = false;
1571
1572     do {
1573         extStreamFormatCmd.setIndexInStreamFormat( i );
1574         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
1575
1576         cmdSuccess = extStreamFormatCmd.fire();
1577         if ( cmdSuccess
1578              && ( extStreamFormatCmd.getResponse() == AVCCommand::eR_Implemented ) )
1579         {
1580             ESamplingFrequency foundFreq = eSF_DontCare;
1581
1582             FormatInformation* formatInfo =
1583                 extStreamFormatCmd.getFormatInformation();
1584             FormatInformationStreamsCompound* compoundStream
1585                 = dynamic_cast< FormatInformationStreamsCompound* > (
1586                     formatInfo->m_streams );
1587             if ( compoundStream ) {
1588                 foundFreq = static_cast<ESamplingFrequency>( compoundStream->m_samplingFrequency );
1589             }
1590
1591             FormatInformationStreamsSync* syncStream
1592                 = dynamic_cast< FormatInformationStreamsSync* > (
1593                     formatInfo->m_streams );
1594             if ( syncStream ) {
1595                 foundFreq = static_cast<ESamplingFrequency>( compoundStream->m_samplingFrequency );
1596             }
1597
1598             if (  foundFreq == samplingFrequency )
1599             {
1600                 correctFormatFound = true;
1601                 break;
1602             }
1603         }
1604
1605         ++i;
1606     } while ( cmdSuccess && ( extStreamFormatCmd.getResponse()
1607                               == ExtendedStreamFormatCmd::eR_Implemented ) );
1608
1609     if ( !cmdSuccess ) {
1610         debugError( "setSampleRatePlug: Failed to retrieve format info\n" );
1611         return false;
1612     }
1613
1614     if ( !correctFormatFound ) {
1615         debugError( "setSampleRatePlug: %s plug %d does not support sample rate %d\n",
1616                     plug.getName(),
1617                     plug.getPlugId(),
1618                     convertESamplingFrequency( samplingFrequency ) );
1619         return false;
1620     }
1621
1622     extStreamFormatCmd.setSubFunction(
1623         ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand );
1624     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Control );
1625
1626     if ( !extStreamFormatCmd.fire() ) {
1627         debugError( "setSampleRate: Could not set sample rate %d "
1628                     "to %s plug %d\n",
1629                     convertESamplingFrequency( samplingFrequency ),
1630                     plug.getName(),
1631                     plug.getPlugId() );
1632         return false;
1633     }
1634
1635     return true;
1636 }
1637
1638 bool
1639 AvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
1640 {
1641     AvPlug* plug = getPlugById( m_isoInputPlugs, 0 );
1642     if ( !plug ) {
1643         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
1644         return false;
1645     }
1646
1647     if ( !setSamplingFrequencyPlug( *plug, PlugAddress::ePD_Input, samplingFrequency ) ) {
1648         debugError( "setSampleRate: Setting sample rate failed\n" );
1649         return false;
1650     }
1651
1652     plug = getPlugById( m_isoOutputPlugs, 0 );
1653     if ( !plug ) {
1654         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
1655         return false;
1656     }
1657
1658     if ( !setSamplingFrequencyPlug( *plug, PlugAddress::ePD_Output, samplingFrequency ) ) {
1659         debugError( "setSampleRate: Setting sample rate failed\n" );
1660         return false;
1661     }
1662
1663     debugOutput( DEBUG_LEVEL_VERBOSE,
1664                  "setSampleRate: Set sample rate to %d\n",  convertESamplingFrequency( samplingFrequency ) );
1665     return true;
1666 }
1667
1668 int
1669 AvDevice::getSamplingFrequency( ) {
1670     AvPlug* inputPlug = getPlugById( m_isoInputPlugs, 0 );
1671     if ( !inputPlug ) {
1672         debugError( "No iso input plug found with id %d\n" );
1673         return false;
1674     }
1675     AvPlug* outputPlug = getPlugById( m_isoOutputPlugs, 0 );
1676     if ( !outputPlug ) {
1677         debugError( "No iso output plug found with id %d\n" );
1678         return false;
1679     }
1680
1681         int samplerate_playback=inputPlug->getSampleRate();
1682         int samplerate_capture=outputPlug->getSampleRate();
1683
1684         if (samplerate_playback != samplerate_capture) {
1685                 debugWarning("Samplerates for capture and playback differ!\n");
1686         }
1687         return samplerate_capture;
1688 }
1689
1690
1691
1692 ConfigRom&
1693 AvDevice::getConfigRom() const
1694 {
1695     return *m_configRom;
1696 }
1697
1698 void
1699 AvDevice::showDevice() const
1700 {
1701     debugWarning( "showDevice: not implemented\n" );
1702 }
1703
1704 bool
1705 AvDevice::prepare() {
1706     ///////////
1707     // get plugs
1708
1709     AvPlug* inputPlug = getPlugById( m_isoInputPlugs, 0 );
1710     if ( !inputPlug ) {
1711         debugError( "No iso input plug found with id %d\n" );
1712         return false;
1713     }
1714     AvPlug* outputPlug = getPlugById( m_isoOutputPlugs, 0 );
1715     if ( !outputPlug ) {
1716         debugError( "No iso output plug found with id %d\n" );
1717         return false;
1718     }
1719
1720         int samplerate=outputPlug->getSampleRate();
1721         m_receiveProcessor=new FreebobStreaming::AmdtpReceiveStreamProcessor(
1722                                  m_1394Service->getPort(),
1723                                  samplerate,
1724                                  outputPlug->getNrOfChannels());
1725
1726         if(!m_receiveProcessor->init()) {
1727                 debugFatal("Could not initialize receive processor!\n");
1728                 return false;
1729        
1730         }
1731
1732         if (!addPlugToProcessor(*outputPlug,m_receiveProcessor,
1733                 FreebobStreaming::AmdtpAudioPort::E_Capture)) {
1734                 debugFatal("Could not add plug to processor!\n");
1735                 return false;
1736         }
1737
1738         // do the transmit processor
1739         // for now we are snooping, so these are receive too.
1740 //      samplerate=inputPlug->getSampleRate();
1741 //      m_receiveProcessor2=new FreebobStreaming::AmdtpReceiveStreamProcessor(
1742 //                               channel,
1743 //                               m_1394Service->getPort(),
1744 //                               samplerate,
1745 //                               inputPlug->getNrOfChannels());
1746 //
1747 //      if (!addPlugToProcessor(*inputPlug,m_receiveProcessor2,
1748 //              FreebobStreaming::AmdtpAudioPort::E_Capture)) {
1749 //              debugFatal("Could not add plug to processor!\n");
1750 //              return false;
1751 //      }
1752
1753         // do the transmit processor
1754         samplerate=inputPlug->getSampleRate();
1755         m_transmitProcessor=new FreebobStreaming::AmdtpTransmitStreamProcessor(
1756                                  m_1394Service->getPort(),
1757                                  samplerate,
1758                                  inputPlug->getNrOfChannels());
1759                                  
1760         if(!m_transmitProcessor->init()) {
1761                 debugFatal("Could not initialize transmit processor!\n");
1762                 return false;
1763        
1764         }
1765
1766         if (!addPlugToProcessor(*inputPlug,m_transmitProcessor,
1767                 FreebobStreaming::AmdtpAudioPort::E_Playback)) {
1768                 debugFatal("Could not add plug to processor!\n");
1769                 return false;
1770         }
1771
1772         return true;
1773 }
1774
1775 bool
1776 AvDevice::addPlugToProcessor(
1777         AvPlug& plug,
1778         FreebobStreaming::StreamProcessor *processor,
1779         FreebobStreaming::AmdtpAudioPort::E_Direction direction) {
1780
1781     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
1782     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
1783           it != clusterInfos.end();
1784           ++it )
1785     {
1786         const AvPlug::ClusterInfo* clusterInfo = &( *it );
1787
1788         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1789         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1790               it != channelInfos.end();
1791               ++it )
1792         {
1793             const AvPlug::ChannelInfo* channelInfo = &( *it );
1794
1795                         FreebobStreaming::Port *p=NULL;
1796                         switch(clusterInfo->m_portType) {
1797                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
1798                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
1799                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
1800                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
1801                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
1802                                 p=new FreebobStreaming::AmdtpAudioPort(
1803                                                 channelInfo->m_name,
1804                                                 direction,
1805                                                 // \todo: streaming backend expects indexing starting from 0
1806                                                 // but bebob reports it starting from 1. Decide where
1807                                                 // and how to handle this (pp: here)
1808                                                 channelInfo->m_streamPosition - 1,
1809                                                 channelInfo->m_location,
1810                                                 FreebobStreaming::AmdtpPortInfo::E_MBLA,
1811                                                 clusterInfo->m_portType
1812                                 );
1813                                 break;
1814
1815                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
1816                                 p=new FreebobStreaming::AmdtpMidiPort(
1817                                                 channelInfo->m_name,
1818                                                 direction,
1819                                                 // \todo: streaming backend expects indexing starting from 0
1820                                                 // but bebob reports it starting from 1. Decide where
1821                                                 // and how to handle this (pp: here)
1822                                                 channelInfo->m_streamPosition - 1,
1823                                                 channelInfo->m_location,
1824                                                 FreebobStreaming::AmdtpPortInfo::E_Midi,
1825                                                 clusterInfo->m_portType
1826                                 );
1827
1828                                 break;
1829                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
1830                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
1831                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
1832                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
1833                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
1834                         case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
1835                         default:
1836                         // unsupported
1837                                 break;
1838                         }
1839
1840                         if (!p) {
1841                                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
1842                         } else {
1843                
1844                                 if (!processor->addPort(p)) {
1845                                         debugWarning("Could not register port with stream processor\n");
1846                                         return false;
1847                                 }
1848                         }
1849          }
1850     }
1851         return true;
1852 }
1853
1854 int
1855 AvDevice::getStreamCount() {
1856         return 2; // one receive, one transmit
1857 }
1858
1859 FreebobStreaming::StreamProcessor *
1860 AvDevice::getStreamProcessorByIndex(int i) {
1861         switch (i) {
1862         case 0:
1863                 return m_receiveProcessor;
1864         case 1:
1865 //              return m_receiveProcessor2;
1866                 return m_transmitProcessor;
1867         default:
1868                 return NULL;
1869         }
1870         return 0;
1871 }
1872
1873 int
1874 AvDevice::startStreamByIndex(int i) {
1875         int iso_channel=0;
1876         int plug=0;
1877         int hostplug=-1;
1878        
1879         switch (i) {
1880         case 0:
1881                 // do connection management: make connection
1882                 iso_channel = iec61883_cmp_connect(
1883                         m_1394Service->getHandle(),
1884                         m_nodeId | 0xffc0,
1885                         &plug,
1886                         raw1394_get_local_id (m_1394Service->getHandle()),
1887                         &hostplug,
1888                         &m_receiveProcessorBandwidth);
1889                
1890                 // set the channel obtained by the connection management
1891                 m_receiveProcessor->setChannel(iso_channel);
1892                 break;
1893         case 1:
1894                 // do connection management: make connection
1895                 iso_channel = iec61883_cmp_connect(
1896                         m_1394Service->getHandle(),
1897                         raw1394_get_local_id (m_1394Service->getHandle()),
1898                         &hostplug,
1899                         m_nodeId | 0xffc0,
1900                         &plug,
1901                         &m_transmitProcessorBandwidth);
1902                
1903                 // set the channel obtained by the connection management
1904 //              m_receiveProcessor2->setChannel(iso_channel);
1905                 m_transmitProcessor->setChannel(iso_channel);
1906                 break;
1907         default:
1908                 return 0;
1909         }
1910
1911         return 0;
1912
1913 }
1914
1915 int
1916 AvDevice::stopStreamByIndex(int i) {
1917         // do connection management: break connection
1918
1919         int plug=0;
1920         int hostplug=-1;
1921
1922         switch (i) {
1923         case 0:
1924                 // do connection management: break connection
1925                 iec61883_cmp_disconnect(
1926                         m_1394Service->getHandle(),
1927                         m_nodeId | 0xffc0,
1928                         plug,
1929                         raw1394_get_local_id (m_1394Service->getHandle()),
1930                         hostplug,
1931                         m_receiveProcessor->getChannel(),
1932                         m_receiveProcessorBandwidth);
1933
1934                 break;
1935         case 1:
1936                 // do connection management: break connection
1937                 iec61883_cmp_disconnect(
1938                         m_1394Service->getHandle(),
1939                         raw1394_get_local_id (m_1394Service->getHandle()),
1940                         hostplug,
1941                         m_nodeId | 0xffc0,
1942                         plug,
1943                         m_transmitProcessor->getChannel(),
1944                         m_transmitProcessorBandwidth);
1945
1946                 // set the channel obtained by the connection management
1947 //              m_receiveProcessor2->setChannel(iso_channel);
1948                 break;
1949         default:
1950                 return 0;
1951         }
1952
1953         return 0;
1954 }
1955
1956 } // end of namespace
1957
Note: See TracBrowser for help on using the browser.