root/branches/echoaudio/src/libavc/general/avc_unit.cpp

Revision 548, 28.3 kB (checked in by ppalmers, 15 years ago)

- make the BeBoB AvDevice? a child class of the GenericAVC AvDevice?. This
avoids a lot of code duplication.
- fix inconsistency in position/location numbering between ext pluginfo
cmd and descriptor.

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