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

Revision 530, 53.4 kB (checked in by wagi, 16 years ago)

disable config parser code

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