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

Revision 1997, 31.6 kB (checked in by adi, 12 years ago)

Fix spelling mistake "connnection"

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