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

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