root/branches/streaming-rework/src/devicemanager.cpp

Revision 426, 18.0 kB (checked in by pieterpalmers, 17 years ago)

- changed the IAvDevice from an interface to a base class,

since there is some code duplication starting to
appear.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1  /* devicemanager.cpp
2  * Copyright (C) 2005,06,07 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "fbtypes.h"
22
23 #include "devicemanager.h"
24 #include "iavdevice.h"
25
26 #include "libieee1394/configrom.h"
27 #include "libieee1394/ieee1394service.h"
28
29 #include "debugmodule/debugmodule.h"
30
31 #include <iostream>
32 #include <sstream>
33
34 #include <unistd.h>
35
36 #include "libstreaming/StreamProcessor.h"
37
38 #ifdef ENABLE_BEBOB
39     #include "bebob/bebob_avdevice.h"
40     #include "maudio/maudio_avdevice.h"
41 #endif
42
43 #ifdef ENABLE_BOUNCE
44     #include "bounce/bounce_avdevice.h"
45     #include "bounce/bounce_slave_avdevice.h"
46 #endif
47
48 #ifdef ENABLE_MOTU
49 #include "motu/motu_avdevice.h"
50 #endif
51
52 #ifdef ENABLE_RME
53 #include "rme/rme_avdevice.h"
54 #endif
55
56 #ifdef ENABLE_DICE
57 #include "dice/dice_avdevice.h"
58 #endif
59
60 #ifdef ENABLE_METRIC_HALO
61 #include "metrichalo/mh_avdevice.h"
62 #endif
63
64 using namespace std;
65
66 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
67
68 DeviceManager::DeviceManager()
69     : m_1394Service( 0 )
70 {
71     addOption(Util::OptionContainer::Option("slaveMode",false));
72     addOption(Util::OptionContainer::Option("snoopMode",false));
73 }
74
75 DeviceManager::~DeviceManager()
76 {
77     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
78           it != m_avDevices.end();
79           ++it )
80     {
81         delete *it;
82     }
83
84     delete m_1394Service;
85 }
86
87 bool
88 DeviceManager::initialize( int port )
89 {
90     m_1394Service = new Ieee1394Service();
91     if ( !m_1394Service ) {
92         debugFatal( "Could not create Ieee1349Service object\n" );
93         return false;
94     }
95
96     if ( !m_1394Service->initialize( port ) ) {
97         debugFatal( "Could not initialize Ieee1349Service object\n" );
98         delete m_1394Service;
99         m_1394Service = 0;
100         return false;
101     }
102
103     return true;
104 }
105
106 bool
107 DeviceManager::discover( int verboseLevel )
108 {
109     bool slaveMode=false;
110     if(!getOption("slaveMode", slaveMode)) {
111         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
112     }
113     bool snoopMode=false;
114     if(!getOption("snoopMode", snoopMode)) {
115         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
116     }
117
118     setDebugLevel( verboseLevel );
119     m_1394Service->setVerbose( verboseLevel );
120
121     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
122           it != m_avDevices.end();
123           ++it )
124     {
125         delete *it;
126     }
127     m_avDevices.clear();
128
129     if (!slaveMode) {
130         for ( fb_nodeid_t nodeId = 0;
131               nodeId < m_1394Service->getNodeCount();
132               ++nodeId )
133         {
134             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
135    
136             if (nodeId == m_1394Service->getLocalNodeId()) {
137                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
138                 continue;
139             }
140    
141             std::auto_ptr<ConfigRom> configRom =
142                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
143                                                          nodeId ) );
144             if ( !configRom->initialize() ) {
145                 // \todo If a PHY on the bus is in power safe mode then
146                 // the config rom is missing. So this might be just
147                 // such this case and we can safely skip it. But it might
148                 // be there is a real software problem on our side.
149                 // This should be handled more carefuly.
150                 debugOutput( DEBUG_LEVEL_NORMAL,
151                              "Could not read config rom from device (node id %d). "
152                              "Skip device discovering for this node\n",
153                              nodeId );
154                 continue;
155             }
156    
157             IAvDevice* avDevice = getDriverForDevice( configRom,
158                                                       nodeId );
159             if ( avDevice ) {
160                 debugOutput( DEBUG_LEVEL_NORMAL,
161                              "discover: driver found for device %d\n",
162                              nodeId );
163
164                 avDevice->setVerboseLevel( verboseLevel );
165                
166                 if ( !avDevice->discover() ) {
167                     debugError( "discover: could not discover device\n" );
168                     delete avDevice;
169                     continue;
170                 }
171
172                 if ( !avDevice->setId( m_avDevices.size() ) ) {
173                     debugError( "setting Id failed\n" );
174                 }
175                
176                 if (snoopMode) {
177                     debugOutput( DEBUG_LEVEL_VERBOSE,
178                                  "Enabling snoop mode on node %d...\n", nodeId );
179
180                     if(!avDevice->setOption("snoopMode", snoopMode)) {
181                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
182                         delete avDevice;
183                         continue;
184                     }
185                 }
186                
187                 if ( verboseLevel ) {
188                     avDevice->showDevice();
189                 }
190
191                 m_avDevices.push_back( avDevice );
192             }
193         }
194         return true;
195        
196     } else { // slave mode
197         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
198         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
199
200         std::auto_ptr<ConfigRom> configRom =
201             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
202                                                      nodeId ) );
203         if ( !configRom->initialize() ) {
204             // \todo If a PHY on the bus is in power safe mode then
205             // the config rom is missing. So this might be just
206             // such this case and we can safely skip it. But it might
207             // be there is a real software problem on our side.
208             // This should be handled more carefuly.
209             debugOutput( DEBUG_LEVEL_NORMAL,
210                          "Could not read config rom from device (node id %d). "
211                          "Skip device discovering for this node\n",
212                          nodeId );
213             return false;
214         }
215
216         IAvDevice* avDevice = getSlaveDriver( configRom );
217         if ( avDevice ) {
218             debugOutput( DEBUG_LEVEL_NORMAL,
219                          "discover: driver found for device %d\n",
220                          nodeId );
221            
222             avDevice->setVerboseLevel( verboseLevel );
223
224             if ( !avDevice->discover() ) {
225                 debugError( "discover: could not discover device\n" );
226                 delete avDevice;
227                 return false;
228             }
229
230             if ( !avDevice->setId( m_avDevices.size() ) ) {
231                 debugError( "setting Id failed\n" );
232             }
233             if ( verboseLevel ) {
234                 avDevice->showDevice();
235             }
236            
237
238             m_avDevices.push_back( avDevice );
239         }
240    
241         return true;
242     }
243 }
244
245
246 IAvDevice*
247 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
248                                    int id )
249 {
250 #ifdef ENABLE_BEBOB
251     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
252     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
253         return new BeBoB::AvDevice( configRom, *m_1394Service, id );
254     }
255 #endif
256
257 #ifdef ENABLE_BEBOB
258     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
259     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
260         return new MAudio::AvDevice( configRom, *m_1394Service, id );
261     }
262 #endif
263
264 #ifdef ENABLE_MOTU
265     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
266     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
267         return new Motu::MotuDevice( configRom, *m_1394Service, id );
268     }
269 #endif
270
271 #ifdef ENABLE_DICE
272     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
273     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
274         return new Dice::DiceAvDevice( configRom, *m_1394Service, id );
275     }
276 #endif
277
278 #ifdef ENABLE_METRIC_HALO
279     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
280     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
281         return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id );
282     }
283 #endif
284
285 #ifdef ENABLE_RME
286     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
287     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
288         return new Rme::RmeDevice( configRom, *m_1394Service, id );
289     }
290 #endif
291
292 #ifdef ENABLE_BOUNCE
293     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
294     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
295         return new Bounce::BounceDevice( configRom, *m_1394Service, id );
296     }
297 #endif
298
299     return 0;
300 }
301
302 IAvDevice*
303 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
304 {
305
306 #ifdef ENABLE_BOUNCE
307     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
308         return new Bounce::BounceSlaveDevice( configRom, *m_1394Service );
309     }
310 #endif
311
312     return 0;
313 }
314
315 bool
316 DeviceManager::isValidNode(int node)
317 {
318     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
319           it != m_avDevices.end();
320           ++it )
321     {
322         IAvDevice* avDevice = *it;
323
324         if (avDevice->getConfigRom().getNodeId() == node) {
325                 return true;
326         }
327     }
328     return false;
329 }
330
331 int
332 DeviceManager::getNbDevices()
333 {
334     return m_avDevices.size();
335 }
336
337 int
338 DeviceManager::getDeviceNodeId( int deviceNr )
339 {
340     if ( ! ( deviceNr < getNbDevices() ) ) {
341         debugError( "Device number out of range (%d)\n", deviceNr );
342         return -1;
343     }
344
345     IAvDevice* avDevice = m_avDevices.at( deviceNr );
346
347     if ( !avDevice ) {
348         debugError( "Could not get device at position (%d)\n",  deviceNr );
349     }
350
351     return avDevice->getConfigRom().getNodeId();
352 }
353
354 IAvDevice*
355 DeviceManager::getAvDevice( int nodeId )
356 {
357     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
358           it != m_avDevices.end();
359           ++it )
360     {
361         IAvDevice* avDevice = *it;
362         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
363             return avDevice;
364         }
365     }
366
367     return 0;
368 }
369
370 IAvDevice*
371 DeviceManager::getAvDeviceByIndex( int idx )
372 {
373         return m_avDevices.at(idx);
374 }
375
376 unsigned int
377 DeviceManager::getAvDeviceCount( )
378 {
379         return m_avDevices.size();
380 }
381
382 /**
383  * Return the streamprocessor that is to be used as
384  * the sync source.
385  *
386  * Algorithm still to be determined
387  *
388  * @return StreamProcessor that is sync source
389  */
390 Streaming::StreamProcessor *
391 DeviceManager::getSyncSource() {
392     IAvDevice* device = getAvDeviceByIndex(0);
393
394     bool slaveMode=false;
395     if(!getOption("slaveMode", slaveMode)) {
396         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
397     }
398    
399     #warning TEST CODE FOR BOUNCE DEVICE !!
400     // this makes the bounce slave use the xmit SP as sync source
401     if (slaveMode) {
402         return device->getStreamProcessorByIndex(1);
403     } else {
404         return device->getStreamProcessorByIndex(0);
405     }
406    
407 }
408
409 xmlDocPtr
410 DeviceManager::getXmlDescription()
411 {
412     xmlDocPtr doc = xmlNewDoc( BAD_CAST "1.0" );
413     if ( !doc ) {
414         debugError( "Couldn't create new xml doc\n" );
415         return 0;
416     }
417
418     xmlNodePtr rootNode = xmlNewNode( 0,  BAD_CAST "FreeBoBConnectionInfo" );
419     if ( !rootNode ) {
420         debugError( "Couldn't create root node\n" );
421         xmlFreeDoc( doc );
422         xmlCleanupParser();
423         return 0;
424     }
425     xmlDocSetRootElement( doc, rootNode );
426
427     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
428           it != m_avDevices.end();
429           ++it )
430     {
431         IAvDevice* avDevice = *it;
432
433         xmlNodePtr deviceNode = xmlNewChild( rootNode, 0,
434                                              BAD_CAST "Device", 0 );
435         if ( !deviceNode ) {
436             debugError( "Couldn't create device node\n" );
437             xmlFreeDoc( doc );
438             xmlCleanupParser();
439             return 0;
440         }
441
442         char* result;
443         asprintf( &result, "%d", avDevice->getConfigRom().getNodeId() );
444         if ( !xmlNewChild( deviceNode,  0,
445                            BAD_CAST "NodeId",  BAD_CAST result ) )
446         {
447             debugError( "Couldn't create 'NodeId' node" );
448             free(result);
449             return 0;
450         }
451         free( result );
452
453         std::string res = "Connection Information for "
454                           + avDevice->getConfigRom().getVendorName()
455                           +", "
456                           + avDevice->getConfigRom().getModelName()
457                           + " configuration";
458         if ( !xmlNewChild( deviceNode,
459                            0,
460                            BAD_CAST "Comment",
461                            BAD_CAST res.c_str() ) ) {
462             debugError( "Couldn't create comment node\n" );
463             xmlFreeDoc( doc );
464             xmlCleanupParser();
465             free(result);
466             return 0;
467         }
468
469         res = avDevice->getConfigRom().getVendorName();
470
471         if ( !xmlNewChild( deviceNode,
472                            0,
473                            BAD_CAST "Vendor",
474                            BAD_CAST res.c_str() ) ) {
475             debugError( "Couldn't create vendor node\n" );
476             xmlFreeDoc( doc );
477             xmlCleanupParser();
478             free(result);
479             return 0;
480         }
481
482         res = avDevice->getConfigRom().getModelName();
483
484         if ( !xmlNewChild( deviceNode,
485                            0,
486                            BAD_CAST "Model",
487                            BAD_CAST res.c_str() ) ) {
488             debugError( "Couldn't create model node\n" );
489             xmlFreeDoc( doc );
490             xmlCleanupParser();
491             free(result);
492             return 0;
493         }
494
495         asprintf( &result, "%08x%08x",
496                   ( quadlet_t )( avDevice->getConfigRom().getGuid() >> 32 ),
497                   ( quadlet_t )( avDevice->getConfigRom().getGuid() & 0xfffffff ) );
498         if ( !xmlNewChild( deviceNode,  0,
499                            BAD_CAST "GUID",  BAD_CAST result ) ) {
500             debugError( "Couldn't create 'GUID' node\n" );
501             xmlFreeDoc( doc );
502             xmlCleanupParser();
503
504             free(result);
505             return 0;
506         }
507         free( result );
508
509
510         if ( !avDevice->addXmlDescription( deviceNode ) ) {
511             debugError( "Adding XML description failed\n" );
512             xmlFreeDoc( doc );
513             xmlCleanupParser();
514             free(result);
515             return 0;
516         }
517
518     }
519
520     return doc;
521 }
522
523 bool
524 DeviceManager::deinitialize()
525 {
526     return true;
527 }
528
529 bool
530 DeviceManager::saveCache( Glib::ustring fileName )
531 {
532     int i;
533     i=0; // avoids unused warning
534    
535     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
536           it != m_avDevices.end();
537           ++it )
538     {
539         IAvDevice* pAvDevice;
540         pAvDevice = *it; // avoids unused warning
541        
542         #ifdef ENABLE_BEBOB
543         BeBoB::AvDevice* pBeBoBDevice = reinterpret_cast< BeBoB::AvDevice* >( pAvDevice );
544         if ( pBeBoBDevice ) {
545             // Let's use a very simple path to find the devices later.
546             // Since under hood there will an xml node name this should
547             // adhere the needed naming rules. Of course we could give it
548             // a good node name and add an attribute but that would mean
549             // we have to expose a bigger interface from IOSerialize/IODesialize,
550             // which is just not needed. KISS.
551             ostringstream strstrm;
552             strstrm << "id" << i;
553             Glib::ustring basePath = "BeBoB/" + strstrm.str() + "/";
554
555             Util::XMLSerialize ser( fileName );
556             pBeBoBDevice->serialize( basePath, ser );
557
558             i++;
559             std::cout << "a bebob device serialized" << std::endl;
560         }
561         #endif
562     }
563     return true;
564 }
565
566 bool
567 DeviceManager::loadCache( Glib::ustring fileName )
568 {
569     int i;
570     i=0; // avoids unused warning
571     Util::XMLDeserialize deser( fileName );
572
573     typedef std::vector<ConfigRom*> ConfigRomVector;
574     ConfigRomVector configRoms;
575
576     for ( fb_nodeid_t nodeId = 0;
577           nodeId < m_1394Service->getNodeCount();
578           ++nodeId )
579     {
580         ConfigRom* pConfigRom  =  new ConfigRom( *m_1394Service, nodeId );
581         if ( !pConfigRom->initialize() ) {
582             // \todo If a PHY on the bus is in power safe mode then
583             // the config rom is missing. So this might be just
584             // such this case and we can safely skip it. But it might
585             // be there is a real software problem on our side.
586             // This should be handled more carefuly.
587             debugOutput( DEBUG_LEVEL_NORMAL,
588                          "Could not read config rom from device (node id %d). "
589                          "Skip device discovering for this node\n",
590                          nodeId );
591             delete pConfigRom;
592             continue;
593         }
594         configRoms.push_back( pConfigRom );
595     }
596
597     #ifdef ENABLE_BEBOB
598     BeBoB::AvDevice* pBeBoBDevice = 0;
599     do {
600         ostringstream strstrm;
601         strstrm << "id" << i;
602         pBeBoBDevice = BeBoB::AvDevice::deserialize(
603             "BeBoB/" + strstrm.str() + "/",
604             deser,
605             *m_1394Service );
606
607         ++i;
608         if ( pBeBoBDevice ) {
609             for (ConfigRomVector::iterator it = configRoms.begin();
610                  it != configRoms.end();
611                  ++it )
612             {
613                 ConfigRom* pConfigRom = *it;
614
615                 if ( pBeBoBDevice->getConfigRom() == *pConfigRom ) {
616                     pBeBoBDevice->getConfigRom().setNodeId( pConfigRom->getNodeId() );
617                     // m_avDevices.push_back( pBeBoBDevice );
618
619                 }
620             }
621         }
622     } while ( pBeBoBDevice );
623     #endif
624    
625     return true;
626 }
Note: See TracBrowser for help on using the browser.