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

Revision 762, 29.9 kB (checked in by wagi, 16 years ago)

Bug fix for #53

Somehow there was a major fuckup. It didn't make any sense at all.
The deserializing code for the PcrPlug?, ExternalPlugs? and
m_inputConnections/m_outputConnections should now be consistend with
the serializing code.

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