root/branches/echoaudio/src/libavc/general/avc_unit.cpp

Revision 507, 14.1 kB (checked in by ppalmers, 17 years ago)

[Temporary commit: compiles but doesn't run]

First pass on AV/C code refactoring. Generic code and data structures
are moved to libavc classes. Implementation/vendor specific stuff remains
in specific classes.

In this case all 'Extended' commands and the discovery procedures remain in
the bebob/ classes, while the remainder goes into the libavc classes.

Line 
1 /*
2  * Copyright (C)      2007 by Pieter Palmers
3  * Copyright (C) 2005-2007 by Daniel Wagner
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25 #include "avc_unit.h"
26 #include "avc_subunit.h"
27 #include "avc_plug.h"
28
29 #include "libieee1394/configrom.h"
30 #include "libieee1394/ieee1394service.h"
31
32 #include "../general/avc_plug_info.h"
33 #include "../general/avc_extended_plug_info.h"
34 #include "../general/avc_subunit_info.h"
35 #include "../streamformat/avc_extended_stream_format.h"
36 #include "../util/avc_serialize.h"
37 #include "../avc_definitions.h"
38
39 #include "debugmodule/debugmodule.h"
40
41 #include <iostream>
42 #include <sstream>
43
44 namespace AVC {
45
46 IMPL_DEBUG_MODULE( Unit, Unit, DEBUG_LEVEL_VERBOSE );
47
48 Unit::Unit( std::auto_ptr< ConfigRom >( configRom ),
49                   Ieee1394Service& ieee1394service,
50                   int nodeId )
51     : m_pPlugManager( new PlugManager( ) )
52     , m_activeSyncInfo( 0 )
53     , m_puConfigRom( configRom )
54     , m_pu1394Service( &ieee1394service )
55 {
56     debugOutput( DEBUG_LEVEL_VERBOSE, "Created AVC::Unit (NodeID %d)\n",
57                  nodeId );
58 }
59
60 Unit::~Unit()
61 {
62     for ( SubunitVector::iterator it = m_subunits.begin();
63           it != m_subunits.end();
64           ++it )
65     {
66         delete *it;
67     }
68     for ( PlugConnectionVector::iterator it = m_plugConnections.begin();
69           it != m_plugConnections.end();
70           ++it )
71     {
72         delete *it;
73     }
74     for ( PlugVector::iterator it = m_pcrPlugs.begin();
75           it != m_pcrPlugs.end();
76           ++it )
77     {
78         delete *it;
79     }
80     for ( PlugVector::iterator it = m_externalPlugs.begin();
81           it != m_externalPlugs.end();
82           ++it )
83     {
84         delete *it;
85     }
86 }
87
88 void
89 Unit::setVerboseLevel(int l)
90 {
91     m_pPlugManager->setVerboseLevel(l);
92 }
93
94 bool
95 Unit::discover()
96 {
97
98     if ( !enumerateSubUnits() ) {
99         debugError( "Could not enumarate sub units\n" );
100         return false;
101     }
102
103     return true;
104 }
105
106 bool
107 Unit::enumerateSubUnits()
108 {
109     SubUnitInfoCmd subUnitInfoCmd( *m_pu1394Service );
110     subUnitInfoCmd.setCommandType( AVCCommand::eCT_Status );
111
112     // NOTE: BeBoB has always exactly one audio and one music subunit. This
113     // means is fits into the first page of the SubUnitInfo command.
114     // So there is no need to do more than needed
115     // FIXME: to be fully spec compliant this needs to be fixed, but let's not
116     //        do that for now
117
118     subUnitInfoCmd.m_page = 0;
119     subUnitInfoCmd.setNodeId( m_puConfigRom->getNodeId() );
120     subUnitInfoCmd.setVerbose( getDebugLevel() );
121     if ( !subUnitInfoCmd.fire() ) {
122         debugError( "Subunit info command failed\n" );
123         // shouldn't this be an error situation?
124         return false;
125     }
126
127     for ( int i = 0; i < subUnitInfoCmd.getNrOfValidEntries(); ++i ) {
128         subunit_type_t subunit_type
129             = subUnitInfoCmd.m_table[i].m_subunit_type;
130
131         unsigned int subunitId = getNrOfSubunits( subunit_type );
132
133         debugOutput( DEBUG_LEVEL_VERBOSE,
134                      "subunit_id = %2d, subunit_type = %2d (%s)\n",
135                      subunitId,
136                      subunit_type,
137                      subunitTypeToString( subunit_type ) );
138
139         Subunit* subunit = 0;
140         switch( subunit_type ) {
141         case eST_Audio:
142             subunit = new SubunitAudio( *this,
143                                                 subunitId );
144             if ( !subunit ) {
145                 debugFatal( "Could not allocate SubunitAudio\n" );
146                 return false;
147             }
148            
149             if ( !subunit->discover() ) {
150                 debugError( "enumerateSubUnits: Could not discover "
151                             "subunit_id = %2d, subunit_type = %2d (%s)\n",
152                             subunitId,
153                             subunit_type,
154                             subunitTypeToString( subunit_type ) );
155                 delete subunit;
156                 return false;
157             } else {
158                 m_subunits.push_back( subunit );
159             }
160            
161             break;
162         case eST_Music:
163             subunit = new SubunitMusic( *this,
164                                         subunitId );
165             if ( !subunit ) {
166                 debugFatal( "Could not allocate SubunitMusic\n" );
167                 return false;
168             }
169             if ( !subunit->discover() ) {
170                 debugError( "enumerateSubUnits: Could not discover "
171                             "subunit_id = %2d, subunit_type = %2d (%s)\n",
172                             subunitId,
173                             subunit_type,
174                             subunitTypeToString( subunit_type ) );
175                 delete subunit;
176                 return false;
177             } else {
178                 m_subunits.push_back( subunit );
179             }
180
181             break;
182         default:
183             debugOutput( DEBUG_LEVEL_NORMAL,
184                          "Unsupported subunit found, subunit_type = %d (%s)\n",
185                          subunit_type,
186                          subunitTypeToString( subunit_type ) );
187             continue;
188
189         }
190     }
191
192     return true;
193 }
194
195 Subunit*
196 Unit::getSubunit( subunit_type_t subunitType,
197                       subunit_id_t subunitId ) const
198 {
199     for ( SubunitVector::const_iterator it = m_subunits.begin();
200           it != m_subunits.end();
201           ++it )
202     {
203         Subunit* subunit = *it;
204         if ( ( subunitType == subunit->getSubunitType() )
205              && ( subunitId == subunit->getSubunitId() ) )
206         {
207             return subunit;
208         }
209     }
210
211     return 0;
212 }
213
214 unsigned int
215 Unit::getNrOfSubunits( subunit_type_t subunitType ) const
216 {
217     unsigned int nrOfSubunits = 0;
218
219     for ( SubunitVector::const_iterator it = m_subunits.begin();
220           it != m_subunits.end();
221           ++it )
222     {
223         Subunit* subunit = *it;
224         if ( subunitType == subunit->getSubunitType() ) {
225             nrOfSubunits++;
226         }
227     }
228
229     return nrOfSubunits;
230 }
231
232 PlugConnection*
233 Unit::getPlugConnection( Plug& srcPlug ) const
234 {
235     for ( PlugConnectionVector::const_iterator it
236               = m_plugConnections.begin();
237           it != m_plugConnections.end();
238           ++it )
239     {
240         PlugConnection* plugConnection = *it;
241         if ( &( plugConnection->getSrcPlug() ) == &srcPlug ) {
242             return plugConnection;
243         }
244     }
245
246     return 0;
247 }
248
249 Plug*
250 Unit::getPlugById( PlugVector& plugs,
251                        Plug::EPlugDirection plugDirection,
252                        int id )
253 {
254     for ( PlugVector::iterator it = plugs.begin();
255           it != plugs.end();
256           ++it )
257     {
258         Plug* plug = *it;
259         if ( ( id == plug->getPlugId() )
260              && ( plugDirection == plug->getPlugDirection() ) )
261         {
262             return plug;
263         }
264     }
265
266     return 0;
267 }
268
269 PlugVector
270 Unit::getPlugsByType( PlugVector& plugs,
271                           Plug::EPlugDirection plugDirection,
272                           Plug::EPlugType type)
273 {
274     PlugVector plugVector;
275     for ( PlugVector::iterator it = plugs.begin();
276           it != plugs.end();
277           ++it )
278     {
279         Plug* plug = *it;
280         if ( ( type == plug->getPlugType() )
281              && ( plugDirection == plug->getPlugDirection() ) )
282         {
283             plugVector.push_back( plug );
284         }
285     }
286
287     return plugVector;
288 }
289
290 Plug*
291 Unit::getSyncPlug( int maxPlugId, Plug::EPlugDirection )
292 {
293     return 0;
294 }
295
296 void
297 Unit::showDevice()
298 {
299     m_pPlugManager->showPlugs();
300 }
301
302 void
303 Unit::showPlugs( PlugVector& plugs ) const
304 {
305     int i = 0;
306     for ( PlugVector::const_iterator it = plugs.begin();
307           it != plugs.end();
308           ++it, ++i )
309     {
310         Plug* plug = *it;
311         debugOutput( DEBUG_LEVEL_VERBOSE, "Plug %d\n", i );
312         plug->showPlug();
313     }
314 }
315
316 template <typename T> bool serializeVector( Glib::ustring path,
317                                             Util::IOSerialize& ser,
318                                             const T& vec )
319 {
320     bool result = true; // if vec.size() == 0
321     int i = 0;
322     for ( typename T::const_iterator it = vec.begin(); it != vec.end(); ++it ) {
323         std::ostringstream strstrm;
324         strstrm << path << i;
325         result &= ( *it )->serialize( strstrm.str() + "/", ser );
326         i++;
327     }
328     return result;
329 }
330
331 template <typename T, typename VT> bool deserializeVector( Glib::ustring path,
332                                                            Util::IODeserialize& deser,
333                                                            Unit& avDevice,
334                                                            VT& vec )
335 {
336     int i = 0;
337     bool bFinished = false;
338     do {
339         std::ostringstream strstrm;
340         strstrm << path << i << "/";
341         T* ptr = T::deserialize( strstrm.str(),
342                                  deser,
343                                  avDevice );
344         if ( ptr ) {
345             vec.push_back( ptr );
346             i++;
347         } else {
348             bFinished = true;
349         }
350     } while ( !bFinished );
351
352     return true;
353 }
354
355 bool
356 Unit::serializeSyncInfoVector( Glib::ustring basePath,
357                                    Util::IOSerialize& ser,
358                                    const SyncInfoVector& vec )
359 {
360     bool result = true;
361     int i = 0;
362
363     for ( SyncInfoVector::const_iterator it = vec.begin();
364           it != vec.end();
365           ++it )
366     {
367         const SyncInfo& info = *it;
368
369         std::ostringstream strstrm;
370         strstrm << basePath << i << "/";
371
372         result &= ser.write( strstrm.str() + "m_source", info.m_source->getGlobalId() );
373         result &= ser.write( strstrm.str() + "m_destination", info.m_destination->getGlobalId() );
374         result &= ser.write( strstrm.str() + "m_description", Glib::ustring( info.m_description ) );
375
376         i++;
377     }
378
379     return result;
380 }
381
382 bool
383 Unit::deserializeSyncInfoVector( Glib::ustring basePath,
384                                      Util::IODeserialize& deser,
385                                      Unit& avDevice,
386                                      SyncInfoVector& vec )
387 {
388     int i = 0;
389     bool bFinished = false;
390     do {
391         bool result;
392         std::ostringstream strstrm;
393         strstrm << basePath << i << "/";
394
395         plug_id_t sourceId;
396         plug_id_t destinationId;
397         Glib::ustring description;
398
399         result  = deser.read( strstrm.str() + "m_source", sourceId );
400         result &= deser.read( strstrm.str() + "m_destination", destinationId );
401         result &= deser.read( strstrm.str() + "m_description", description );
402
403         if ( result ) {
404             SyncInfo syncInfo;
405             syncInfo.m_source = avDevice.getPlugManager().getPlug( sourceId );
406             syncInfo.m_destination = avDevice.getPlugManager().getPlug( destinationId );
407             syncInfo.m_description = description;
408
409             vec.push_back( syncInfo );
410             i++;
411         } else {
412             bFinished = true;
413         }
414     } while ( !bFinished );
415
416     return true;
417 }
418
419 static bool
420 deserializePlugUpdateConnections( Glib::ustring path,
421                                     Util::IODeserialize& deser,
422                                     PlugVector& vec )
423 {
424     bool result = true;
425     for ( PlugVector::iterator it = vec.begin();
426           it != vec.end();
427           ++it )
428     {
429         Plug* pPlug = *it;
430         result &= pPlug->deserializeUpdate( path, deser );
431     }
432     return result;
433 }
434
435 bool
436 Unit::serialize( Glib::ustring basePath,
437                      Util::IOSerialize& ser ) const
438 {
439
440     bool result;
441     result  = ser.write( basePath + "m_verboseLevel_unit", getDebugLevel() );
442     result &= m_pPlugManager->serialize( basePath + "Plug", ser ); // serialize all av plugs
443     result &= serializeVector( basePath + "PlugConnection", ser, m_plugConnections );
444     result &= serializeVector( basePath + "Subunit", ser, m_subunits );
445     result &= serializeSyncInfoVector( basePath + "SyncInfo", ser, m_syncInfos );
446
447     int i = 0;
448     for ( SyncInfoVector::const_iterator it = m_syncInfos.begin();
449           it != m_syncInfos.end();
450           ++it )
451     {
452         const SyncInfo& info = *it;
453         if ( m_activeSyncInfo == &info ) {
454             result &= ser.write( basePath + "m_activeSyncInfo",  i );
455             break;
456         }
457         i++;
458     }
459
460     return result;
461 }
462
463 bool
464 Unit::deserialize( Glib::ustring basePath,
465                    Unit* pDev,
466                    Util::IODeserialize& deser,
467                    Ieee1394Service& ieee1394Service )
468 {
469
470     if ( pDev ) {
471         bool result;
472        
473         int verboseLevel;
474         result  = deser.read( basePath + "m_verboseLevel_unit", verboseLevel );
475         setDebugLevel( verboseLevel );
476        
477         if (pDev->m_pPlugManager) delete pDev->m_pPlugManager;
478         pDev->m_pPlugManager = PlugManager::deserialize( basePath + "Plug", deser, *pDev );
479         if ( !pDev->m_pPlugManager ) {
480             delete pDev;
481             return 0;
482         }
483         result &= deserializePlugUpdateConnections( basePath + "Plug", deser, pDev->m_pcrPlugs );
484         result &= deserializePlugUpdateConnections( basePath + "Plug", deser, pDev->m_externalPlugs );
485         result &= deserializeVector<PlugConnection>( basePath + "PlugConnnection", deser, *pDev, pDev->m_plugConnections );
486         result &= deserializeVector<Subunit>( basePath + "Subunit",  deser, *pDev, pDev->m_subunits );
487         result &= deserializeSyncInfoVector( basePath + "SyncInfo", deser, *pDev, pDev->m_syncInfos );
488
489         unsigned int i;
490         result &= deser.read( basePath + "m_activeSyncInfo", i );
491
492         if ( result ) {
493             if ( i < pDev->m_syncInfos.size() ) {
494                 pDev->m_activeSyncInfo = &pDev->m_syncInfos[i];
495             }
496         }
497
498     }
499
500     return pDev;
501 }
502
503 } // end of namespace
Note: See TracBrowser for help on using the browser.