root/trunk/libfreebob/src/bebob/bebob_avdevice.cpp

Revision 370, 38.6 kB (checked in by wagi, 17 years ago)

Don't cache node id everywhere, config rom holds an updated version of the node id

Line 
1 /* bebob_avdevice.cpp
2  * Copyright (C) 2005,06 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "bebob/bebob_avdevice.h"
22 #include "bebob/bebob_avdevice_subunit.h"
23 #include "configrom.h"
24
25 #include "libfreebobavc/avc_plug_info.h"
26 #include "libfreebobavc/avc_extended_plug_info.h"
27 #include "libfreebobavc/avc_subunit_info.h"
28 #include "libfreebobavc/avc_extended_stream_format.h"
29 #include "libfreebobavc/avc_serialize.h"
30 #include "libfreebobavc/ieee1394service.h"
31 #include "libfreebobavc/avc_definitions.h"
32
33 #include "debugmodule/debugmodule.h"
34
35 #include <iostream>
36 #include <sstream>
37
38 namespace BeBoB {
39
40 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_NORMAL );
41
42 AvDevice::AvDevice( std::auto_ptr< ConfigRom >( configRom ),
43                     Ieee1394Service& ieee1394service,
44                     int nodeId,
45                     int verboseLevel )
46     : m_pConfigRom( configRom )
47     , m_1394Service( &ieee1394service )
48     , m_verboseLevel( verboseLevel )
49     , m_plugManager( verboseLevel )
50     , m_activeSyncInfo( 0 )
51     , m_id( 0 )
52     , m_receiveProcessor ( 0 )
53     , m_receiveProcessorBandwidth ( -1 )
54     , m_transmitProcessor ( 0 )
55     , m_transmitProcessorBandwidth ( -1 )
56 {
57     setDebugLevel( verboseLevel );
58     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
59                  nodeId );
60 }
61
62 AvDevice::AvDevice()
63     : m_pConfigRom( 0 )
64     , m_1394Service( 0 )
65     , m_verboseLevel( 0 )
66     , m_plugManager( 0 )
67     , m_activeSyncInfo( 0 )
68     , m_id( 0 )
69     , m_receiveProcessor ( 0 )
70     , m_receiveProcessorBandwidth ( -1 )
71     , m_transmitProcessor ( 0 )
72     , m_transmitProcessorBandwidth ( -1 )
73 {
74 }
75
76 AvDevice::~AvDevice()
77 {
78     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
79           it != m_subunits.end();
80           ++it )
81     {
82         delete *it;
83     }
84     for ( AvPlugConnectionVector::iterator it = m_plugConnections.begin();
85           it != m_plugConnections.end();
86           ++it )
87     {
88         delete *it;
89     }
90     for ( AvPlugVector::iterator it = m_pcrPlugs.begin();
91           it != m_pcrPlugs.end();
92           ++it )
93     {
94         delete *it;
95     }
96     for ( AvPlugVector::iterator it = m_externalPlugs.begin();
97           it != m_externalPlugs.end();
98           ++it )
99     {
100         delete *it;
101     }
102 }
103
104 ConfigRom&
105 AvDevice::getConfigRom() const
106 {
107     return *m_pConfigRom;
108 }
109
110 struct VendorModelEntry {
111     unsigned int vendor_id;
112     unsigned int model_id;
113 };
114
115 static VendorModelEntry supportedDeviceList[] =
116 {
117     {0x00000f, 0x00010065},  // Mackie, Onyx Firewire
118
119     {0x0003db, 0x00010048},  // Apogee Electronics, Rosetta 200
120
121     {0x0007f5, 0x00010048},  // BridgeCo, RD Audio1
122
123     {0x000a92, 0x00010066},  // Presonous FirePOD
124
125     {0x000aac, 0x00000003},  // TerraTec Electronic GmbH, Phase 88 FW
126     {0x000aac, 0x00000004},  // TerraTec Electronic GmbH, Phase X24 FW (model version 4)
127     {0x000aac, 0x00000007},  // TerraTec Electronic GmbH, Phase X24 FW (model version 7)
128
129     {0x000f1b, 0x00010064},  // ESI, Quatafire 610
130
131     {0x00130e, 0x00000003},  // Focusrite, Pro26IO (Saffire 26)
132
133     {0x0040ab, 0x00010048},  // EDIROL, FA-101
134     {0x0040ab, 0x00010049},  // EDIROL, FA-66
135 };
136
137 bool
138 AvDevice::probe( ConfigRom& configRom )
139 {
140     unsigned int vendorId = configRom.getNodeVendorId();
141     unsigned int modelId = configRom.getModelId();
142
143     for ( unsigned int i = 0;
144           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
145           ++i )
146     {
147         if ( ( supportedDeviceList[i].vendor_id == vendorId )
148              && ( supportedDeviceList[i].model_id == modelId ) )
149         {
150             return true;
151         }
152     }
153
154     return false;
155 }
156
157 bool
158 AvDevice::discover()
159 {
160     if ( !enumerateSubUnits() ) {
161         debugError( "Could not enumarate sub units\n" );
162         return false;
163     }
164
165     if ( !discoverPlugs() ) {
166         debugError( "Detecting plugs failed\n" );
167         return false;
168     }
169
170     if ( !discoverPlugConnections() ) {
171         debugError( "Detecting plug connections failed\n" );
172         return false;
173     }
174
175     if ( !discoverSubUnitsPlugConnections() ) {
176         debugError( "Detecting plug connnection failed\n" );
177         return false;
178     }
179
180     if ( !discoverSyncModes() ) {
181         debugError( "Detecting sync modes failed\n" );
182         return false;
183     }
184
185     return true;
186 }
187
188 bool
189 AvDevice::discoverPlugs()
190 {
191     //////////////////////////////////////////////
192     // Get number of available isochronous input
193     // and output plugs of unit
194
195     PlugInfoCmd plugInfoCmd( m_1394Service );
196     plugInfoCmd.setNodeId( m_pConfigRom->getNodeId() );
197     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
198     plugInfoCmd.setVerbose( m_verboseLevel );
199
200     if ( !plugInfoCmd.fire() ) {
201         debugError( "plug info command failed\n" );
202         return false;
203     }
204
205     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso input plugs = %d\n",
206                  plugInfoCmd.m_serialBusIsochronousInputPlugs );
207     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso output plugs = %d\n",
208                  plugInfoCmd.m_serialBusIsochronousOutputPlugs );
209     debugOutput( DEBUG_LEVEL_NORMAL, "number of external input plugs = %d\n",
210                  plugInfoCmd.m_externalInputPlugs );
211     debugOutput( DEBUG_LEVEL_NORMAL, "number of external output plugs = %d\n",
212                  plugInfoCmd.m_externalOutputPlugs );
213
214     if ( !discoverPlugsPCR( AvPlug::eAPD_Input,
215                             plugInfoCmd.m_serialBusIsochronousInputPlugs ) )
216     {
217         debugError( "pcr input plug discovering failed\n" );
218         return false;
219     }
220
221     if ( !discoverPlugsPCR( AvPlug::eAPD_Output,
222                             plugInfoCmd.m_serialBusIsochronousOutputPlugs ) )
223     {
224         debugError( "pcr output plug discovering failed\n" );
225         return false;
226     }
227
228     if ( !discoverPlugsExternal( AvPlug::eAPD_Input,
229                                  plugInfoCmd.m_externalInputPlugs ) )
230     {
231         debugError( "external input plug discovering failed\n" );
232         return false;
233     }
234
235     if ( !discoverPlugsExternal( AvPlug::eAPD_Output,
236                                  plugInfoCmd.m_externalOutputPlugs ) )
237     {
238         debugError( "external output plug discovering failed\n" );
239         return false;
240     }
241
242     return true;
243 }
244
245 bool
246 AvDevice::discoverPlugsPCR( AvPlug::EAvPlugDirection plugDirection,
247                             plug_id_t plugMaxId )
248 {
249     for ( int plugId = 0;
250           plugId < plugMaxId;
251           ++plugId )
252     {
253         AvPlug* plug  = new AvPlug( *m_1394Service,
254                                     *m_pConfigRom,
255                                     m_plugManager,
256                                     AVCCommand::eST_Unit,
257                                     0xff,
258                                     0xff,
259                                     0xff,
260                                     AvPlug::eAPA_PCR,
261                                     plugDirection,
262                                     plugId,
263                                     m_verboseLevel );
264         if ( !plug || !plug->discover() ) {
265             debugError( "plug discovering failed\n" );
266             delete plug;
267             return false;
268         }
269
270         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
271                      plug->getName() );
272         m_pcrPlugs.push_back( plug );
273     }
274
275     return true;
276 }
277
278 bool
279 AvDevice::discoverPlugsExternal( AvPlug::EAvPlugDirection plugDirection,
280                                  plug_id_t plugMaxId )
281 {
282     for ( int plugId = 0;
283           plugId < plugMaxId;
284           ++plugId )
285     {
286         AvPlug* plug  = new AvPlug( *m_1394Service,
287                                     *m_pConfigRom,
288                                     m_plugManager,
289                                     AVCCommand::eST_Unit,
290                                     0xff,
291                                     0xff,
292                                     0xff,
293                                     AvPlug::eAPA_ExternalPlug,
294                                     plugDirection,
295                                     plugId,
296                                     m_verboseLevel );
297         if ( !plug || !plug->discover() ) {
298             debugError( "plug discovering failed\n" );
299             return false;
300         }
301
302         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
303                      plug->getName() );
304         m_externalPlugs.push_back( plug );
305     }
306
307     return true;
308 }
309
310 bool
311 AvDevice::discoverPlugConnections()
312 {
313     for ( AvPlugVector::iterator it = m_pcrPlugs.begin();
314           it != m_pcrPlugs.end();
315           ++it )
316     {
317         AvPlug* plug = *it;
318         if ( !plug->discoverConnections() ) {
319             debugError( "Could not discover plug connections\n" );
320             return false;
321         }
322     }
323     for ( AvPlugVector::iterator it = m_externalPlugs.begin();
324           it != m_externalPlugs.end();
325           ++it )
326     {
327         AvPlug* plug = *it;
328         if ( !plug->discoverConnections() ) {
329             debugError( "Could not discover plug connections\n" );
330             return false;
331         }
332     }
333
334     return true;
335 }
336
337 bool
338 AvDevice::discoverSubUnitsPlugConnections()
339 {
340     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
341           it != m_subunits.end();
342           ++it )
343     {
344         AvDeviceSubunit* subunit = *it;
345         if ( !subunit->discoverConnections() ) {
346             debugError( "Subunit '%s'  plug connections failed\n",
347                         subunit->getName() );
348             return false;
349         }
350     }
351     return true;
352 }
353
354 bool
355 AvDevice::discoverSyncModes()
356 {
357     // Following possible sync plugs exists:
358     // - Music subunit sync output plug = internal sync (CSP)
359     // - Unit input plug 0 = SYT match
360     // - Unit input plut 1 = Sync stream
361     //
362     // If last sync mode is reported it is mostelikely not
363     // implemented *sic*
364     //
365     // Following sync sources are device specific:
366     // - All unit external input plugs which have a
367     //   sync information (WS, SPDIF, ...)
368
369     // First we have to find the sync input and output plug
370     // in the music subunit.
371
372     // Note PCR input means 1394bus-to-device where as
373     // MSU input means subunit-to-device
374
375     AvPlugVector syncPCRInputPlugs = getPlugsByType( m_pcrPlugs,
376                                                      AvPlug::eAPD_Input,
377                                                      AvPlug::eAPT_Sync );
378     if ( !syncPCRInputPlugs.size() ) {
379         debugWarning( "No PCR sync input plug found\n" );
380     }
381
382     AvPlugVector syncPCROutputPlugs = getPlugsByType( m_pcrPlugs,
383                                                       AvPlug::eAPD_Output,
384                                                       AvPlug::eAPT_Sync );
385     if ( !syncPCROutputPlugs.size() ) {
386         debugWarning( "No PCR sync output plug found\n" );
387     }
388
389     AvPlugVector isoPCRInputPlugs = getPlugsByType( m_pcrPlugs,
390                                                     AvPlug::eAPD_Input,
391                                                     AvPlug::eAPT_IsoStream );
392     if ( !isoPCRInputPlugs.size() ) {
393         debugWarning( "No PCR iso input plug found\n" );
394
395     }
396
397     AvPlugVector isoPCROutputPlugs = getPlugsByType( m_pcrPlugs,
398                                                     AvPlug::eAPD_Output,
399                                                     AvPlug::eAPT_IsoStream );
400     if ( !isoPCROutputPlugs.size() ) {
401         debugWarning( "No PCR iso output plug found\n" );
402
403     }
404
405     AvPlugVector digitalPCRInputPlugs = getPlugsByType( m_externalPlugs,
406                                                     AvPlug::eAPD_Input,
407                                                     AvPlug::eAPT_Digital );
408
409     AvPlugVector syncMSUInputPlugs = m_plugManager.getPlugsByType(
410         AVCCommand::eST_Music,
411         0,
412         0xff,
413         0xff,
414         AvPlug::eAPA_SubunitPlug,
415         AvPlug::eAPD_Input,
416         AvPlug::eAPT_Sync );
417     if ( !syncMSUInputPlugs.size() ) {
418         debugWarning( "No sync input plug for MSU subunit found\n" );
419     }
420
421     AvPlugVector syncMSUOutputPlugs = m_plugManager.getPlugsByType(
422         AVCCommand::eST_Music,
423         0,
424         0xff,
425         0xff,
426         AvPlug::eAPA_SubunitPlug,
427         AvPlug::eAPD_Output,
428         AvPlug::eAPT_Sync );
429     if ( !syncMSUOutputPlugs.size() ) {
430         debugWarning( "No sync output plug for MSU subunit found\n" );
431     }
432
433     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Input Plugs:\n" );
434     showAvPlugs( syncPCRInputPlugs );
435     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Output Plugs:\n" );
436     showAvPlugs( syncPCROutputPlugs );
437     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Input Plugs:\n" );
438     showAvPlugs( isoPCRInputPlugs );
439     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Output Plugs:\n" );
440     showAvPlugs( isoPCROutputPlugs );
441     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR digital Input Plugs:\n" );
442     showAvPlugs( digitalPCRInputPlugs );
443     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Input Plugs:\n" );
444     showAvPlugs( syncMSUInputPlugs );
445     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Output Plugs:\n" );
446     showAvPlugs( syncMSUOutputPlugs );
447
448     // Check all possible PCR input to MSU input connections
449     // -> sync stream input
450     checkSyncConnectionsAndAddToList( syncPCRInputPlugs,
451                                       syncMSUInputPlugs,
452                                       "Sync Stream Input" );
453
454     // Check all possible MSU output to PCR output connections
455     // -> sync stream output
456     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
457                                       syncPCROutputPlugs,
458                                       "Sync Stream Output" );
459
460     // Check all PCR iso input to MSU input connections
461     // -> SYT match
462     checkSyncConnectionsAndAddToList( isoPCRInputPlugs,
463                                       syncMSUInputPlugs,
464                                       "Syt Match" );
465
466     // Check all MSU sync output to MSU input connections
467     // -> CSP
468     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
469                                       syncMSUInputPlugs,
470                                       "Internal (CSP)" );
471
472     // Check all external PCR digital input to MSU input connections
473     // -> SPDIF/ADAT sync
474     checkSyncConnectionsAndAddToList( digitalPCRInputPlugs,
475                                       syncMSUInputPlugs,
476                                       "Digital Input Sync" );
477
478     // Currently active connection signal source cmd, command type
479     // status, source unknown, destination MSU sync input plug
480
481     for ( AvPlugVector::const_iterator it = syncMSUInputPlugs.begin();
482           it != syncMSUInputPlugs.end();
483           ++it )
484     {
485         AvPlug* msuPlug = *it;
486         for ( AvPlugVector::const_iterator jt =
487                   msuPlug->getInputConnections().begin();
488               jt != msuPlug->getInputConnections().end();
489               ++jt )
490         {
491             AvPlug* plug = *jt;
492
493             for ( SyncInfoVector::iterator it = m_syncInfos.begin();
494                   it != m_syncInfos.end();
495                   ++it )
496             {
497                 SyncInfo* pSyncInfo = &*it;
498                 if ( ( pSyncInfo->m_source == plug )
499                      && ( pSyncInfo->m_destination == msuPlug ) )
500                 {
501                     m_activeSyncInfo = pSyncInfo;
502                     break;
503                 }
504             }
505             debugOutput( DEBUG_LEVEL_NORMAL,
506                          "Active Sync Connection: '%s' -> '%s'\n",
507                          plug->getName(),
508                          msuPlug->getName() );
509         }
510     }
511
512     return true;
513 }
514
515 bool
516 AvDevice::enumerateSubUnits()
517 {
518     bool musicSubunitFound=false;
519     bool audioSubunitFound=false;
520
521     SubUnitInfoCmd subUnitInfoCmd( m_1394Service );
522     //subUnitInfoCmd.setVerbose( 1 );
523     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
524
525     // BeBoB has always exactly one audio and one music subunit. This
526     // means is fits into the first page of the SubUnitInfo command.
527     // So there is no need to do more than needed
528
529     subUnitInfoCmd.m_page = 0;
530     subUnitInfoCmd.setNodeId( m_pConfigRom->getNodeId() );
531     subUnitInfoCmd.setVerbose( m_verboseLevel );
532     if ( !subUnitInfoCmd.fire() ) {
533         debugError( "Subunit info command failed\n" );
534         // shouldn't this be an error situation?
535         return false;
536     }
537
538     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
539         subunit_type_t subunit_type
540             = subUnitInfoCmd.m_table[i].m_subunit_type;
541
542         unsigned int subunitId = getNrOfSubunits( subunit_type );
543
544         debugOutput( DEBUG_LEVEL_VERBOSE,
545                      "subunit_id = %2d, subunit_type = %2d (%s)\n",
546                      subunitId,
547                      subunit_type,
548                      subunitTypeToString( subunit_type ) );
549
550         AvDeviceSubunit* subunit = 0;
551         switch( subunit_type ) {
552         case AVCCommand::eST_Audio:
553             subunit = new AvDeviceSubunitAudio( *this, subunitId,
554                                                 m_verboseLevel );
555             if ( !subunit ) {
556                 debugFatal( "Could not allocate AvDeviceSubunitAudio\n" );
557                 return false;
558             }
559
560             m_subunits.push_back( subunit );
561             audioSubunitFound=true;
562
563             break;
564         case AVCCommand::eST_Music:
565             subunit = new AvDeviceSubunitMusic( *this, subunitId,
566                                                 m_verboseLevel );
567             if ( !subunit ) {
568                 debugFatal( "Could not allocate AvDeviceSubunitMusic\n" );
569                 return false;
570             }
571
572             m_subunits.push_back( subunit );
573             musicSubunitFound=true;
574
575             break;
576         default:
577             debugOutput( DEBUG_LEVEL_NORMAL,
578                          "Unsupported subunit found, subunit_type = %d (%s)\n",
579                          subunit_type,
580                          subunitTypeToString( subunit_type ) );
581             continue;
582
583         }
584
585         if ( !subunit->discover() ) {
586             debugError( "enumerateSubUnits: Could not discover "
587                         "subunit_id = %2d, subunit_type = %2d (%s)\n",
588                         subunitId,
589                         subunit_type,
590                         subunitTypeToString( subunit_type ) );
591             delete subunit;
592             return false;
593         }
594
595     }
596
597     // a BeBoB always has an audio and a music subunit
598     return (musicSubunitFound && audioSubunitFound);
599 }
600
601
602 AvDeviceSubunit*
603 AvDevice::getSubunit( subunit_type_t subunitType,
604                       subunit_id_t subunitId ) const
605 {
606     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
607           it != m_subunits.end();
608           ++it )
609     {
610         AvDeviceSubunit* subunit = *it;
611         if ( ( subunitType == subunit->getSubunitType() )
612              && ( subunitId == subunit->getSubunitId() ) )
613         {
614             return subunit;
615         }
616     }
617
618     return 0;
619 }
620
621
622 unsigned int
623 AvDevice::getNrOfSubunits( subunit_type_t subunitType ) const
624 {
625     unsigned int nrOfSubunits = 0;
626
627     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
628           it != m_subunits.end();
629           ++it )
630     {
631         AvDeviceSubunit* subunit = *it;
632         if ( subunitType == subunit->getSubunitType() ) {
633             nrOfSubunits++;
634         }
635     }
636
637     return nrOfSubunits;
638 }
639
640 AvPlugConnection*
641 AvDevice::getPlugConnection( AvPlug& srcPlug ) const
642 {
643     for ( AvPlugConnectionVector::const_iterator it
644               = m_plugConnections.begin();
645           it != m_plugConnections.end();
646           ++it )
647     {
648         AvPlugConnection* plugConnection = *it;
649         if ( &( plugConnection->getSrcPlug() ) == &srcPlug ) {
650             return plugConnection;
651         }
652     }
653
654     return 0;
655 }
656
657 AvPlug*
658 AvDevice::getPlugById( AvPlugVector& plugs,
659                        AvPlug::EAvPlugDirection plugDirection,
660                        int id )
661 {
662     for ( AvPlugVector::iterator it = plugs.begin();
663           it != plugs.end();
664           ++it )
665     {
666         AvPlug* plug = *it;
667         if ( ( id == plug->getPlugId() )
668              && ( plugDirection == plug->getPlugDirection() ) )
669         {
670             return plug;
671         }
672     }
673
674     return 0;
675 }
676
677 AvPlugVector
678 AvDevice::getPlugsByType( AvPlugVector& plugs,
679                           AvPlug::EAvPlugDirection plugDirection,
680                           AvPlug::EAvPlugType type)
681 {
682     AvPlugVector plugVector;
683     for ( AvPlugVector::iterator it = plugs.begin();
684           it != plugs.end();
685           ++it )
686     {
687         AvPlug* plug = *it;
688         if ( ( type == plug->getPlugType() )
689              && ( plugDirection == plug->getPlugDirection() ) )
690         {
691             plugVector.push_back( plug );
692         }
693     }
694
695     return plugVector;
696 }
697
698 AvPlug*
699 AvDevice::getSyncPlug( int maxPlugId, AvPlug::EAvPlugDirection )
700 {
701     return 0;
702 }
703
704 bool
705 AvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
706 {
707
708     AvPlug* plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
709     if ( !plug ) {
710         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
711         return false;
712     }
713
714     if ( !setSamplingFrequencyPlug( *plug,
715                                     AvPlug::eAPD_Input,
716                                     samplingFrequency ) )
717     {
718         debugError( "setSampleRate: Setting sample rate failed\n" );
719         return false;
720     }
721
722     plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output,  0 );
723     if ( !plug ) {
724         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
725         return false;
726     }
727
728     if ( !setSamplingFrequencyPlug( *plug,
729                                     AvPlug::eAPD_Output,
730                                     samplingFrequency ) )
731     {
732         debugError( "setSampleRate: Setting sample rate failed\n" );
733         return false;
734     }
735
736
737     debugOutput( DEBUG_LEVEL_VERBOSE,
738                  "setSampleRate: Set sample rate to %d\n",
739                  convertESamplingFrequency( samplingFrequency ) );
740     return true;
741 }
742
743 int
744 AvDevice::getSamplingFrequency( ) {
745     AvPlug* inputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
746     if ( !inputPlug ) {
747         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
748         return false;
749     }
750     AvPlug* outputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 );
751     if ( !outputPlug ) {
752         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
753         return false;
754     }
755
756     int samplerate_playback=inputPlug->getSampleRate();
757     int samplerate_capture=outputPlug->getSampleRate();
758
759     if (samplerate_playback != samplerate_capture) {
760         debugWarning("Samplerates for capture and playback differ!\n");
761     }
762     return samplerate_capture;
763 }
764
765
766 bool
767 AvDevice::setSamplingFrequencyPlug( AvPlug& plug,
768                                     AvPlug::EAvPlugDirection direction,
769                                     ESamplingFrequency samplingFrequency )
770 {
771
772     ExtendedStreamFormatCmd extStreamFormatCmd(
773         m_1394Service,
774         ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList );
775     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
776                                      plug.getPlugId() );
777
778     extStreamFormatCmd.setPlugAddress(
779         PlugAddress(
780             AvPlug::convertPlugDirection(direction ),
781             PlugAddress::ePAM_Unit,
782             unitPlugAddress ) );
783
784     extStreamFormatCmd.setNodeId( m_pConfigRom->getNodeId() );
785     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
786
787     int i = 0;
788     bool cmdSuccess = false;
789     bool correctFormatFound = false;
790
791     do {
792         extStreamFormatCmd.setIndexInStreamFormat( i );
793         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
794         extStreamFormatCmd.setVerbose( m_verboseLevel );
795
796         cmdSuccess = extStreamFormatCmd.fire();
797
798         if ( cmdSuccess
799              && ( extStreamFormatCmd.getResponse() ==
800                   AVCCommand::eR_Implemented ) )
801         {
802             ESamplingFrequency foundFreq = eSF_DontCare;
803
804             FormatInformation* formatInfo =
805                 extStreamFormatCmd.getFormatInformation();
806             FormatInformationStreamsCompound* compoundStream
807                 = dynamic_cast< FormatInformationStreamsCompound* > (
808                     formatInfo->m_streams );
809             if ( compoundStream ) {
810                 foundFreq =
811                     static_cast< ESamplingFrequency >(
812                         compoundStream->m_samplingFrequency );
813             }
814
815             FormatInformationStreamsSync* syncStream
816                 = dynamic_cast< FormatInformationStreamsSync* > (
817                     formatInfo->m_streams );
818             if ( syncStream ) {
819                 foundFreq =
820                     static_cast< ESamplingFrequency >(
821                         syncStream->m_samplingFrequency );
822             }
823
824             if ( foundFreq == samplingFrequency )
825             {
826                 correctFormatFound = true;
827                 break;
828             }
829         }
830
831         ++i;
832     } while ( cmdSuccess
833               && ( extStreamFormatCmd.getResponse() ==
834                    ExtendedStreamFormatCmd::eR_Implemented ) );
835
836     if ( !cmdSuccess ) {
837         debugError( "setSampleRatePlug: Failed to retrieve format info\n" );
838         return false;
839     }
840
841     if ( !correctFormatFound ) {
842         debugError( "setSampleRatePlug: %s plug %d does not support "
843                     "sample rate %d\n",
844                     plug.getName(),
845                     plug.getPlugId(),
846                     convertESamplingFrequency( samplingFrequency ) );
847         return false;
848     }
849
850     extStreamFormatCmd.setSubFunction(
851         ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand );
852     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Control );
853     extStreamFormatCmd.setVerbose( m_verboseLevel );
854
855     if ( !extStreamFormatCmd.fire() ) {
856         debugError( "setSampleRate: Could not set sample rate %d "
857                     "to %s plug %d\n",
858                     convertESamplingFrequency( samplingFrequency ),
859                     plug.getName(),
860                     plug.getPlugId() );
861         return false;
862     }
863
864     return true;
865 }
866
867 void
868 AvDevice::showDevice() const
869 {
870     m_plugManager.showPlugs();
871 }
872
873 void
874 AvDevice::showAvPlugs( AvPlugVector& plugs ) const
875 {
876     int i = 0;
877     for ( AvPlugVector::const_iterator it = plugs.begin();
878           it != plugs.end();
879           ++it, ++i )
880     {
881         AvPlug* plug = *it;
882         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d\n", i );
883         plug->showPlug();
884     }
885 }
886
887 bool
888 AvDevice::checkSyncConnectionsAndAddToList( AvPlugVector& plhs,
889                                             AvPlugVector& prhs,
890                                             std::string syncDescription )
891 {
892     for ( AvPlugVector::iterator plIt = plhs.begin();
893           plIt != plhs.end();
894           ++plIt )
895     {
896         AvPlug* pl = *plIt;
897         for ( AvPlugVector::iterator prIt = prhs.begin();
898               prIt != prhs.end();
899               ++prIt )
900         {
901             AvPlug* pr = *prIt;
902             if ( pl->inquireConnnection( *pr ) ) {
903                 m_syncInfos.push_back( SyncInfo( *pl, *pr, syncDescription ) );
904                 debugOutput( DEBUG_LEVEL_NORMAL,
905                              "Sync connection '%s' -> '%s'\n",
906                              pl->getName(),
907                              pr->getName() );
908             }
909         }
910     }
911     return true;
912 }
913
914 bool AvDevice::setActiveSync(const SyncInfo& syncInfo)
915 {
916     return syncInfo.m_source->setConnection( *syncInfo.m_destination );
917 }
918
919 bool AvDevice::setId( unsigned int id)
920 {
921     // FIXME: decent ID system nescessary
922     m_id=id;
923         return true;
924 }
925
926 bool
927 AvDevice::prepare() {
928     ///////////
929     // get plugs
930
931     AvPlug* inputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
932     if ( !inputPlug ) {
933         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
934         return false;
935     }
936     AvPlug* outputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 );
937     if ( !outputPlug ) {
938         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
939         return false;
940     }
941
942     int samplerate=outputPlug->getSampleRate();
943     m_receiveProcessor=new FreebobStreaming::AmdtpReceiveStreamProcessor(
944                              m_1394Service->getPort(),
945                              samplerate,
946                              outputPlug->getNrOfChannels());
947
948     if(!m_receiveProcessor->init()) {
949         debugFatal("Could not initialize receive processor!\n");
950         return false;
951     }
952
953     if (!addPlugToProcessor(*outputPlug,m_receiveProcessor,
954         FreebobStreaming::AmdtpAudioPort::E_Capture)) {
955         debugFatal("Could not add plug to processor!\n");
956         return false;
957     }
958
959     // do the transmit processor
960 //     if (m_snoopMode) {
961 //         // we are snooping, so these are receive too.
962 //         samplerate=inputPlug->getSampleRate();
963 //         m_receiveProcessor2=new FreebobStreaming::AmdtpReceiveStreamProcessor(
964 //                                   channel,
965 //                                   m_1394Service->getPort(),
966 //                                   samplerate,
967 //                                   inputPlug->getNrOfChannels());
968 //
969 //         if(!m_receiveProcessor2->init()) {
970 //             debugFatal("Could not initialize snooping receive processor!\n");
971 //             return false;
972 //         }
973 //         if (!addPlugToProcessor(*inputPlug,m_receiveProcessor2,
974 //             FreebobStreaming::AmdtpAudioPort::E_Capture)) {
975 //             debugFatal("Could not add plug to processor!\n");
976 //             return false;
977 //         }
978 //     } else {
979         // do the transmit processor
980         samplerate=inputPlug->getSampleRate();
981         m_transmitProcessor=new FreebobStreaming::AmdtpTransmitStreamProcessor(
982                                 m_1394Service->getPort(),
983                                 samplerate,
984                                 inputPlug->getNrOfChannels());
985
986         if(!m_transmitProcessor->init()) {
987             debugFatal("Could not initialize transmit processor!\n");
988             return false;
989
990         }
991
992         // FIXME: do this the proper way!
993         m_transmitProcessor->syncmaster=m_receiveProcessor;
994
995         if (!addPlugToProcessor(*inputPlug,m_transmitProcessor,
996             FreebobStreaming::AmdtpAudioPort::E_Playback)) {
997             debugFatal("Could not add plug to processor!\n");
998             return false;
999         }
1000 //     }
1001
1002     return true;
1003 }
1004
1005 bool
1006 AvDevice::addPlugToProcessor(
1007     AvPlug& plug,
1008     FreebobStreaming::StreamProcessor *processor,
1009     FreebobStreaming::AmdtpAudioPort::E_Direction direction) {
1010
1011     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
1012     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
1013           it != clusterInfos.end();
1014           ++it )
1015     {
1016         const AvPlug::ClusterInfo* clusterInfo = &( *it );
1017
1018         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1019         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1020               it != channelInfos.end();
1021               ++it )
1022         {
1023             const AvPlug::ChannelInfo* channelInfo = &( *it );
1024             std::ostringstream portname;
1025
1026             portname << "dev" << m_id << "_" << channelInfo->m_name;
1027
1028             FreebobStreaming::Port *p=NULL;
1029             switch(clusterInfo->m_portType) {
1030             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
1031             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
1032             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
1033             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
1034             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
1035                 p=new FreebobStreaming::AmdtpAudioPort(
1036                         portname.str(),
1037                         direction,
1038                         // \todo: streaming backend expects indexing starting from 0
1039                         // but bebob reports it starting from 1. Decide where
1040                         // and how to handle this (pp: here)
1041                         channelInfo->m_streamPosition - 1,
1042                         channelInfo->m_location,
1043                         FreebobStreaming::AmdtpPortInfo::E_MBLA,
1044                         clusterInfo->m_portType
1045                 );
1046                 break;
1047
1048             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
1049                 p=new FreebobStreaming::AmdtpMidiPort(
1050                         portname.str(),
1051                         direction,
1052                         // \todo: streaming backend expects indexing starting from 0
1053                         // but bebob reports it starting from 1. Decide where
1054                         // and how to handle this (pp: here)
1055                         channelInfo->m_streamPosition - 1,
1056                         channelInfo->m_location,
1057                         FreebobStreaming::AmdtpPortInfo::E_Midi,
1058                         clusterInfo->m_portType
1059                 );
1060
1061                 break;
1062             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
1063             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
1064             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
1065             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
1066             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
1067             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
1068             default:
1069             // unsupported
1070                 break;
1071             }
1072
1073             if (!p) {
1074                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
1075             } else {
1076
1077                 if (!processor->addPort(p)) {
1078                     debugWarning("Could not register port with stream processor\n");
1079                     return false;
1080                 }
1081             }
1082          }
1083     }
1084     return true;
1085 }
1086
1087 int
1088 AvDevice::getStreamCount() {
1089     return 2; // one receive, one transmit
1090 }
1091
1092 FreebobStreaming::StreamProcessor *
1093 AvDevice::getStreamProcessorByIndex(int i) {
1094     switch (i) {
1095     case 0:
1096         return m_receiveProcessor;
1097     case 1:
1098 //         if (m_snoopMode) {
1099 //             return m_receiveProcessor2;
1100 //         } else {
1101             return m_transmitProcessor;
1102 //         }
1103     default:
1104         return NULL;
1105     }
1106     return 0;
1107 }
1108
1109 int
1110 AvDevice::startStreamByIndex(int i) {
1111     int iso_channel=0;
1112     int plug=0;
1113     int hostplug=-1;
1114
1115 //     if (m_snoopMode) {
1116 //
1117 //         switch (i) {
1118 //         case 0:
1119 //             // snooping doesn't use CMP, but obtains the info of the channel
1120 //             // from the target plug
1121 //
1122 //             // TODO: get isochannel from plug
1123 //
1124 //             // set the channel obtained by the connection management
1125 //             m_receiveProcessor->setChannel(iso_channel);
1126 //             break;
1127 //         case 1:
1128 //             // snooping doesn't use CMP, but obtains the info of the channel
1129 //             // from the target plug
1130 //
1131 //             // TODO: get isochannel from plug
1132 //
1133 //             // set the channel obtained by the connection management
1134 //             m_receiveProcessor2->setChannel(iso_channel);
1135 //
1136 //             break;
1137 //         default:
1138 //             return 0;
1139 //         }
1140 //     } else {
1141
1142         switch (i) {
1143         case 0:
1144             // do connection management: make connection
1145             iso_channel = iec61883_cmp_connect(
1146                 m_1394Service->getHandle(),
1147                 m_pConfigRom->getNodeId() | 0xffc0,
1148                 &plug,
1149                 raw1394_get_local_id (m_1394Service->getHandle()),
1150                 &hostplug,
1151                 &m_receiveProcessorBandwidth);
1152
1153             // set the channel obtained by the connection management
1154             m_receiveProcessor->setChannel(iso_channel);
1155             break;
1156         case 1:
1157             // do connection management: make connection
1158             iso_channel = iec61883_cmp_connect(
1159                 m_1394Service->getHandle(),
1160                 raw1394_get_local_id (m_1394Service->getHandle()),
1161                 &hostplug,
1162                 m_pConfigRom->getNodeId() | 0xffc0,
1163                 &plug,
1164                 &m_transmitProcessorBandwidth);
1165
1166             // set the channel obtained by the connection management
1167             m_transmitProcessor->setChannel(iso_channel);
1168             break;
1169         default:
1170             return 0;
1171         }
1172 //     }
1173
1174     return 0;
1175
1176 }
1177
1178 int
1179 AvDevice::stopStreamByIndex(int i) {
1180     // do connection management: break connection
1181
1182     int plug=0;
1183     int hostplug=-1;
1184 //     if (m_snoopMode) {
1185 //         switch (i) {
1186 //         case 0:
1187 //             // do connection management: break connection
1188 //
1189 //             break;
1190 //         case 1:
1191 //             // do connection management: break connection
1192 //
1193 //             break;
1194 //         default:
1195 //             return 0;
1196 //         }
1197 //     } else {
1198         switch (i) {
1199         case 0:
1200             // do connection management: break connection
1201             iec61883_cmp_disconnect(
1202                 m_1394Service->getHandle(),
1203                 m_pConfigRom->getNodeId() | 0xffc0,
1204                 plug,
1205                 raw1394_get_local_id (m_1394Service->getHandle()),
1206                 hostplug,
1207                 m_receiveProcessor->getChannel(),
1208                 m_receiveProcessorBandwidth);
1209
1210             break;
1211         case 1:
1212             // do connection management: break connection
1213             iec61883_cmp_disconnect(
1214                 m_1394Service->getHandle(),
1215                 raw1394_get_local_id (m_1394Service->getHandle()),
1216                 hostplug,
1217                 m_pConfigRom->getNodeId() | 0xffc0,
1218                 plug,
1219                 m_transmitProcessor->getChannel(),
1220                 m_transmitProcessorBandwidth);
1221
1222             break;
1223         default:
1224             return 0;
1225         }
1226 //     }
1227
1228     return 0;
1229 }
1230
1231 bool
1232 AvDevice::serialize( Glib::ustring basePath, Util::IOSerialize& ser )
1233 {
1234     bool result;
1235     result = m_pConfigRom->serialize( basePath + "m_pConfigRom/", ser );
1236
1237     return result;
1238 }
1239
1240 AvDevice*
1241 AvDevice::deserialize( Glib::ustring basePath,
1242                        Util::IODeserialize& deser,
1243                        Ieee1394Service& ieee1394Service )
1244 {
1245     AvDevice* pDev = new AvDevice;
1246
1247     if ( pDev ) {
1248         pDev->m_pConfigRom = std::auto_ptr<ConfigRom> (
1249             ConfigRom::deserialize( basePath + "m_pConfigRom/", deser, ieee1394Service )
1250             );
1251         if ( !pDev->m_pConfigRom.get() ) {
1252             delete pDev;
1253             return 0;
1254         }
1255
1256         pDev->m_1394Service = &ieee1394Service;
1257
1258     }
1259
1260     return pDev;
1261 }
1262
1263 } // end of namespace
Note: See TracBrowser for help on using the browser.