root/trunk/libffado/src/libavc/general/avc_unit.cpp

Revision 560, 29.7 kB (checked in by ppalmers, 17 years ago)

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

Line 
1 /*
2  * Copyright (C)      2007 by Pieter Palmers
3  * Copyright (C) 2005-2007 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25 #include "avc_unit.h"
26 #include "avc_subunit.h"
27 #include "avc_plug.h"
28
29 #include "libieee1394/configrom.h"
30 #include "libieee1394/ieee1394service.h"
31
32 #include "../general/avc_plug_info.h"
33 #include "../general/avc_extended_plug_info.h"
34 #include "../general/avc_subunit_info.h"
35 #include "../streamformat/avc_extended_stream_format.h"
36 #include "../util/avc_serialize.h"
37 #include "../avc_definitions.h"
38
39 #include "debugmodule/debugmodule.h"
40
41 #include <iostream>
42 #include <sstream>
43
44 namespace AVC {
45
46 IMPL_DEBUG_MODULE( Unit, Unit, DEBUG_LEVEL_NORMAL );
47
48 Unit::Unit( )
49     : m_pPlugManager( new PlugManager( ) )
50     , m_activeSyncInfo( 0 )
51 {
52     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Unit\n" );
53     m_pPlugManager->setVerboseLevel( getDebugLevel() );
54 }
55
56 Unit::~Unit()
57 {
58     for ( SubunitVector::iterator it = m_subunits.begin();
59           it != m_subunits.end();
60           ++it )
61     {
62         delete *it;
63     }
64     for ( PlugConnectionVector::iterator it = m_plugConnections.begin();
65           it != m_plugConnections.end();
66           ++it )
67     {
68         delete *it;
69     }
70     for ( PlugVector::iterator it = m_pcrPlugs.begin();
71           it != m_pcrPlugs.end();
72           ++it )
73     {
74         delete *it;
75     }
76     for ( PlugVector::iterator it = m_externalPlugs.begin();
77           it != m_externalPlugs.end();
78           ++it )
79     {
80         delete *it;
81     }
82 }
83
84 Plug *
85 Unit::createPlug( Unit* unit,
86                   Subunit* subunit,
87                   function_block_type_t functionBlockType,
88                   function_block_type_t functionBlockId,
89                   Plug::EPlugAddressType plugAddressType,
90                   Plug::EPlugDirection plugDirection,
91                   plug_id_t plugId )
92 {
93
94     Plug *p= new Plug( unit,
95                        subunit,
96                        functionBlockType,
97                        functionBlockId,
98                        plugAddressType,
99                        plugDirection,
100                        plugId );
101     if (p) p->setVerboseLevel(getDebugLevel());
102     return p;
103 }
104
105 Subunit*
106 Unit::createSubunit(Unit& unit,
107                     ESubunitType type,
108                     subunit_t id )
109 {
110     Subunit* s=NULL;
111     switch (type) {
112         case eST_Audio:
113             s=new SubunitAudio(unit, id );
114             break;
115         case eST_Music:
116             s=new SubunitMusic(unit, id );
117             break;
118         default:
119             s=NULL;
120             break;
121     }
122     if(s) s->setVerboseLevel(getDebugLevel());
123     return s;
124 }
125
126 void
127 Unit::setVerboseLevel(int l)
128 {
129     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
130     setDebugLevel(l);
131     for ( SubunitVector::const_iterator it = m_subunits.begin();
132           it != m_subunits.end();
133           ++it )
134     {
135         (*it)->setVerboseLevel(l);
136     }
137
138     m_pPlugManager->setVerboseLevel(l);
139 }
140
141 bool
142 Unit::discover()
143 {
144
145     if ( !enumerateSubUnits() ) {
146         debugError( "Could not enumarate sub units\n" );
147         return false;
148     }
149
150     if ( !discoverPlugs() ) {
151         debugError( "Detecting plugs failed\n" );
152         return false;
153     }
154
155     if ( !discoverPlugConnections() ) {
156         debugError( "Detecting plug connections failed\n" );
157         return false;
158     }
159
160     if ( !discoverSubUnitsPlugConnections() ) {
161         debugError( "Detecting subunit plug connnections failed\n" );
162         return false;
163     }
164
165     if ( !m_pPlugManager->tidyPlugConnections(m_plugConnections) ) {
166         debugError( "Tidying of plug connnections failed\n" );
167         return false;
168     }
169
170     if ( !discoverSyncModes() ) {
171         debugError( "Detecting sync modes failed\n" );
172         return false;
173     }
174
175     if ( !propagatePlugInfo() ) {
176         debugError( "Failed to propagate plug info\n" );
177         return false;
178     }
179
180     return true;
181 }
182
183 bool
184 Unit::enumerateSubUnits()
185 {
186     SubUnitInfoCmd subUnitInfoCmd( get1394Service() );
187     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
188
189     // NOTE: BeBoB has always exactly one audio and one music subunit. This
190     // means is fits into the first page of the SubUnitInfo command.
191     // So there is no need to do more than needed
192     // FIXME: to be fully spec compliant this needs to be fixed, but let's not
193     //        do that for now
194
195     subUnitInfoCmd.m_page = 0;
196     subUnitInfoCmd.setNodeId( getConfigRom().getNodeId() );
197     subUnitInfoCmd.setVerbose( getDebugLevel() );
198     if ( !subUnitInfoCmd.fire() ) {
199         debugError( "Subunit info command failed\n" );
200         // shouldn't this be an error situation?
201         return false;
202     }
203
204     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
205         subunit_type_t subunit_type
206             = subUnitInfoCmd.m_table[i].m_subunit_type;
207
208         unsigned int subunitId = getNrOfSubunits( subunit_type );
209
210         debugOutput( DEBUG_LEVEL_VERBOSE,
211                      "subunit_id = %2d, subunit_type = %2d (%s)\n",
212                      subunitId,
213                      subunit_type,
214                      subunitTypeToString( subunit_type ) );
215
216         Subunit* subunit = 0;
217         switch( subunit_type ) {
218         case eST_Audio:
219             subunit = createSubunit( *this, eST_Audio, subunitId );
220             if ( !subunit ) {
221                 debugFatal( "Could not allocate SubunitAudio\n" );
222                 return false;
223             }
224            
225             subunit->setVerboseLevel(getDebugLevel());
226            
227             if ( !subunit->discover() ) {
228                 debugError( "enumerateSubUnits: Could not discover "
229                             "subunit_id = %2d, subunit_type = %2d (%s)\n",
230                             subunitId,
231                             subunit_type,
232                             subunitTypeToString( subunit_type ) );
233                 delete subunit;
234                 return false;
235             } else {
236                 m_subunits.push_back( subunit );
237             }
238            
239             break;
240         case eST_Music:
241             subunit = createSubunit( *this, eST_Music, subunitId );
242             if ( !subunit ) {
243                 debugFatal( "Could not allocate SubunitMusic\n" );
244                 return false;
245             }
246            
247             subunit->setVerboseLevel(getDebugLevel());
248            
249             if ( !subunit->discover() ) {
250                 debugError( "enumerateSubUnits: Could not discover "
251                             "subunit_id = %2d, subunit_type = %2d (%s)\n",
252                             subunitId,
253                             subunit_type,
254                             subunitTypeToString( subunit_type ) );
255                 delete subunit;
256                 return false;
257             } else {
258                 m_subunits.push_back( subunit );
259             }
260
261             break;
262         default:
263             debugOutput( DEBUG_LEVEL_NORMAL,
264                          "Unsupported subunit found, subunit_type = %d (%s)\n",
265                          subunit_type,
266                          subunitTypeToString( subunit_type ) );
267             continue;
268
269         }
270     }
271
272     return true;
273 }
274
275 Subunit*
276 Unit::getSubunit( subunit_type_t subunitType,
277                       subunit_id_t subunitId ) const
278 {
279     for ( SubunitVector::const_iterator it = m_subunits.begin();
280           it != m_subunits.end();
281           ++it )
282     {
283         Subunit* subunit = *it;
284         if ( ( subunitType == subunit->getSubunitType() )
285              && ( subunitId == subunit->getSubunitId() ) )
286         {
287             return subunit;
288         }
289     }
290
291     return 0;
292 }
293
294 unsigned int
295 Unit::getNrOfSubunits( subunit_type_t subunitType ) const
296 {
297     unsigned int nrOfSubunits = 0;
298
299     for ( SubunitVector::const_iterator it = m_subunits.begin();
300           it != m_subunits.end();
301           ++it )
302     {
303         Subunit* subunit = *it;
304         if ( subunitType == subunit->getSubunitType() ) {
305             nrOfSubunits++;
306         }
307     }
308
309     return nrOfSubunits;
310 }
311
312 bool
313 Unit::discoverPlugs()
314 {
315     debugOutput( DEBUG_LEVEL_NORMAL, "Discovering plugs...\n");
316
317     //////////////////////////////////////////////
318     // Get number of available isochronous input
319     // and output plugs of unit
320
321     PlugInfoCmd plugInfoCmd( get1394Service() );
322     plugInfoCmd.setNodeId( getConfigRom().getNodeId() );
323     plugInfoCmd.setCommandType( AVCCommand::eCT_Status );
324     plugInfoCmd.setVerbose( getDebugLevel() );
325
326     if ( !plugInfoCmd.fire() ) {
327         debugError( "plug info command failed\n" );
328         return false;
329     }
330
331     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso input plugs = %d\n",
332                  plugInfoCmd.m_serialBusIsochronousInputPlugs );
333     debugOutput( DEBUG_LEVEL_NORMAL, "number of iso output plugs = %d\n",
334                  plugInfoCmd.m_serialBusIsochronousOutputPlugs );
335     debugOutput( DEBUG_LEVEL_NORMAL, "number of external input plugs = %d\n",
336                  plugInfoCmd.m_externalInputPlugs );
337     debugOutput( DEBUG_LEVEL_NORMAL, "number of external output plugs = %d\n",
338                  plugInfoCmd.m_externalOutputPlugs );
339
340     if ( !discoverPlugsPCR( Plug::eAPD_Input,
341                             plugInfoCmd.m_serialBusIsochronousInputPlugs ) )
342     {
343         debugError( "pcr input plug discovering failed\n" );
344         return false;
345     }
346
347     if ( !discoverPlugsPCR( Plug::eAPD_Output,
348                             plugInfoCmd.m_serialBusIsochronousOutputPlugs ) )
349     {
350         debugError( "pcr output plug discovering failed\n" );
351         return false;
352     }
353
354     if ( !discoverPlugsExternal( Plug::eAPD_Input,
355                                  plugInfoCmd.m_externalInputPlugs ) )
356     {
357         debugError( "external input plug discovering failed\n" );
358         return false;
359     }
360
361     if ( !discoverPlugsExternal( Plug::eAPD_Output,
362                                  plugInfoCmd.m_externalOutputPlugs ) )
363     {
364         debugError( "external output plug discovering failed\n" );
365         return false;
366     }
367
368     return true;
369 }
370
371 bool
372 Unit::discoverPlugsPCR( Plug::EPlugDirection plugDirection,
373                             plug_id_t plugMaxId )
374 {
375     debugOutput( DEBUG_LEVEL_NORMAL, "Discovering PCR plugs, direction %d...\n",plugDirection);
376     for ( int plugId = 0;
377           plugId < plugMaxId;
378           ++plugId )
379     {
380         Plug* plug  = createPlug( this,
381                                 NULL,
382                                 0xff,
383                                 0xff,
384                                 Plug::eAPA_PCR,
385                                 plugDirection,
386                                 plugId );
387
388         if( plug ) plug->setVerboseLevel(getDebugLevel());
389
390         if ( !plug || !plug->discover() ) {
391             debugError( "plug discovering failed\n" );
392             delete plug;
393             return false;
394         }
395
396         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
397                      plug->getName() );
398         m_pcrPlugs.push_back( plug );
399     }
400
401     return true;
402 }
403
404 bool
405 Unit::discoverPlugsExternal( Plug::EPlugDirection plugDirection,
406                                  plug_id_t plugMaxId )
407 {
408     debugOutput( DEBUG_LEVEL_NORMAL, "Discovering External plugs, direction %d...\n",plugDirection);
409     for ( int plugId = 0;
410           plugId < plugMaxId;
411           ++plugId )
412     {
413         Plug* plug  = createPlug( this, NULL,
414                                 0xff,
415                                 0xff,
416                                 Plug::eAPA_ExternalPlug,
417                                 plugDirection,
418                                 plugId );
419
420         if( plug ) plug->setVerboseLevel(getDebugLevel());
421
422         if ( !plug || !plug->discover() ) {
423             debugError( "plug discovering failed\n" );
424             return false;
425         }
426
427         debugOutput( DEBUG_LEVEL_NORMAL, "plug '%s' found\n",
428                      plug->getName() );
429         m_externalPlugs.push_back( plug );
430     }
431
432     return true;
433 }
434
435 bool
436 Unit::discoverPlugConnections()
437 {
438     debugOutput( DEBUG_LEVEL_NORMAL, "Discovering PCR plug connections...\n");
439     for ( PlugVector::iterator it = m_pcrPlugs.begin();
440           it != m_pcrPlugs.end();
441           ++it )
442     {
443         Plug* plug = *it;
444         if ( !plug->discoverConnections() ) {
445             debugError( "Could not discover PCR plug connections\n" );
446             return false;
447         }
448     }
449     debugOutput( DEBUG_LEVEL_NORMAL, "Discovering External plug connections...\n");
450     for ( PlugVector::iterator it = m_externalPlugs.begin();
451           it != m_externalPlugs.end();
452           ++it )
453     {
454         Plug* plug = *it;
455         if ( !plug->discoverConnections() ) {
456             debugError( "Could not discover External plug connections\n" );
457             return false;
458         }
459     }
460
461     return true;
462 }
463
464 bool
465 Unit::discoverSubUnitsPlugConnections()
466 {
467     for ( SubunitVector::iterator it = m_subunits.begin();
468           it != m_subunits.end();
469           ++it )
470     {
471         Subunit* subunit = *it;
472
473         if ( !subunit->discoverConnections() ) {
474             debugError( "Subunit '%s'  plug connections failed\n",
475                         subunit->getName() );
476             return false;
477         }
478     }
479     return true;
480 }
481
482 bool
483 Unit::propagatePlugInfo()
484 {
485     debugOutput( DEBUG_LEVEL_NORMAL, "Propagating info to PCR plugs...\n");
486     for ( PlugVector::iterator it = m_pcrPlugs.begin();
487           it != m_pcrPlugs.end();
488           ++it )
489     {
490         Plug* plug = *it;
491         debugOutput( DEBUG_LEVEL_NORMAL, "plug: %s\n", plug->getName());
492         if (!plug->propagateFromConnectedPlug()) {
493             debugWarning( "Could not propagate info for plug '%s'\n", plug->getName());
494         }
495     }
496     debugOutput( DEBUG_LEVEL_NORMAL, "Propagating info to External plugs...\n");
497     for ( PlugVector::iterator it = m_externalPlugs.begin();
498           it != m_externalPlugs.end();
499           ++it )
500     {
501         Plug* plug = *it;
502         debugOutput( DEBUG_LEVEL_NORMAL, "plug: %s\n", plug->getName());
503         if (!plug->propagateFromConnectedPlug()) {
504             debugWarning( "Could not propagate info for plug '%s'\n", plug->getName());
505         }
506     }
507
508     return true;
509
510 }
511
512
513 PlugConnection*
514 Unit::getPlugConnection( Plug& srcPlug ) const
515 {
516     for ( PlugConnectionVector::const_iterator it
517               = m_plugConnections.begin();
518           it != m_plugConnections.end();
519           ++it )
520     {
521         PlugConnection* plugConnection = *it;
522         if ( &( plugConnection->getSrcPlug() ) == &srcPlug ) {
523             return plugConnection;
524         }
525     }
526
527     return 0;
528 }
529
530 Plug*
531 Unit::getPlugById( PlugVector& plugs,
532                        Plug::EPlugDirection plugDirection,
533                        int id )
534 {
535     for ( PlugVector::iterator it = plugs.begin();
536           it != plugs.end();
537           ++it )
538     {
539         Plug* plug = *it;
540         if ( ( id == plug->getPlugId() )
541              && ( plugDirection == plug->getPlugDirection() ) )
542         {
543             return plug;
544         }
545     }
546
547     return 0;
548 }
549
550 PlugVector
551 Unit::getPlugsByType( PlugVector& plugs,
552                           Plug::EPlugDirection plugDirection,
553                           Plug::EPlugType type)
554 {
555     PlugVector plugVector;
556     for ( PlugVector::iterator it = plugs.begin();
557           it != plugs.end();
558           ++it )
559     {
560         Plug* plug = *it;
561         if ( ( type == plug->getPlugType() )
562              && ( plugDirection == plug->getPlugDirection() ) )
563         {
564             plugVector.push_back( plug );
565         }
566     }
567
568     return plugVector;
569 }
570
571 Plug*
572 Unit::getSyncPlug( int maxPlugId, Plug::EPlugDirection )
573 {
574     return 0;
575 }
576
577 bool
578 Unit::discoverSyncModes()
579 {
580     // Following possible sync plugs exists:
581     // - Music subunit sync output plug = internal sync (CSP)
582     // - Unit input plug 0 = SYT match
583     // - Unit input plut 1 = Sync stream
584     //
585     // If last sync mode is reported it is mostelikely not
586     // implemented *sic*
587     //
588     // Following sync sources are device specific:
589     // - All unit external input plugs which have a
590     //   sync information (WS, SPDIF, ...)
591
592     // First we have to find the sync input and output plug
593     // in the music subunit.
594
595     // Note PCR input means 1394bus-to-device where as
596     // MSU input means subunit-to-device
597
598     PlugVector syncPCRInputPlugs = getPlugsByType( m_pcrPlugs,
599                                                      Plug::eAPD_Input,
600                                                      Plug::eAPT_Sync );
601     if ( !syncPCRInputPlugs.size() ) {
602         debugWarning( "No PCR sync input plug found\n" );
603     }
604
605     PlugVector syncPCROutputPlugs = getPlugsByType( m_pcrPlugs,
606                                                       Plug::eAPD_Output,
607                                                       Plug::eAPT_Sync );
608     if ( !syncPCROutputPlugs.size() ) {
609         debugWarning( "No PCR sync output plug found\n" );
610     }
611
612     PlugVector isoPCRInputPlugs = getPlugsByType( m_pcrPlugs,
613                                                     Plug::eAPD_Input,
614                                                     Plug::eAPT_IsoStream );
615     if ( !isoPCRInputPlugs.size() ) {
616         debugWarning( "No PCR iso input plug found\n" );
617
618     }
619
620     PlugVector isoPCROutputPlugs = getPlugsByType( m_pcrPlugs,
621                                                     Plug::eAPD_Output,
622                                                     Plug::eAPT_IsoStream );
623     if ( !isoPCROutputPlugs.size() ) {
624         debugWarning( "No PCR iso output plug found\n" );
625
626     }
627
628     PlugVector digitalExternalInputPlugs = getPlugsByType( m_externalPlugs,
629                                                     Plug::eAPD_Input,
630                                                     Plug::eAPT_Digital );
631     if ( !digitalExternalInputPlugs.size() ) {
632         debugOutput( DEBUG_LEVEL_VERBOSE, "No external digital input plugs found\n" );
633
634     }
635    
636     PlugVector syncExternalInputPlugs = getPlugsByType( m_externalPlugs,
637                                                     Plug::eAPD_Input,
638                                                     Plug::eAPT_Sync );
639     if ( !syncExternalInputPlugs.size() ) {
640         debugOutput( DEBUG_LEVEL_VERBOSE, "No external sync input plugs found\n" );
641
642     }
643
644     PlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
645         eST_Music,
646         0,
647         0xff,
648         0xff,
649         Plug::eAPA_SubunitPlug,
650         Plug::eAPD_Input,
651         Plug::eAPT_Sync );
652     if ( !syncMSUInputPlugs.size() ) {
653         debugWarning( "No sync input plug for MSU subunit found\n" );
654     }
655
656     PlugVector syncMSUOutputPlugs = m_pPlugManager->getPlugsByType(
657         eST_Music,
658         0,
659         0xff,
660         0xff,
661         Plug::eAPA_SubunitPlug,
662         Plug::eAPD_Output,
663         Plug::eAPT_Sync );
664     if ( !syncMSUOutputPlugs.size() ) {
665         debugWarning( "No sync output plug for MSU subunit found\n" );
666     }
667
668     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Input Plugs:\n" );
669     showPlugs( syncPCRInputPlugs );
670     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Output Plugs:\n" );
671     showPlugs( syncPCROutputPlugs );
672     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Input Plugs:\n" );
673     showPlugs( isoPCRInputPlugs );
674     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Output Plugs:\n" );
675     showPlugs( isoPCROutputPlugs );
676     debugOutput( DEBUG_LEVEL_VERBOSE, "External digital Input Plugs:\n" );
677     showPlugs( digitalExternalInputPlugs );
678     debugOutput( DEBUG_LEVEL_VERBOSE, "External sync Input Plugs:\n" );
679     showPlugs( syncExternalInputPlugs );
680     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Input Plugs:\n" );
681     showPlugs( syncMSUInputPlugs );
682     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Output Plugs:\n" );
683     showPlugs( syncMSUOutputPlugs );
684
685     // Check all possible PCR input to MSU input connections
686     // -> sync stream input
687     checkSyncConnectionsAndAddToList( syncPCRInputPlugs,
688                                       syncMSUInputPlugs,
689                                       "Sync Stream Input" );
690
691     // Check all possible MSU output to PCR output connections
692     // -> sync stream output
693     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
694                                       syncPCROutputPlugs,
695                                       "Sync Stream Output" );
696
697     // Check all PCR iso input to MSU input connections
698     // -> SYT match
699     checkSyncConnectionsAndAddToList( isoPCRInputPlugs,
700                                       syncMSUInputPlugs,
701                                       "Syt Match" );
702
703     // Check all MSU sync output to MSU input connections
704     // -> CSP
705     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
706                                       syncMSUInputPlugs,
707                                       "Internal (CSP)" );
708
709     // Check all external digital input to MSU input connections
710     // -> SPDIF/ADAT sync
711     checkSyncConnectionsAndAddToList( digitalExternalInputPlugs,
712                                       syncMSUInputPlugs,
713                                       "Digital Input Sync" );
714
715     // Check all external sync input to MSU input connections
716     // -> SPDIF/ADAT sync
717     checkSyncConnectionsAndAddToList( syncExternalInputPlugs,
718                                       syncMSUInputPlugs,
719                                       "Digital Input Sync" );
720
721     // Currently active connection signal source cmd, command type
722     // status, source unknown, destination MSU sync input plug
723
724     for ( PlugVector::const_iterator it = syncMSUInputPlugs.begin();
725           it != syncMSUInputPlugs.end();
726           ++it )
727     {
728         AVC::Plug* msuPlug = *it;
729         for ( PlugVector::const_iterator jt =
730                   msuPlug->getInputConnections().begin();
731               jt != msuPlug->getInputConnections().end();
732               ++jt )
733         {
734             AVC::Plug* plug = *jt;
735
736             for ( SyncInfoVector::iterator it = m_syncInfos.begin();
737                   it != m_syncInfos.end();
738                   ++it )
739             {
740                 SyncInfo* pSyncInfo = &*it;
741                 if ( ( pSyncInfo->m_source == plug )
742                      && ( pSyncInfo->m_destination == msuPlug ) )
743                 {
744                     m_activeSyncInfo = pSyncInfo;
745                     break;
746                 }
747             }
748             debugOutput( DEBUG_LEVEL_NORMAL,
749                          "Active Sync Connection: '%s' -> '%s'\n",
750                          plug->getName(),
751                          msuPlug->getName() );
752         }
753     }
754
755     return true;
756 }
757
758 bool
759 Unit::checkSyncConnectionsAndAddToList( PlugVector& plhs,
760                                             PlugVector& prhs,
761                                             std::string syncDescription )
762 {
763     for ( PlugVector::iterator plIt = plhs.begin();
764           plIt != plhs.end();
765           ++plIt )
766     {
767         AVC::Plug* pl = *plIt;
768         for ( PlugVector::iterator prIt = prhs.begin();
769               prIt != prhs.end();
770               ++prIt )
771         {
772             AVC::Plug* pr = *prIt;
773             if ( pl->inquireConnnection( *pr ) ) {
774                 m_syncInfos.push_back( SyncInfo( *pl, *pr, syncDescription ) );
775                 debugOutput( DEBUG_LEVEL_NORMAL,
776                              "Sync connection '%s' -> '%s'\n",
777                              pl->getName(),
778                              pr->getName() );
779             }
780         }
781     }
782     return true;
783 }
784
785 bool Unit::setActiveSync(const SyncInfo& syncInfo)
786 {
787     return syncInfo.m_source->setConnection( *syncInfo.m_destination );
788 }
789
790
791 void
792 Unit::show()
793 {
794     m_pPlugManager->showPlugs();
795 }
796
797 void
798 Unit::showPlugs( PlugVector& plugs ) const
799 {
800     int i = 0;
801     for ( PlugVector::const_iterator it = plugs.begin();
802           it != plugs.end();
803           ++it, ++i )
804     {
805         Plug* plug = *it;
806         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d\n", i );
807         plug->showPlug();
808     }
809 }
810
811 template <typename T> bool serializeVector( Glib::ustring path,
812                                             Util::IOSerialize& ser,
813                                             const T& vec )
814 {
815     bool result = true; // if vec.size() == 0
816     int i = 0;
817     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
818         std::ostringstream strstrm;
819         strstrm << path << i;
820         result &= ( *it )->serialize( strstrm.str() + "/", ser );
821         i++;
822     }
823     return result;
824 }
825
826 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
827                                                            Util::IODeserialize& deser,
828                                                            Unit& unit,
829                                                            VT& vec )
830 {
831     int i = 0;
832     bool bFinished = false;
833     do {
834         std::ostringstream strstrm;
835         strstrm << path << i << "/";
836         T* ptr = T::deserialize( strstrm.str(),
837                                  deser,
838                                  unit );
839         if ( ptr ) {
840             vec.push_back( ptr );
841             i++;
842         } else {
843             bFinished = true;
844         }
845     } while ( !bFinished );
846
847     return true;
848 }
849
850 bool
851 Unit::serializeSyncInfoVector( Glib::ustring basePath,
852                                    Util::IOSerialize& ser,
853                                    const SyncInfoVector& vec )
854 {
855     bool result = true;
856     int i = 0;
857
858     for ( SyncInfoVector::const_iterator it = vec.begin();
859           it != vec.end();
860           ++it )
861     {
862         const SyncInfo& info = *it;
863
864         std::ostringstream strstrm;
865         strstrm << basePath << i << "/";
866
867         result &= ser.write( strstrm.str() + "m_source", info.m_source->getGlobalId() );
868         result &= ser.write( strstrm.str() + "m_destination", info.m_destination->getGlobalId() );
869         result &= ser.write( strstrm.str() + "m_description", Glib::ustring( info.m_description ) );
870
871         i++;
872     }
873
874     return result;
875 }
876
877 bool
878 Unit::deserializeSyncInfoVector( Glib::ustring basePath,
879                                      Util::IODeserialize& deser,
880                                      SyncInfoVector& vec )
881 {
882     int i = 0;
883     bool bFinished = false;
884     do {
885         bool result;
886         std::ostringstream strstrm;
887         strstrm << basePath << i << "/";
888
889         plug_id_t sourceId;
890         plug_id_t destinationId;
891         Glib::ustring description;
892
893         if ( deser.isExisting( strstrm.str() + "m_source" ) ) {
894             result  = deser.read( strstrm.str() + "m_source", sourceId );
895             result &= deser.read( strstrm.str() + "m_destination", destinationId );
896             result &= deser.read( strstrm.str() + "m_description", description );
897         } else {
898             result = false;
899         }
900
901         if ( result ) {
902             SyncInfo syncInfo;
903             syncInfo.m_source = m_pPlugManager->getPlug( sourceId );
904             syncInfo.m_destination = m_pPlugManager->getPlug( destinationId );
905             syncInfo.m_description = description;
906
907             vec.push_back( syncInfo );
908             i++;
909         } else {
910             bFinished = true;
911         }
912     } while ( !bFinished );
913
914     return true;
915 }
916
917 static bool
918 deserializePlugUpdateConnections( Glib::ustring path,
919                                     Util::IODeserialize& deser,
920                                     PlugVector& vec )
921 {
922     bool result = true;
923     for ( PlugVector::iterator it = vec.begin();
924           it != vec.end();
925           ++it )
926     {
927         Plug* pPlug = *it;
928         result &= pPlug->deserializeUpdate( path, deser );
929     }
930     return result;
931 }
932
933 bool
934 Unit::serialize( Glib::ustring basePath,
935                      Util::IOSerialize& ser ) const
936 {
937
938     bool result;
939     result  = ser.write( basePath + "m_verboseLevel_unit", getDebugLevel() );
940     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
941     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
942     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
943 #warning this fails after the echoaudio merge
944 //     result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
945    
946     int i = 0;
947     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
948           it != m_syncInfos.end();
949           ++it )
950     {
951         const SyncInfo& info = *it;
952         if ( m_activeSyncInfo == &info ) {
953             result &= ser.write( basePath + "m_activeSyncInfo",  i );
954             break;
955         }
956         i++;
957     }
958
959     return result;
960 }
961
962 bool
963 Unit::deserialize( Glib::ustring basePath,
964                    Util::IODeserialize& deser,
965                    Ieee1394Service& ieee1394Service )
966 {
967     bool result;
968    
969     int verboseLevel;
970     result  = deser.read( basePath + "m_verboseLevel_unit", verboseLevel );
971     setDebugLevel( verboseLevel );
972    
973     if (m_pPlugManager) delete m_pPlugManager;
974     m_pPlugManager = PlugManager::deserialize( basePath + "Plug", deser, *this );
975     if ( !m_pPlugManager ) {
976         return false;
977     }
978    
979     result &= deserializePlugUpdateConnections( basePath + "Plug", deser, m_pcrPlugs );
980     result &= deserializePlugUpdateConnections( basePath + "Plug", deser, m_externalPlugs );
981     result &= deserializeVector<PlugConnection>( basePath + "PlugConnnection", deser, *this, m_plugConnections );
982     result &= deserializeVector<Subunit>( basePath + "Subunit",  deser, *this, m_subunits );
983     result &= deserializeSyncInfoVector( basePath + "SyncInfo", deser, m_syncInfos );
984
985
986     unsigned int i;
987     result &= deser.read( basePath + "m_activeSyncInfo", i );
988
989     if ( result ) {
990         if ( i < m_syncInfos.size() ) {
991             m_activeSyncInfo = &m_syncInfos[i];
992         }
993     }
994
995     return true;
996 }
997
998 } // end of namespace
Note: See TracBrowser for help on using the browser.