root/trunk/libfreebob/src/bebob_light/bebob_light_avdevice.cpp

Revision 241, 59.5 kB (checked in by pieterpalmers, 16 years ago)

* configure.ac: Version bump to 1.0.0

* Changed all FreeBob? to FreeBoB
* Removed all .cvsignore
* Added Pieter to AUTHORS
* Updated NEWS and README (release canditate date added)

by Daniel Wagner

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