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

Revision 537, 54.9 kB (checked in by ppalmers, 17 years ago)

- SPDIF out works (tested)
- SPDIF in should work (untested)
- sync from external sync plug works

Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "bebob/bebob_avdevice.h"
25 #include "bebob/bebob_avdevice_subunit.h"
26 #include "bebob/GenericMixer.h"
27
28 #include "libieee1394/configrom.h"
29 #include "libieee1394/ieee1394service.h"
30
31 #include "libavc/avc_plug_info.h"
32 #include "libavc/avc_extended_plug_info.h"
33 #include "libavc/avc_subunit_info.h"
34 #include "libavc/avc_extended_stream_format.h"
35 #include "libavc/avc_serialize.h"
36 #include "libavc/avc_definitions.h"
37
38 #include "debugmodule/debugmodule.h"
39
40 #include <iostream>
41 #include <sstream>
42 #include <unistd.h>
43 #include <sys/stat.h>
44
45 namespace BeBoB {
46
47 static VendorModelEntry supportedDeviceList[] =
48 {
49     {0x00000f, 0x00010065, "Mackie", "Onyx Firewire"},
50
51     {0x0003db, 0x00010048, "Apogee Electronics", "Rosetta 200"},
52
53     {0x0007f5, 0x00010048, "BridgeCo", "RD Audio1"},
54
55     {0x000a92, 0x00010000, "PreSonus", "FIREBOX"},
56     {0x000a92, 0x00010066, "PreSonus", "FirePOD"},
57
58     {0x000aac, 0x00000003, "TerraTec Electronic GmbH", "Phase 88 FW"},
59     {0x000aac, 0x00000004, "TerraTec Electronic GmbH", "Phase X24 FW (model version 4)"},
60     {0x000aac, 0x00000007, "TerraTec Electronic GmbH", "Phase X24 FW (model version 7)"},
61
62     {0x000f1b, 0x00010064, "ESI", "Quatafire 610"},
63
64     {0x00130e, 0x00000000, "Focusrite", "Saffire (LE)"},
65     {0x00130e, 0x00000003, "Focusrite", "Saffire Pro26IO"},
66     {0x00130e, 0x00000006, "Focusrite", "Saffire Pro10IO"},
67
68     {0x0040ab, 0x00010048, "EDIROL", "FA-101"},
69     {0x0040ab, 0x00010049, "EDIROL", "FA-66"},
70
71     {0x000d6c, 0x00010062, "M-Audio", "FW Solo"},
72     {0x000d6c, 0x00010081, "M-Audio", "NRV10"},
73
74 };
75
76 AvDevice::AvDevice( std::auto_ptr< ConfigRom >( configRom ),
77                     Ieee1394Service& ieee1394service,
78                     int nodeId )
79     : IAvDevice( configRom, ieee1394service, nodeId )
80     , m_pPlugManager( new AvPlugManager( DEBUG_LEVEL_NORMAL ) )
81     , m_activeSyncInfo( 0 )
82     , m_model ( NULL )
83     , m_Mixer ( NULL )
84 {
85     debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::AvDevice (NodeID %d)\n",
86                  nodeId );
87     addOption(Util::OptionContainer::Option("snoopMode",false));
88 }
89
90 AvDevice::~AvDevice()
91 {
92     if(m_Mixer != NULL) {
93         if (!removeChildOscNode(m_Mixer)) {
94             debugWarning("failed to unregister mixer from OSC namespace\n");
95         }
96         delete m_Mixer;
97     }
98
99     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
100           it != m_subunits.end();
101           ++it )
102     {
103         delete *it;
104     }
105     for ( AvPlugConnectionVector::iterator it = m_plugConnections.begin();
106           it != m_plugConnections.end();
107           ++it )
108     {
109         delete *it;
110     }
111     for ( AvPlugVector::iterator it = m_pcrPlugs.begin();
112           it != m_pcrPlugs.end();
113           ++it )
114     {
115         delete *it;
116     }
117     for ( AvPlugVector::iterator it = m_externalPlugs.begin();
118           it != m_externalPlugs.end();
119           ++it )
120     {
121         delete *it;
122     }
123 }
124
125 void
126 AvDevice::setVerboseLevel(int l)
127 {
128 //     m_pPlugManager->setVerboseLevel(l);
129
130     IAvDevice::setVerboseLevel(l);
131 }
132
133 bool
134 AvDevice::probe( ConfigRom& configRom )
135 {
136     unsigned int vendorId = configRom.getNodeVendorId();
137     unsigned int modelId = configRom.getModelId();
138
139     //ConfigParser configParser( "/home/wagi/src/libffado/src/bebob/ffado_driver_bebob.txt" );
140
141     for ( unsigned int i = 0;
142           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
143           ++i )
144     {
145         if ( ( supportedDeviceList[i].vendor_id == vendorId )
146              && ( supportedDeviceList[i].model_id == modelId ) )
147         {
148             return true;
149         }
150     }
151
152     return false;
153 }
154
155 bool
156 AvDevice::discover()
157 {
158     unsigned int vendorId = m_pConfigRom->getNodeVendorId();
159     unsigned int modelId = m_pConfigRom->getModelId();
160
161     for ( unsigned int i = 0;
162           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
163           ++i )
164     {
165         if ( ( supportedDeviceList[i].vendor_id == vendorId )
166              && ( supportedDeviceList[i].model_id == modelId )
167            )
168         {
169             m_model = &(supportedDeviceList[i]);
170             break;
171         }
172     }
173
174     if (m_model != NULL) {
175         debugOutput( DEBUG_LEVEL_VERBOSE, "found %s %s\n",
176                 m_model->vendor_name, m_model->model_name);
177     } else return false;
178
179     if ( !enumerateSubUnits() ) {
180         debugError( "Could not enumarate sub units\n" );
181         return false;
182     }
183
184     if ( !discoverPlugs() ) {
185         debugError( "Detecting plugs failed\n" );
186         return false;
187     }
188
189     if ( !discoverPlugConnections() ) {
190         debugError( "Detecting plug connections failed\n" );
191         return false;
192     }
193
194     if ( !discoverSubUnitsPlugConnections() ) {
195         debugError( "Detecting plug connnection failed\n" );
196         return false;
197     }
198
199     if ( !discoverSyncModes() ) {
200         debugError( "Detecting sync modes failed\n" );
201         return false;
202     }
203
204     // create a GenericMixer and add it as an OSC child node
205     //  remove if already there
206     if(m_Mixer != NULL) {
207         if (!removeChildOscNode(m_Mixer)) {
208             debugWarning("failed to unregister mixer from OSC namespace\n");
209         }
210         delete m_Mixer;
211     }
212
213     //  create the mixer & register it
214     if(getAudioSubunit(0) == NULL) {
215         debugWarning("Could not find audio subunit, mixer not available.\n");
216         m_Mixer = NULL;
217     } else {
218         m_Mixer = new GenericMixer(*m_p1394Service , *this);
219         if (!addChildOscNode(m_Mixer)) {
220             debugWarning("failed to register mixer in OSC namespace\n");
221         }
222     }
223     return true;
224 }
225
226 bool
227 AvDevice::discoverPlugs()
228 {
229     //////////////////////////////////////////////
230     // Get number of available isochronous input
231     // and output plugs of unit
232
233     PlugInfoCmd plugInfoCmd( *m_p1394Service );
234     plugInfoCmd.setNodeId( m_pConfigRom->getNodeId() );
235     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
236     plugInfoCmd.setVerbose( m_verboseLevel );
237
238     if ( !plugInfoCmd.fire() ) {
239         debugError( "plug info command failed\n" );
240         return false;
241     }
242
243     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso input plugs = %d\n",
244                  plugInfoCmd.m_serialBusIsochronousInputPlugs );
245     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso output plugs = %d\n",
246                  plugInfoCmd.m_serialBusIsochronousOutputPlugs );
247     debugOutput( DEBUG_LEVEL_NORMAL, "number of external input plugs = %d\n",
248                  plugInfoCmd.m_externalInputPlugs );
249     debugOutput( DEBUG_LEVEL_NORMAL, "number of external output plugs = %d\n",
250                  plugInfoCmd.m_externalOutputPlugs );
251
252     if ( !discoverPlugsPCR( AvPlug::eAPD_Input,
253                             plugInfoCmd.m_serialBusIsochronousInputPlugs ) )
254     {
255         debugError( "pcr input plug discovering failed\n" );
256         return false;
257     }
258
259     if ( !discoverPlugsPCR( AvPlug::eAPD_Output,
260                             plugInfoCmd.m_serialBusIsochronousOutputPlugs ) )
261     {
262         debugError( "pcr output plug discovering failed\n" );
263         return false;
264     }
265
266     if ( !discoverPlugsExternal( AvPlug::eAPD_Input,
267                                  plugInfoCmd.m_externalInputPlugs ) )
268     {
269         debugError( "external input plug discovering failed\n" );
270         return false;
271     }
272
273     if ( !discoverPlugsExternal( AvPlug::eAPD_Output,
274                                  plugInfoCmd.m_externalOutputPlugs ) )
275     {
276         debugError( "external output plug discovering failed\n" );
277         return false;
278     }
279
280     return true;
281 }
282
283 bool
284 AvDevice::discoverPlugsPCR( AvPlug::EAvPlugDirection plugDirection,
285                             plug_id_t plugMaxId )
286 {
287     for ( int plugId = 0;
288           plugId < plugMaxId;
289           ++plugId )
290     {
291         AvPlug* plug  = new AvPlug( *m_p1394Service,
292                                     *m_pConfigRom,
293                                     *m_pPlugManager,
294                                     AVCCommand::eST_Unit,
295                                     0xff,
296                                     0xff,
297                                     0xff,
298                                     AvPlug::eAPA_PCR,
299                                     plugDirection,
300                                     plugId,
301                                     m_verboseLevel );
302         if ( !plug || !plug->discover() ) {
303             debugError( "plug discovering failed\n" );
304             delete plug;
305             return false;
306         }
307
308         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
309                      plug->getName() );
310         m_pcrPlugs.push_back( plug );
311     }
312
313     return true;
314 }
315
316 bool
317 AvDevice::discoverPlugsExternal( AvPlug::EAvPlugDirection plugDirection,
318                                  plug_id_t plugMaxId )
319 {
320     for ( int plugId = 0;
321           plugId < plugMaxId;
322           ++plugId )
323     {
324         AvPlug* plug  = new AvPlug( *m_p1394Service,
325                                     *m_pConfigRom,
326                                     *m_pPlugManager,
327                                     AVCCommand::eST_Unit,
328                                     0xff,
329                                     0xff,
330                                     0xff,
331                                     AvPlug::eAPA_ExternalPlug,
332                                     plugDirection,
333                                     plugId,
334                                     m_verboseLevel );
335         if ( !plug || !plug->discover() ) {
336             debugError( "plug discovering failed\n" );
337             return false;
338         }
339
340         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
341                      plug->getName() );
342         m_externalPlugs.push_back( plug );
343     }
344
345     return true;
346 }
347
348 bool
349 AvDevice::discoverPlugConnections()
350 {
351     for ( AvPlugVector::iterator it = m_pcrPlugs.begin();
352           it != m_pcrPlugs.end();
353           ++it )
354     {
355         AvPlug* plug = *it;
356         if ( !plug->discoverConnections() ) {
357             debugError( "Could not discover plug connections\n" );
358             return false;
359         }
360     }
361     for ( AvPlugVector::iterator it = m_externalPlugs.begin();
362           it != m_externalPlugs.end();
363           ++it )
364     {
365         AvPlug* plug = *it;
366         if ( !plug->discoverConnections() ) {
367             debugError( "Could not discover plug connections\n" );
368             return false;
369         }
370     }
371
372     return true;
373 }
374
375 bool
376 AvDevice::discoverSubUnitsPlugConnections()
377 {
378     for ( AvDeviceSubunitVector::iterator it = m_subunits.begin();
379           it != m_subunits.end();
380           ++it )
381     {
382         AvDeviceSubunit* subunit = *it;
383         if ( !subunit->discoverConnections() ) {
384             debugError( "Subunit '%s'  plug connections failed\n",
385                         subunit->getName() );
386             return false;
387         }
388     }
389     return true;
390 }
391
392 bool
393 AvDevice::discoverSyncModes()
394 {
395     // Following possible sync plugs exists:
396     // - Music subunit sync output plug = internal sync (CSP)
397     // - Unit input plug 0 = SYT match
398     // - Unit input plut 1 = Sync stream
399     //
400     // If last sync mode is reported it is mostelikely not
401     // implemented *sic*
402     //
403     // Following sync sources are device specific:
404     // - All unit external input plugs which have a
405     //   sync information (WS, SPDIF, ...)
406
407     // First we have to find the sync input and output plug
408     // in the music subunit.
409
410     // Note PCR input means 1394bus-to-device where as
411     // MSU input means subunit-to-device
412
413     AvPlugVector syncPCRInputPlugs = getPlugsByType( m_pcrPlugs,
414                                                      AvPlug::eAPD_Input,
415                                                      AvPlug::eAPT_Sync );
416     if ( !syncPCRInputPlugs.size() ) {
417         debugWarning( "No PCR sync input plug found\n" );
418     }
419
420     AvPlugVector syncPCROutputPlugs = getPlugsByType( m_pcrPlugs,
421                                                       AvPlug::eAPD_Output,
422                                                       AvPlug::eAPT_Sync );
423     if ( !syncPCROutputPlugs.size() ) {
424         debugWarning( "No PCR sync output plug found\n" );
425     }
426
427     AvPlugVector isoPCRInputPlugs = getPlugsByType( m_pcrPlugs,
428                                                     AvPlug::eAPD_Input,
429                                                     AvPlug::eAPT_IsoStream );
430     if ( !isoPCRInputPlugs.size() ) {
431         debugWarning( "No PCR iso input plug found\n" );
432
433     }
434
435     AvPlugVector isoPCROutputPlugs = getPlugsByType( m_pcrPlugs,
436                                                     AvPlug::eAPD_Output,
437                                                     AvPlug::eAPT_IsoStream );
438     if ( !isoPCROutputPlugs.size() ) {
439         debugWarning( "No PCR iso output plug found\n" );
440
441     }
442
443     AvPlugVector digitalExternalInputPlugs = getPlugsByType( m_externalPlugs,
444                                                     AvPlug::eAPD_Input,
445                                                     AvPlug::eAPT_Digital );
446     if ( !digitalExternalInputPlugs.size() ) {
447         debugOutput( DEBUG_LEVEL_VERBOSE, "No external digital input plugs found\n" );
448
449     }
450    
451     AvPlugVector syncExternalInputPlugs = getPlugsByType( m_externalPlugs,
452                                                     AvPlug::eAPD_Input,
453                                                     AvPlug::eAPT_Sync );
454     if ( !syncExternalInputPlugs.size() ) {
455         debugOutput( DEBUG_LEVEL_VERBOSE, "No external sync input plugs found\n" );
456
457     }
458
459     AvPlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
460         AVCCommand::eST_Music,
461         0,
462         0xff,
463         0xff,
464         AvPlug::eAPA_SubunitPlug,
465         AvPlug::eAPD_Input,
466         AvPlug::eAPT_Sync );
467     if ( !syncMSUInputPlugs.size() ) {
468         debugWarning( "No sync input plug for MSU subunit found\n" );
469     }
470
471     AvPlugVector syncMSUOutputPlugs = m_pPlugManager->getPlugsByType(
472         AVCCommand::eST_Music,
473         0,
474         0xff,
475         0xff,
476         AvPlug::eAPA_SubunitPlug,
477         AvPlug::eAPD_Output,
478         AvPlug::eAPT_Sync );
479     if ( !syncMSUOutputPlugs.size() ) {
480         debugWarning( "No sync output plug for MSU subunit found\n" );
481     }
482
483     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Input Plugs:\n" );
484     showAvPlugs( syncPCRInputPlugs );
485     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Output Plugs:\n" );
486     showAvPlugs( syncPCROutputPlugs );
487     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Input Plugs:\n" );
488     showAvPlugs( isoPCRInputPlugs );
489     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Output Plugs:\n" );
490     showAvPlugs( isoPCROutputPlugs );
491     debugOutput( DEBUG_LEVEL_VERBOSE, "External digital Input Plugs:\n" );
492     showAvPlugs( digitalExternalInputPlugs );
493     debugOutput( DEBUG_LEVEL_VERBOSE, "External sync Input Plugs:\n" );
494     showAvPlugs( syncExternalInputPlugs );
495     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Input Plugs:\n" );
496     showAvPlugs( syncMSUInputPlugs );
497     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Output Plugs:\n" );
498     showAvPlugs( syncMSUOutputPlugs );
499
500     // Check all possible PCR input to MSU input connections
501     // -> sync stream input
502     checkSyncConnectionsAndAddToList( syncPCRInputPlugs,
503                                       syncMSUInputPlugs,
504                                       "Sync Stream Input" );
505
506     // Check all possible MSU output to PCR output connections
507     // -> sync stream output
508     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
509                                       syncPCROutputPlugs,
510                                       "Sync Stream Output" );
511
512     // Check all PCR iso input to MSU input connections
513     // -> SYT match
514     checkSyncConnectionsAndAddToList( isoPCRInputPlugs,
515                                       syncMSUInputPlugs,
516                                       "Syt Match" );
517
518     // Check all MSU sync output to MSU input connections
519     // -> CSP
520     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
521                                       syncMSUInputPlugs,
522                                       "Internal (CSP)" );
523
524     // Check all external digital input to MSU input connections
525     // -> SPDIF/ADAT sync
526     checkSyncConnectionsAndAddToList( digitalExternalInputPlugs,
527                                       syncMSUInputPlugs,
528                                       "Digital Input Sync" );
529
530     // Check all external sync input to MSU input connections
531     // -> SPDIF/ADAT sync
532     checkSyncConnectionsAndAddToList( syncExternalInputPlugs,
533                                       syncMSUInputPlugs,
534                                       "Digital Input Sync" );
535
536     // Currently active connection signal source cmd, command type
537     // status, source unknown, destination MSU sync input plug
538
539     for ( AvPlugVector::const_iterator it = syncMSUInputPlugs.begin();
540           it != syncMSUInputPlugs.end();
541           ++it )
542     {
543         AvPlug* msuPlug = *it;
544         for ( AvPlugVector::const_iterator jt =
545                   msuPlug->getInputConnections().begin();
546               jt != msuPlug->getInputConnections().end();
547               ++jt )
548         {
549             AvPlug* plug = *jt;
550
551             for ( SyncInfoVector::iterator it = m_syncInfos.begin();
552                   it != m_syncInfos.end();
553                   ++it )
554             {
555                 SyncInfo* pSyncInfo = &*it;
556                 if ( ( pSyncInfo->m_source == plug )
557                      && ( pSyncInfo->m_destination == msuPlug ) )
558                 {
559                     m_activeSyncInfo = pSyncInfo;
560                     break;
561                 }
562             }
563             debugOutput( DEBUG_LEVEL_NORMAL,
564                          "Active Sync Connection: '%s' -> '%s'\n",
565                          plug->getName(),
566                          msuPlug->getName() );
567         }
568     }
569
570     return true;
571 }
572
573 bool
574 AvDevice::enumerateSubUnits()
575 {
576     bool musicSubunitFound=false;
577     bool audioSubunitFound=false;
578
579     SubUnitInfoCmd subUnitInfoCmd( *m_p1394Service );
580     //subUnitInfoCmd.setVerbose( 1 );
581     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
582
583     // BeBoB has always exactly one audio and one music subunit. This
584     // means is fits into the first page of the SubUnitInfo command.
585     // So there is no need to do more than needed
586
587     subUnitInfoCmd.m_page = 0;
588     subUnitInfoCmd.setNodeId( m_pConfigRom->getNodeId() );
589     subUnitInfoCmd.setVerbose( m_verboseLevel );
590     if ( !subUnitInfoCmd.fire() ) {
591         debugError( "Subunit info command failed\n" );
592         // shouldn't this be an error situation?
593         return false;
594     }
595
596     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
597         subunit_type_t subunit_type
598             = subUnitInfoCmd.m_table[i].m_subunit_type;
599
600         unsigned int subunitId = getNrOfSubunits( subunit_type );
601
602         debugOutput( DEBUG_LEVEL_VERBOSE,
603                      "subunit_id = %2d, subunit_type = %2d (%s)\n",
604                      subunitId,
605                      subunit_type,
606                      subunitTypeToString( subunit_type ) );
607
608         AvDeviceSubunit* subunit = 0;
609         switch( subunit_type ) {
610         case AVCCommand::eST_Audio:
611             subunit = new AvDeviceSubunitAudio( *this,
612                                                 subunitId,
613                                                 m_verboseLevel );
614             if ( !subunit ) {
615                 debugFatal( "Could not allocate AvDeviceSubunitAudio\n" );
616                 return false;
617             }
618
619             m_subunits.push_back( subunit );
620             audioSubunitFound=true;
621
622             break;
623         case AVCCommand::eST_Music:
624             subunit = new AvDeviceSubunitMusic( *this,
625                                                 subunitId,
626                                                 m_verboseLevel );
627             if ( !subunit ) {
628                 debugFatal( "Could not allocate AvDeviceSubunitMusic\n" );
629                 return false;
630             }
631
632             m_subunits.push_back( subunit );
633             musicSubunitFound=true;
634
635             break;
636         default:
637             debugOutput( DEBUG_LEVEL_NORMAL,
638                          "Unsupported subunit found, subunit_type = %d (%s)\n",
639                          subunit_type,
640                          subunitTypeToString( subunit_type ) );
641             continue;
642
643         }
644
645         if ( !subunit->discover() ) {
646             debugError( "enumerateSubUnits: Could not discover "
647                         "subunit_id = %2d, subunit_type = %2d (%s)\n",
648                         subunitId,
649                         subunit_type,
650                         subunitTypeToString( subunit_type ) );
651             delete subunit;
652             return false;
653         }
654
655     }
656
657     // a BeBoB always has an audio and a music subunit
658     return (musicSubunitFound && audioSubunitFound);
659 }
660
661
662 AvDeviceSubunit*
663 AvDevice::getSubunit( subunit_type_t subunitType,
664                       subunit_id_t subunitId ) const
665 {
666     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
667           it != m_subunits.end();
668           ++it )
669     {
670         AvDeviceSubunit* subunit = *it;
671         if ( ( subunitType == subunit->getSubunitType() )
672              && ( subunitId == subunit->getSubunitId() ) )
673         {
674             return subunit;
675         }
676     }
677
678     return 0;
679 }
680
681
682 unsigned int
683 AvDevice::getNrOfSubunits( subunit_type_t subunitType ) const
684 {
685     unsigned int nrOfSubunits = 0;
686
687     for ( AvDeviceSubunitVector::const_iterator it = m_subunits.begin();
688           it != m_subunits.end();
689           ++it )
690     {
691         AvDeviceSubunit* subunit = *it;
692         if ( subunitType == subunit->getSubunitType() ) {
693             nrOfSubunits++;
694         }
695     }
696
697     return nrOfSubunits;
698 }
699
700 AvPlugConnection*
701 AvDevice::getPlugConnection( AvPlug& srcPlug ) const
702 {
703     for ( AvPlugConnectionVector::const_iterator it
704               = m_plugConnections.begin();
705           it != m_plugConnections.end();
706           ++it )
707     {
708         AvPlugConnection* plugConnection = *it;
709         if ( &( plugConnection->getSrcPlug() ) == &srcPlug ) {
710             return plugConnection;
711         }
712     }
713
714     return 0;
715 }
716
717 AvPlug*
718 AvDevice::getPlugById( AvPlugVector& plugs,
719                        AvPlug::EAvPlugDirection plugDirection,
720                        int id )
721 {
722     for ( AvPlugVector::iterator it = plugs.begin();
723           it != plugs.end();
724           ++it )
725     {
726         AvPlug* plug = *it;
727         if ( ( id == plug->getPlugId() )
728              && ( plugDirection == plug->getPlugDirection() ) )
729         {
730             return plug;
731         }
732     }
733
734     return 0;
735 }
736
737 AvPlugVector
738 AvDevice::getPlugsByType( AvPlugVector& plugs,
739                           AvPlug::EAvPlugDirection plugDirection,
740                           AvPlug::EAvPlugType type)
741 {
742     AvPlugVector plugVector;
743     for ( AvPlugVector::iterator it = plugs.begin();
744           it != plugs.end();
745           ++it )
746     {
747         AvPlug* plug = *it;
748         if ( ( type == plug->getPlugType() )
749              && ( plugDirection == plug->getPlugDirection() ) )
750         {
751             plugVector.push_back( plug );
752         }
753     }
754
755     return plugVector;
756 }
757
758 AvPlug*
759 AvDevice::getSyncPlug( int maxPlugId, AvPlug::EAvPlugDirection )
760 {
761     return 0;
762 }
763
764 bool
765 AvDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
766 {
767     bool snoopMode=false;
768     if(!getOption("snoopMode", snoopMode)) {
769         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
770     }
771
772     if(snoopMode) {
773         int current_sr=getSamplingFrequency();
774         if (current_sr != convertESamplingFrequency( samplingFrequency ) ) {
775             debugError("In snoop mode it is impossible to set the sample rate.\n");
776             debugError("Please start the client with the correct setting.\n");
777             return false;
778         }
779         return true;
780     } else {
781         AvPlug* plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
782         if ( !plug ) {
783             debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
784             return false;
785         }
786
787         if ( !setSamplingFrequencyPlug( *plug,
788                                         AvPlug::eAPD_Input,
789                                         samplingFrequency ) )
790         {
791             debugError( "setSampleRate: Setting sample rate failed\n" );
792             return false;
793         }
794
795         plug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output,  0 );
796         if ( !plug ) {
797             debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
798             return false;
799         }
800
801         if ( !setSamplingFrequencyPlug( *plug,
802                                         AvPlug::eAPD_Output,
803                                         samplingFrequency ) )
804         {
805             debugError( "setSampleRate: Setting sample rate failed\n" );
806             return false;
807         }
808
809         debugOutput( DEBUG_LEVEL_VERBOSE,
810                      "setSampleRate: Set sample rate to %d\n",
811                      convertESamplingFrequency( samplingFrequency ) );
812         return true;
813     }
814     // not executable
815     return false;
816 }
817
818 int
819 AvDevice::getSamplingFrequency( )
820 {
821     AvPlug* inputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
822     if ( !inputPlug ) {
823         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
824         return false;
825     }
826     AvPlug* outputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 );
827     if ( !outputPlug ) {
828         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
829         return false;
830     }
831
832     int samplerate_playback=inputPlug->getSampleRate();
833     int samplerate_capture=outputPlug->getSampleRate();
834
835     if (samplerate_playback != samplerate_capture) {
836         debugWarning("Samplerates for capture and playback differ!\n");
837     }
838     return samplerate_capture;
839 }
840
841 int
842 AvDevice::getConfigurationIdSampleRate()
843 {
844     ExtendedStreamFormatCmd extStreamFormatCmd( *m_p1394Service );
845     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
846                                      m_nodeId );
847     extStreamFormatCmd.setPlugAddress( PlugAddress( PlugAddress::ePD_Input,
848                                                     PlugAddress::ePAM_Unit,
849                                                     unitPlugAddress ) );
850
851     extStreamFormatCmd.setNodeId( m_nodeId );
852     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
853     extStreamFormatCmd.setVerbose( true );
854
855     if ( !extStreamFormatCmd.fire() ) {
856         debugError( "Stream format command failed\n" );
857         return false;
858     }
859
860     FormatInformation* formatInfo =
861         extStreamFormatCmd.getFormatInformation();
862     FormatInformationStreamsCompound* compoundStream
863         = dynamic_cast< FormatInformationStreamsCompound* > (
864             formatInfo->m_streams );
865     if ( compoundStream ) {
866         debugOutput(DEBUG_LEVEL_VERBOSE, "Sample rate 0x%02x\n",
867                     compoundStream->m_samplingFrequency );
868         return compoundStream->m_samplingFrequency;
869     }
870
871     debugError( "Could not retrieve sample rate\n" );
872     return 0;
873 }
874
875 int
876 AvDevice::getConfigurationIdNumberOfChannel( PlugAddress::EPlugDirection ePlugDirection )
877 {
878     ExtendedPlugInfoCmd extPlugInfoCmd( *m_p1394Service );
879     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
880                                      m_nodeId );
881     extPlugInfoCmd.setPlugAddress( PlugAddress( ePlugDirection,
882                                                 PlugAddress::ePAM_Unit,
883                                                 unitPlugAddress ) );
884     extPlugInfoCmd.setNodeId( m_nodeId );
885     extPlugInfoCmd.setCommandType( AVCCommand::eCT_Status );
886     extPlugInfoCmd.setVerbose( true );
887     ExtendedPlugInfoInfoType extendedPlugInfoInfoType(
888         ExtendedPlugInfoInfoType::eIT_NoOfChannels );
889     extendedPlugInfoInfoType.initialize();
890     extPlugInfoCmd.setInfoType( extendedPlugInfoInfoType );
891
892     if ( !extPlugInfoCmd.fire() ) {
893         debugError( "Number of channels command failed\n" );
894         return false;
895     }
896
897     ExtendedPlugInfoInfoType* infoType = extPlugInfoCmd.getInfoType();
898     if ( infoType
899          && infoType->m_plugNrOfChns )
900     {
901         debugOutput(DEBUG_LEVEL_VERBOSE, "Number of channels 0x%02x\n",
902                     infoType->m_plugNrOfChns->m_nrOfChannels );
903         return infoType->m_plugNrOfChns->m_nrOfChannels;
904     }
905
906     debugError( "Could not retrieve number of channels\n" );
907     return 0;
908 }
909
910 int
911 AvDevice::getConfigurationIdSyncMode()
912 {
913     SignalSourceCmd signalSourceCmd( *m_p1394Service );
914     SignalUnitAddress signalUnitAddr;
915     signalUnitAddr.m_plugId = 0x01;
916     signalSourceCmd.setSignalDestination( signalUnitAddr );
917     signalSourceCmd.setNodeId( m_nodeId );
918     signalSourceCmd.setSubunitType( AVCCommand::eST_Unit  );
919     signalSourceCmd.setSubunitId( 0xff );
920
921     signalSourceCmd.setCommandType( AVCCommand::eCT_Status );
922
923     if ( !signalSourceCmd.fire() ) {
924         debugError( "Number of channels command failed\n" );
925         return false;
926     }
927
928     SignalAddress* pSyncPlugSignalAddress = signalSourceCmd.getSignalSource();
929     SignalSubunitAddress* pSyncPlugSubunitAddress
930         = dynamic_cast<SignalSubunitAddress*>( pSyncPlugSignalAddress );
931     if ( pSyncPlugSubunitAddress ) {
932         debugOutput(DEBUG_LEVEL_VERBOSE, "Sync mode 0x%02x\n",
933                     ( pSyncPlugSubunitAddress->m_subunitType << 3
934                       | pSyncPlugSubunitAddress->m_subunitId ) << 8
935                     | pSyncPlugSubunitAddress->m_plugId );
936
937         return ( pSyncPlugSubunitAddress->m_subunitType << 3
938                  | pSyncPlugSubunitAddress->m_subunitId ) << 8
939             | pSyncPlugSubunitAddress->m_plugId;
940     }
941
942     debugError( "Could not retrieve sync mode\n" );
943     return 0;
944 }
945
946 int
947 AvDevice::getConfigurationId()
948 {
949     // create a unique configuration id.
950     int id = 0;
951     id = getConfigurationIdSampleRate();
952     id |= ( getConfigurationIdNumberOfChannel( PlugAddress::ePD_Input )
953             + getConfigurationIdNumberOfChannel( PlugAddress::ePD_Output ) ) << 8;
954     id |= getConfigurationIdSyncMode() << 16;
955
956     return id;
957 }
958
959 bool
960 AvDevice::setSamplingFrequencyPlug( AvPlug& plug,
961                                     AvPlug::EAvPlugDirection direction,
962                                     ESamplingFrequency samplingFrequency )
963 {
964
965     ExtendedStreamFormatCmd extStreamFormatCmd(
966         *m_p1394Service,
967         ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommandList );
968     UnitPlugAddress unitPlugAddress( UnitPlugAddress::ePT_PCR,
969                                      plug.getPlugId() );
970
971     extStreamFormatCmd.setPlugAddress(
972         PlugAddress(
973             AvPlug::convertPlugDirection(direction ),
974             PlugAddress::ePAM_Unit,
975             unitPlugAddress ) );
976
977     extStreamFormatCmd.setNodeId( m_pConfigRom->getNodeId() );
978     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
979
980     int i = 0;
981     bool cmdSuccess = false;
982     bool correctFormatFound = false;
983
984     do {
985         extStreamFormatCmd.setIndexInStreamFormat( i );
986         extStreamFormatCmd.setCommandType( AVCCommand::eCT_Status );
987         extStreamFormatCmd.setVerbose( m_verboseLevel );
988
989         cmdSuccess = extStreamFormatCmd.fire();
990
991         if ( cmdSuccess
992              && ( extStreamFormatCmd.getResponse() ==
993                   AVCCommand::eR_Implemented ) )
994         {
995             ESamplingFrequency foundFreq = eSF_DontCare;
996
997             FormatInformation* formatInfo =
998                 extStreamFormatCmd.getFormatInformation();
999             FormatInformationStreamsCompound* compoundStream
1000                 = dynamic_cast< FormatInformationStreamsCompound* > (
1001                     formatInfo->m_streams );
1002             if ( compoundStream ) {
1003                 foundFreq =
1004                     static_cast< ESamplingFrequency >(
1005                         compoundStream->m_samplingFrequency );
1006             }
1007
1008             FormatInformationStreamsSync* syncStream
1009                 = dynamic_cast< FormatInformationStreamsSync* > (
1010                     formatInfo->m_streams );
1011             if ( syncStream ) {
1012                 foundFreq =
1013                     static_cast< ESamplingFrequency >(
1014                         syncStream->m_samplingFrequency );
1015             }
1016
1017             if ( foundFreq == samplingFrequency )
1018             {
1019                 correctFormatFound = true;
1020                 break;
1021             }
1022         }
1023
1024         ++i;
1025     } while ( cmdSuccess
1026               && ( extStreamFormatCmd.getResponse() ==
1027                    ExtendedStreamFormatCmd::eR_Implemented ) );
1028
1029     if ( !cmdSuccess ) {
1030         debugError( "setSampleRatePlug: Failed to retrieve format info\n" );
1031         return false;
1032     }
1033
1034     if ( !correctFormatFound ) {
1035         debugError( "setSampleRatePlug: %s plug %d does not support "
1036                     "sample rate %d\n",
1037                     plug.getName(),
1038                     plug.getPlugId(),
1039                     convertESamplingFrequency( samplingFrequency ) );
1040         return false;
1041     }
1042
1043     extStreamFormatCmd.setSubFunction(
1044         ExtendedStreamFormatCmd::eSF_ExtendedStreamFormatInformationCommand );
1045     extStreamFormatCmd.setCommandType( AVCCommand::eCT_Control );
1046     extStreamFormatCmd.setVerbose( m_verboseLevel );
1047
1048     if ( !extStreamFormatCmd.fire() ) {
1049         debugError( "setSampleRate: Could not set sample rate %d "
1050                     "to %s plug %d\n",
1051                     convertESamplingFrequency( samplingFrequency ),
1052                     plug.getName(),
1053                     plug.getPlugId() );
1054         return false;
1055     }
1056
1057     return true;
1058 }
1059
1060 void
1061 AvDevice::showDevice()
1062 {
1063     debugOutput(DEBUG_LEVEL_VERBOSE,
1064         "%s %s at node %d\n", m_model->vendor_name, m_model->model_name,
1065         m_nodeId);
1066
1067     m_pPlugManager->showPlugs();
1068 }
1069
1070 void
1071 AvDevice::showAvPlugs( AvPlugVector& plugs ) const
1072 {
1073     int i = 0;
1074     for ( AvPlugVector::const_iterator it = plugs.begin();
1075           it != plugs.end();
1076           ++it, ++i )
1077     {
1078         AvPlug* plug = *it;
1079         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d\n", i );
1080         plug->showPlug();
1081     }
1082 }
1083
1084 bool
1085 AvDevice::checkSyncConnectionsAndAddToList( AvPlugVector& plhs,
1086                                             AvPlugVector& prhs,
1087                                             std::string syncDescription )
1088 {
1089     for ( AvPlugVector::iterator plIt = plhs.begin();
1090           plIt != plhs.end();
1091           ++plIt )
1092     {
1093         AvPlug* pl = *plIt;
1094         for ( AvPlugVector::iterator prIt = prhs.begin();
1095               prIt != prhs.end();
1096               ++prIt )
1097         {
1098             AvPlug* pr = *prIt;
1099             if ( pl->inquireConnnection( *pr ) ) {
1100                 m_syncInfos.push_back( SyncInfo( *pl, *pr, syncDescription ) );
1101                 debugOutput( DEBUG_LEVEL_NORMAL,
1102                              "Sync connection '%s' -> '%s'\n",
1103                              pl->getName(),
1104                              pr->getName() );
1105             }
1106         }
1107     }
1108     return true;
1109 }
1110
1111 bool AvDevice::setActiveSync(const SyncInfo& syncInfo)
1112 {
1113     return syncInfo.m_source->setConnection( *syncInfo.m_destination );
1114 }
1115
1116 bool
1117 AvDevice::lock() {
1118     bool snoopMode=false;
1119     if(!getOption("snoopMode", snoopMode)) {
1120         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
1121     }
1122
1123     if (snoopMode) {
1124         // don't lock
1125     } else {
1126
1127     }
1128
1129     return true;
1130 }
1131
1132 bool
1133 AvDevice::unlock() {
1134     bool snoopMode=false;
1135     if(!getOption("snoopMode", snoopMode)) {
1136         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
1137     }
1138
1139     if (snoopMode) {
1140         // don't unlock
1141     } else {
1142
1143     }
1144     return true;
1145 }
1146
1147 bool
1148 AvDevice::prepare() {
1149     bool snoopMode=false;
1150     if(!getOption("snoopMode", snoopMode)) {
1151         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
1152     }
1153
1154     ///////////
1155     // get plugs
1156
1157     AvPlug* inputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
1158     if ( !inputPlug ) {
1159         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
1160         return false;
1161     }
1162     AvPlug* outputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 );
1163     if ( !outputPlug ) {
1164         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
1165         return false;
1166     }
1167
1168     int samplerate=outputPlug->getSampleRate();
1169
1170     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing receive processor...\n");
1171     // create & add streamprocessors
1172     Streaming::StreamProcessor *p;
1173
1174     p=new Streaming::AmdtpReceiveStreamProcessor(
1175                              m_p1394Service->getPort(),
1176                              samplerate,
1177                              outputPlug->getNrOfChannels());
1178
1179     if(!p->init()) {
1180         debugFatal("Could not initialize receive processor!\n");
1181         delete p;
1182         return false;
1183     }
1184    
1185     if (!addPlugToProcessor(*outputPlug,p,
1186         Streaming::Port::E_Capture)) {
1187         debugFatal("Could not add plug to processor!\n");
1188         delete p;
1189         return false;
1190     }
1191
1192     m_receiveProcessors.push_back(p);
1193
1194     // do the transmit processor
1195     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing transmit processor%s...\n",
1196             (snoopMode?" in snoop mode":""));
1197     if (snoopMode) {
1198         // we are snooping, so this is receive too.
1199         p=new Streaming::AmdtpReceiveStreamProcessor(
1200                                   m_p1394Service->getPort(),
1201                                   samplerate,
1202                                   inputPlug->getNrOfChannels());
1203     } else {
1204         p=new Streaming::AmdtpTransmitStreamProcessor(
1205                                 m_p1394Service->getPort(),
1206                                 samplerate,
1207                                 inputPlug->getNrOfChannels());
1208     }
1209
1210     if(!p->init()) {
1211         debugFatal("Could not initialize transmit processor %s!\n",
1212             (snoopMode?" in snoop mode":""));
1213         delete p;
1214         return false;
1215     }
1216
1217     if (snoopMode) {
1218         if (!addPlugToProcessor(*inputPlug,p,
1219             Streaming::Port::E_Capture)) {
1220             debugFatal("Could not add plug to processor!\n");
1221             return false;
1222         }
1223     } else {
1224         if (!addPlugToProcessor(*inputPlug,p,
1225             Streaming::Port::E_Playback)) {
1226             debugFatal("Could not add plug to processor!\n");
1227             return false;
1228         }
1229     }
1230
1231     // we put this SP into the transmit SP vector,
1232     // no matter if we are in snoop mode or not
1233     // this allows us to find out what direction
1234     // a certain stream should have.
1235     m_transmitProcessors.push_back(p);
1236
1237     return true;
1238 }
1239
1240 bool
1241 AvDevice::addPlugToProcessor(
1242     AvPlug& plug,
1243     Streaming::StreamProcessor *processor,
1244     Streaming::AmdtpAudioPort::E_Direction direction) {
1245
1246     std::string id=std::string("dev?");
1247     if(!getOption("id", id)) {
1248         debugWarning("Could not retrieve id parameter, defauling to 'dev?'\n");
1249     }
1250
1251     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
1252     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
1253           it != clusterInfos.end();
1254           ++it )
1255     {
1256         const AvPlug::ClusterInfo* clusterInfo = &( *it );
1257
1258         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
1259         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
1260               it != channelInfos.end();
1261               ++it )
1262         {
1263             const AvPlug::ChannelInfo* channelInfo = &( *it );
1264             std::ostringstream portname;
1265
1266             portname << id << "_" << channelInfo->m_name;
1267
1268             Streaming::Port *p=NULL;
1269             switch(clusterInfo->m_portType) {
1270             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
1271             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
1272             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
1273             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
1274             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
1275                 p=new Streaming::AmdtpAudioPort(
1276                         portname.str(),
1277                         direction,
1278                         // \todo: streaming backend expects indexing starting from 0
1279                         // but bebob reports it starting from 1. Decide where
1280                         // and how to handle this (pp: here)
1281                         channelInfo->m_streamPosition - 1,
1282                         channelInfo->m_location - 1,
1283                         Streaming::AmdtpPortInfo::E_MBLA
1284                 );
1285                 break;
1286
1287             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
1288                 p=new Streaming::AmdtpMidiPort(
1289                         portname.str(),
1290                         direction,
1291                         // \todo: streaming backend expects indexing starting from 0
1292                         // but bebob reports it starting from 1. Decide where
1293                         // and how to handle this (pp: here)
1294                         channelInfo->m_streamPosition - 1,
1295                         channelInfo->m_location - 1,
1296                         Streaming::AmdtpPortInfo::E_Midi
1297                 );
1298
1299                 break;
1300             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
1301             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
1302             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
1303             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
1304             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
1305                 p=new Streaming::AmdtpAudioPort(
1306                         portname.str(),
1307                         direction,
1308                         // \todo: streaming backend expects indexing starting from 0
1309                         // but bebob reports it starting from 1. Decide where
1310                         // and how to handle this (pp: here)
1311                         channelInfo->m_streamPosition - 1,
1312                         channelInfo->m_location - 1,
1313                         Streaming::AmdtpPortInfo::E_MBLA
1314                 );
1315                 break;
1316             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
1317             default:
1318             // unsupported
1319                 break;
1320             }
1321
1322             if (!p) {
1323                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
1324             } else {
1325
1326                 if (!processor->addPort(p)) {
1327                     debugWarning("Could not register port with stream processor\n");
1328                     return false;
1329                 }
1330             }
1331          }
1332     }
1333     return true;
1334 }
1335
1336 int
1337 AvDevice::getStreamCount() {
1338     return m_receiveProcessors.size() + m_transmitProcessors.size();
1339 }
1340
1341 Streaming::StreamProcessor *
1342 AvDevice::getStreamProcessorByIndex(int i) {
1343
1344     if (i<(int)m_receiveProcessors.size()) {
1345         return m_receiveProcessors.at(i);
1346     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1347         return m_transmitProcessors.at(i-m_receiveProcessors.size());
1348     }
1349
1350     return NULL;
1351 }
1352
1353 bool
1354 AvDevice::startStreamByIndex(int i) {
1355     int iso_channel=-1;
1356     bool snoopMode=false;
1357     if(!getOption("snoopMode", snoopMode)) {
1358         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
1359     }
1360
1361     if (i<(int)m_receiveProcessors.size()) {
1362         int n=i;
1363         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1364
1365         if(snoopMode) { // a stream from the device to another host
1366             // FIXME: put this into a decent framework!
1367             // we should check the oPCR[n] on the device
1368             struct iec61883_oPCR opcr;
1369             if (iec61883_get_oPCRX(
1370                     m_p1394Service->getHandle(),
1371                     m_pConfigRom->getNodeId() | 0xffc0,
1372                     (quadlet_t *)&opcr,
1373                     n)) {
1374
1375                 debugWarning("Error getting the channel for SP %d\n",i);
1376                 return false;
1377             }
1378
1379             iso_channel=opcr.channel;
1380         } else {
1381             iso_channel=m_p1394Service->allocateIsoChannelCMP(
1382                 m_pConfigRom->getNodeId() | 0xffc0, n,
1383                 m_p1394Service->getLocalNodeId()| 0xffc0, -1);
1384         }
1385         if (iso_channel<0) {
1386             debugError("Could not allocate ISO channel for SP %d\n",i);
1387             return false;
1388         }
1389
1390         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
1391
1392         p->setChannel(iso_channel);
1393         return true;
1394
1395     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1396         int n=i-m_receiveProcessors.size();
1397         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1398
1399         if(snoopMode) { // a stream from another host to the device
1400             // FIXME: put this into a decent framework!
1401             // we should check the iPCR[n] on the device
1402             struct iec61883_iPCR ipcr;
1403             if (iec61883_get_iPCRX(
1404                     m_p1394Service->getHandle(),
1405                     m_pConfigRom->getNodeId() | 0xffc0,
1406                     (quadlet_t *)&ipcr,
1407                     n)) {
1408
1409                 debugWarning("Error getting the channel for SP %d\n",i);
1410                 return false;
1411             }
1412
1413             iso_channel=ipcr.channel;
1414
1415         } else {
1416             iso_channel=m_p1394Service->allocateIsoChannelCMP(
1417                 m_p1394Service->getLocalNodeId()| 0xffc0, -1,
1418                 m_pConfigRom->getNodeId() | 0xffc0, n);
1419         }
1420
1421         if (iso_channel<0) {
1422             debugError("Could not allocate ISO channel for SP %d\n",i);
1423             return false;
1424         }
1425
1426         debugOutput(DEBUG_LEVEL_VERBOSE, "Started SP %d on channel %d\n",i,iso_channel);
1427
1428         p->setChannel(iso_channel);
1429         return true;
1430     }
1431
1432     debugError("SP index %d out of range!\n",i);
1433     return false;
1434 }
1435
1436 bool
1437 AvDevice::stopStreamByIndex(int i) {
1438     bool snoopMode=false;
1439     if(!getOption("snoopMode", snoopMode)) {
1440         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
1441     }
1442
1443     if (i<(int)m_receiveProcessors.size()) {
1444         int n=i;
1445         Streaming::StreamProcessor *p=m_receiveProcessors.at(n);
1446
1447         if(snoopMode) {
1448
1449         } else {
1450             // deallocate ISO channel
1451             if(!m_p1394Service->freeIsoChannel(p->getChannel())) {
1452                 debugError("Could not deallocate iso channel for SP %d\n",i);
1453                 return false;
1454             }
1455         }
1456         p->setChannel(-1);
1457
1458         return true;
1459
1460     } else if (i<(int)m_receiveProcessors.size() + (int)m_transmitProcessors.size()) {
1461         int n=i-m_receiveProcessors.size();
1462         Streaming::StreamProcessor *p=m_transmitProcessors.at(n);
1463
1464         if(snoopMode) {
1465
1466         } else {
1467             // deallocate ISO channel
1468             if(!m_p1394Service->freeIsoChannel(p->getChannel())) {
1469                 debugError("Could not deallocate iso channel for SP %d\n",i);
1470                 return false;
1471             }
1472         }
1473         p->setChannel(-1);
1474
1475         return true;
1476     }
1477
1478     debugError("SP index %d out of range!\n",i);
1479     return false;
1480 }
1481
1482 template <typename T> bool serializeVector( Glib::ustring path,
1483                                             Util::IOSerialize& ser,
1484                                             const T& vec )
1485 {
1486     bool result = true; // if vec.size() == 0
1487     int i = 0;
1488     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
1489         std::ostringstream strstrm;
1490         strstrm << path << i;
1491         result &= ( *it )->serialize( strstrm.str() + "/", ser );
1492         i++;
1493     }
1494     return result;
1495 }
1496
1497 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
1498                                                            Util::IODeserialize& deser,
1499                                                            AvDevice& avDevice,
1500                                                            VT& vec )
1501 {
1502     int i = 0;
1503     bool bFinished = false;
1504     do {
1505         std::ostringstream strstrm;
1506         strstrm << path << i << "/";
1507         T* ptr = T::deserialize( strstrm.str(),
1508                                  deser,
1509                                  avDevice );
1510         if ( ptr ) {
1511             vec.push_back( ptr );
1512             i++;
1513         } else {
1514             bFinished = true;
1515         }
1516     } while ( !bFinished );
1517
1518     return true;
1519 }
1520
1521 bool
1522 AvDevice::serializeSyncInfoVector( Glib::ustring basePath,
1523                                    Util::IOSerialize& ser,
1524                                    const SyncInfoVector& vec ) const
1525 {
1526     bool result = true;
1527     int i = 0;
1528
1529     for ( SyncInfoVector::const_iterator it = vec.begin();
1530           it != vec.end();
1531           ++it )
1532     {
1533         const SyncInfo& info = *it;
1534
1535         std::ostringstream strstrm;
1536         strstrm << basePath << i << "/";
1537
1538         result &= ser.write( strstrm.str() + "m_source", info.m_source->getGlobalId() );
1539         result &= ser.write( strstrm.str() + "m_destination", info.m_destination->getGlobalId() );
1540         result &= ser.write( strstrm.str() + "m_description", Glib::ustring( info.m_description ) );
1541
1542         i++;
1543     }
1544
1545     return result;
1546 }
1547
1548 bool
1549 AvDevice::deserializeSyncInfoVector( Glib::ustring basePath,
1550                                      Util::IODeserialize& deser,
1551                                      SyncInfoVector& vec )
1552 {
1553     int i = 0;
1554     bool bFinished = false;
1555     do {
1556         bool result;
1557         std::ostringstream strstrm;
1558         strstrm << basePath << i << "/";
1559
1560         plug_id_t sourceId;
1561         plug_id_t destinationId;
1562         Glib::ustring description;
1563
1564         if ( deser.isExisting( strstrm.str() + "m_source" ) ) {
1565             result  = deser.read( strstrm.str() + "m_source", sourceId );
1566             result &= deser.read( strstrm.str() + "m_destination", destinationId );
1567             result &= deser.read( strstrm.str() + "m_description", description );
1568         } else {
1569             result = false;
1570         }
1571
1572         if ( result ) {
1573             SyncInfo syncInfo;
1574             syncInfo.m_source = m_pPlugManager->getPlug( sourceId );
1575             syncInfo.m_destination = m_pPlugManager->getPlug( destinationId );
1576             syncInfo.m_description = description;
1577
1578             vec.push_back( syncInfo );
1579             i++;
1580         } else {
1581             bFinished = true;
1582         }
1583     } while ( !bFinished );
1584
1585     return true;
1586 }
1587
1588 static bool
1589 deserializeAvPlugUpdateConnections( Glib::ustring path,
1590                                     Util::IODeserialize& deser,
1591                                     AvPlugVector& vec )
1592 {
1593     bool result = true;
1594     for ( AvPlugVector::iterator it = vec.begin();
1595           it != vec.end();
1596           ++it )
1597     {
1598         AvPlug* pPlug = *it;
1599         result &= pPlug->deserializeUpdate( path, deser );
1600     }
1601     return result;
1602 }
1603
1604 bool
1605 AvDevice::serialize( Glib::ustring basePath,
1606                      Util::IOSerialize& ser ) const
1607 {
1608
1609     bool result;
1610     result  = m_pConfigRom->serialize( basePath + "m_pConfigRom/", ser );
1611     result &= ser.write( basePath + "m_verboseLevel", m_verboseLevel );
1612     result &= m_pPlugManager->serialize( basePath + "AvPlug", ser ); // serialize all av plugs
1613     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
1614     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
1615     result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
1616
1617     int i = 0;
1618     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
1619           it != m_syncInfos.end();
1620           ++it )
1621     {
1622         const SyncInfo& info = *it;
1623         if ( m_activeSyncInfo == &info ) {
1624             result &= ser.write( basePath + "m_activeSyncInfo",  i );
1625             break;
1626         }
1627         i++;
1628     }
1629
1630     result &= serializeOptions( basePath + "Options", ser );
1631
1632     // result &= ser.write( basePath + "m_id", id );
1633
1634     return result;
1635 }
1636
1637 bool
1638 AvDevice::deserialize( Glib::ustring basePath,
1639                        Util::IODeserialize& deser )
1640 {
1641     bool result;
1642     result  = deser.read( basePath + "m_verboseLevel", m_verboseLevel );
1643
1644     delete m_pPlugManager;
1645     m_pPlugManager = AvPlugManager::deserialize( basePath + "AvPlug", deser, *this );
1646     if ( !m_pPlugManager ) {
1647         return false;
1648     }
1649     result &= deserializeAvPlugUpdateConnections( basePath + "AvPlug", deser, m_pcrPlugs );
1650     result &= deserializeAvPlugUpdateConnections( basePath + "AvPlug", deser, m_externalPlugs );
1651     result &= deserializeVector<AvPlugConnection>( basePath + "PlugConnnection", deser, *this, m_plugConnections );
1652     result &= deserializeVector<AvDeviceSubunit>( basePath + "Subunit",  deser, *this, m_subunits );
1653     result &= deserializeSyncInfoVector( basePath + "SyncInfo", deser, m_syncInfos );
1654
1655     unsigned int i;
1656     result &= deser.read( basePath + "m_activeSyncInfo", i );
1657
1658     if ( result ) {
1659         if ( i < m_syncInfos.size() ) {
1660             m_activeSyncInfo = &m_syncInfos[i];
1661         }
1662     }
1663
1664     result &= deserializeOptions( basePath + "Options", deser, *this );
1665
1666     return result;
1667 }
1668
1669
1670 Glib::ustring
1671 AvDevice::getCachePath()
1672 {
1673     Glib::ustring cachePath;
1674     char* pCachePath;
1675     if ( asprintf( &pCachePath, "%s/cache/libffado/",  CACHEDIR ) < 0 ) {
1676         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
1677         cachePath == "/var/cache/libffado/";
1678     } else {
1679         cachePath = pCachePath;
1680         free( pCachePath );
1681     }
1682     return cachePath;
1683 }
1684
1685 bool
1686 AvDevice::loadFromCache()
1687 {
1688     Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
1689
1690     char* configId;
1691     asprintf(&configId, "%08x", getConfigurationId() );
1692     if ( !configId ) {
1693         debugError( "could not create id string\n" );
1694         return false;
1695     }
1696
1697     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
1698     free( configId );
1699     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
1700
1701     Util::XMLDeserialize deser( sFileName, m_verboseLevel );
1702
1703     bool result = deserialize( "", deser );
1704     if ( result ) {
1705         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n",
1706                      sFileName.c_str() );
1707     }
1708
1709     return result;
1710 }
1711
1712 bool
1713 AvDevice::saveCache()
1714 {
1715     // the path looks like this:
1716     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
1717
1718     Glib::ustring sDevicePath = getCachePath() + m_pConfigRom->getGuidString();
1719     struct stat buf;
1720     if ( stat( sDevicePath.c_str(), &buf ) == 0 ) {
1721         if ( !S_ISDIR( buf.st_mode ) ) {
1722             debugError( "\"%s\" is not a directory\n",  sDevicePath.c_str() );
1723             return false;
1724         }
1725     } else {
1726         if (  mkdir( sDevicePath.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
1727             debugError( "Could not create \"%s\" directory\n", sDevicePath.c_str() );
1728             return false;
1729         }
1730     }
1731
1732     char* configId;
1733     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId() );
1734     if ( !configId ) {
1735         debugError( "Could not create id string\n" );
1736         return false;
1737     }
1738     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
1739     free( configId );
1740     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
1741
1742     Util::XMLSerialize ser( sFileName );
1743     return serialize( "", ser );
1744 }
1745
1746 } // end of namespace
Note: See TracBrowser for help on using the browser.