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

Revision 554, 29.2 kB (checked in by ppalmers, 15 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

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 digitalExternalInputPlugs = getPlugsByType( m_externalPlugs,
606                                                     Plug::eAPD_Input,
607                                                     Plug::eAPT_Digital );
608     if ( !digitalExternalInputPlugs.size() ) {
609         debugOutput( DEBUG_LEVEL_VERBOSE, "No external digital input plugs found\n" );
610
611     }
612    
613     PlugVector syncExternalInputPlugs = getPlugsByType( m_externalPlugs,
614                                                     Plug::eAPD_Input,
615                                                     Plug::eAPT_Sync );
616     if ( !syncExternalInputPlugs.size() ) {
617         debugOutput( DEBUG_LEVEL_VERBOSE, "No external sync input plugs found\n" );
618
619     }
620
621     PlugVector syncMSUInputPlugs = m_pPlugManager->getPlugsByType(
622         eST_Music,
623         0,
624         0xff,
625         0xff,
626         Plug::eAPA_SubunitPlug,
627         Plug::eAPD_Input,
628         Plug::eAPT_Sync );
629     if ( !syncMSUInputPlugs.size() ) {
630         debugWarning( "No sync input plug for MSU subunit found\n" );
631     }
632
633     PlugVector syncMSUOutputPlugs = m_pPlugManager->getPlugsByType(
634         eST_Music,
635         0,
636         0xff,
637         0xff,
638         Plug::eAPA_SubunitPlug,
639         Plug::eAPD_Output,
640         Plug::eAPT_Sync );
641     if ( !syncMSUOutputPlugs.size() ) {
642         debugWarning( "No sync output plug for MSU subunit found\n" );
643     }
644
645     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Input Plugs:\n" );
646     showPlugs( syncPCRInputPlugs );
647     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Sync Output Plugs:\n" );
648     showPlugs( syncPCROutputPlugs );
649     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Input Plugs:\n" );
650     showPlugs( isoPCRInputPlugs );
651     debugOutput( DEBUG_LEVEL_VERBOSE, "PCR Iso Output Plugs:\n" );
652     showPlugs( isoPCROutputPlugs );
653     debugOutput( DEBUG_LEVEL_VERBOSE, "External digital Input Plugs:\n" );
654     showPlugs( digitalExternalInputPlugs );
655     debugOutput( DEBUG_LEVEL_VERBOSE, "External sync Input Plugs:\n" );
656     showPlugs( syncExternalInputPlugs );
657     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Input Plugs:\n" );
658     showPlugs( syncMSUInputPlugs );
659     debugOutput( DEBUG_LEVEL_VERBOSE, "MSU Sync Output Plugs:\n" );
660     showPlugs( syncMSUOutputPlugs );
661
662     // Check all possible PCR input to MSU input connections
663     // -> sync stream input
664     checkSyncConnectionsAndAddToList( syncPCRInputPlugs,
665                                       syncMSUInputPlugs,
666                                       "Sync Stream Input" );
667
668     // Check all possible MSU output to PCR output connections
669     // -> sync stream output
670     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
671                                       syncPCROutputPlugs,
672                                       "Sync Stream Output" );
673
674     // Check all PCR iso input to MSU input connections
675     // -> SYT match
676     checkSyncConnectionsAndAddToList( isoPCRInputPlugs,
677                                       syncMSUInputPlugs,
678                                       "Syt Match" );
679
680     // Check all MSU sync output to MSU input connections
681     // -> CSP
682     checkSyncConnectionsAndAddToList( syncMSUOutputPlugs,
683                                       syncMSUInputPlugs,
684                                       "Internal (CSP)" );
685
686     // Check all external digital input to MSU input connections
687     // -> SPDIF/ADAT sync
688     checkSyncConnectionsAndAddToList( digitalExternalInputPlugs,
689                                       syncMSUInputPlugs,
690                                       "Digital Input Sync" );
691
692     // Check all external sync input to MSU input connections
693     // -> SPDIF/ADAT sync
694     checkSyncConnectionsAndAddToList( syncExternalInputPlugs,
695                                       syncMSUInputPlugs,
696                                       "Digital Input Sync" );
697
698     // Currently active connection signal source cmd, command type
699     // status, source unknown, destination MSU sync input plug
700
701     for ( PlugVector::const_iterator it = syncMSUInputPlugs.begin();
702           it != syncMSUInputPlugs.end();
703           ++it )
704     {
705         AVC::Plug* msuPlug = *it;
706         for ( PlugVector::const_iterator jt =
707                   msuPlug->getInputConnections().begin();
708               jt != msuPlug->getInputConnections().end();
709               ++jt )
710         {
711             AVC::Plug* plug = *jt;
712
713             for ( SyncInfoVector::iterator it = m_syncInfos.begin();
714                   it != m_syncInfos.end();
715                   ++it )
716             {
717                 SyncInfo* pSyncInfo = &*it;
718                 if ( ( pSyncInfo->m_source == plug )
719                      && ( pSyncInfo->m_destination == msuPlug ) )
720                 {
721                     m_activeSyncInfo = pSyncInfo;
722                     break;
723                 }
724             }
725             debugOutput( DEBUG_LEVEL_NORMAL,
726                          "Active Sync Connection: '%s' -> '%s'\n",
727                          plug->getName(),
728                          msuPlug->getName() );
729         }
730     }
731
732     return true;
733 }
734
735 bool
736 Unit::checkSyncConnectionsAndAddToList( PlugVector& plhs,
737                                             PlugVector& prhs,
738                                             std::string syncDescription )
739 {
740     for ( PlugVector::iterator plIt = plhs.begin();
741           plIt != plhs.end();
742           ++plIt )
743     {
744         AVC::Plug* pl = *plIt;
745         for ( PlugVector::iterator prIt = prhs.begin();
746               prIt != prhs.end();
747               ++prIt )
748         {
749             AVC::Plug* pr = *prIt;
750             if ( pl->inquireConnnection( *pr ) ) {
751                 m_syncInfos.push_back( SyncInfo( *pl, *pr, syncDescription ) );
752                 debugOutput( DEBUG_LEVEL_NORMAL,
753                              "Sync connection '%s' -> '%s'\n",
754                              pl->getName(),
755                              pr->getName() );
756             }
757         }
758     }
759     return true;
760 }
761
762 bool Unit::setActiveSync(const SyncInfo& syncInfo)
763 {
764     return syncInfo.m_source->setConnection( *syncInfo.m_destination );
765 }
766
767
768 void
769 Unit::showDevice()
770 {
771     m_pPlugManager->showPlugs();
772 }
773
774 void
775 Unit::showPlugs( PlugVector& plugs ) const
776 {
777     int i = 0;
778     for ( PlugVector::const_iterator it = plugs.begin();
779           it != plugs.end();
780           ++it, ++i )
781     {
782         Plug* plug = *it;
783         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d\n", i );
784         plug->showPlug();
785     }
786 }
787
788 template <typename T> bool serializeVector( Glib::ustring path,
789                                             Util::IOSerialize& ser,
790                                             const T& vec )
791 {
792     bool result = true; // if vec.size() == 0
793     int i = 0;
794     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
795         std::ostringstream strstrm;
796         strstrm << path << i;
797         result &= ( *it )->serialize( strstrm.str() + "/", ser );
798         i++;
799     }
800     return result;
801 }
802
803 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
804                                                            Util::IODeserialize& deser,
805                                                            Unit& unit,
806                                                            VT& vec )
807 {
808     int i = 0;
809     bool bFinished = false;
810     do {
811         std::ostringstream strstrm;
812         strstrm << path << i << "/";
813         T* ptr = T::deserialize( strstrm.str(),
814                                  deser,
815                                  unit );
816         if ( ptr ) {
817             vec.push_back( ptr );
818             i++;
819         } else {
820             bFinished = true;
821         }
822     } while ( !bFinished );
823
824     return true;
825 }
826
827 bool
828 Unit::serializeSyncInfoVector( Glib::ustring basePath,
829                                    Util::IOSerialize& ser,
830                                    const SyncInfoVector& vec )
831 {
832     bool result = true;
833     int i = 0;
834
835     for ( SyncInfoVector::const_iterator it = vec.begin();
836           it != vec.end();
837           ++it )
838     {
839         const SyncInfo& info = *it;
840
841         std::ostringstream strstrm;
842         strstrm << basePath << i << "/";
843
844         result &= ser.write( strstrm.str() + "m_source", info.m_source->getGlobalId() );
845         result &= ser.write( strstrm.str() + "m_destination", info.m_destination->getGlobalId() );
846         result &= ser.write( strstrm.str() + "m_description", Glib::ustring( info.m_description ) );
847
848         i++;
849     }
850
851     return result;
852 }
853
854 bool
855 Unit::deserializeSyncInfoVector( Glib::ustring basePath,
856                                      Util::IODeserialize& deser,
857                                      SyncInfoVector& vec )
858 {
859     int i = 0;
860     bool bFinished = false;
861     do {
862         bool result;
863         std::ostringstream strstrm;
864         strstrm << basePath << i << "/";
865
866         plug_id_t sourceId;
867         plug_id_t destinationId;
868         Glib::ustring description;
869
870         if ( deser.isExisting( strstrm.str() + "m_source" ) ) {
871             result  = deser.read( strstrm.str() + "m_source", sourceId );
872             result &= deser.read( strstrm.str() + "m_destination", destinationId );
873             result &= deser.read( strstrm.str() + "m_description", description );
874         } else {
875             result = false;
876         }
877
878         if ( result ) {
879             SyncInfo syncInfo;
880             syncInfo.m_source = m_pPlugManager->getPlug( sourceId );
881             syncInfo.m_destination = m_pPlugManager->getPlug( destinationId );
882             syncInfo.m_description = description;
883
884             vec.push_back( syncInfo );
885             i++;
886         } else {
887             bFinished = true;
888         }
889     } while ( !bFinished );
890
891     return true;
892 }
893
894 static bool
895 deserializePlugUpdateConnections( Glib::ustring path,
896                                     Util::IODeserialize& deser,
897                                     PlugVector& vec )
898 {
899     bool result = true;
900     for ( PlugVector::iterator it = vec.begin();
901           it != vec.end();
902           ++it )
903     {
904         Plug* pPlug = *it;
905         result &= pPlug->deserializeUpdate( path, deser );
906     }
907     return result;
908 }
909
910 bool
911 Unit::serialize( Glib::ustring basePath,
912                      Util::IOSerialize& ser ) const
913 {
914
915     bool result;
916     result  = ser.write( basePath + "m_verboseLevel_unit", getDebugLevel() );
917     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
918     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
919     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
920 #warning this fails after the echoaudio merge
921 //     result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
922    
923     int i = 0;
924     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
925           it != m_syncInfos.end();
926           ++it )
927     {
928         const SyncInfo& info = *it;
929         if ( m_activeSyncInfo == &info ) {
930             result &= ser.write( basePath + "m_activeSyncInfo",  i );
931             break;
932         }
933         i++;
934     }
935
936     return result;
937 }
938
939 bool
940 Unit::deserialize( Glib::ustring basePath,
941                    Util::IODeserialize& deser,
942                    Ieee1394Service& ieee1394Service )
943 {
944     bool result;
945    
946     int verboseLevel;
947     result  = deser.read( basePath + "m_verboseLevel_unit", verboseLevel );
948     setDebugLevel( verboseLevel );
949    
950     if (m_pPlugManager) delete m_pPlugManager;
951     m_pPlugManager = PlugManager::deserialize( basePath + "Plug", deser, *this );
952     if ( !m_pPlugManager ) {
953         return false;
954     }
955    
956     result &= deserializePlugUpdateConnections( basePath + "Plug", deser, m_pcrPlugs );
957     result &= deserializePlugUpdateConnections( basePath + "Plug", deser, m_externalPlugs );
958     result &= deserializeVector<PlugConnection>( basePath + "PlugConnnection", deser, *this, m_plugConnections );
959     result &= deserializeVector<Subunit>( basePath + "Subunit",  deser, *this, m_subunits );
960     result &= deserializeSyncInfoVector( basePath + "SyncInfo", deser, m_syncInfos );
961
962
963     unsigned int i;
964     result &= deser.read( basePath + "m_activeSyncInfo", i );
965
966     if ( result ) {
967         if ( i < m_syncInfos.size() ) {
968             m_activeSyncInfo = &m_syncInfos[i];
969         }
970     }
971
972     return true;
973 }
974
975 } // end of namespace
Note: See TracBrowser for help on using the browser.