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

Revision 509, 13.9 kB (checked in by ppalmers, 17 years ago)

- Moved all generic stuff but the functionblocks over to libavc
- compiles and works

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