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

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

move serialization routines to libutil such that they can be used for non-AVC stuff too (fireworks EFC)

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 "libutil/cmd_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.