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

Revision 678, 30.5 kB (checked in by ppalmers, 16 years ago)

Fix bug where the internal data structures of the AVC::Unit were not cleared before discovery. This
prevented devices from being re-discovered since all old structures remained (e.g. all of a sudden
there are 2 music subunits)

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