root/branches/libffado-scons_porting_work/src/devicemanager.cpp

Revision 527, 16.9 kB (checked in by arnonym, 15 years ago)

More on the installation. and the directory for the cache is now defined via config.h so adopt the devicemanager to it.

I think I have to look into libtool for the installation of libs...

And there should probably be a configure-check for the architecture, as I don't think that everybody needs the -fpic.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  * Copyright (C) 2005-2007 by Pieter Palmers
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 "config.h"
26
27 #include "fbtypes.h"
28
29 #include "devicemanager.h"
30 #include "iavdevice.h"
31
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
34
35 #include "libstreaming/StreamProcessor.h"
36
37 #include "debugmodule/debugmodule.h"
38
39 #ifdef ENABLE_BEBOB
40 #include "bebob/bebob_avdevice.h"
41 #include "maudio/maudio_avdevice.h"
42 #endif
43
44 #ifdef ENABLE_BOUNCE
45 #include "bounce/bounce_avdevice.h"
46 #include "bounce/bounce_slave_avdevice.h"
47 #endif
48
49 #ifdef ENABLE_MOTU
50 #include "motu/motu_avdevice.h"
51 #endif
52
53 #ifdef ENABLE_RME
54 #include "rme/rme_avdevice.h"
55 #endif
56
57 #ifdef ENABLE_DICE
58 #include "dice/dice_avdevice.h"
59 #endif
60
61 #ifdef ENABLE_METRIC_HALO
62 #include "metrichalo/mh_avdevice.h"
63 #endif
64
65 #include <iostream>
66 #include <sstream>
67 #include <unistd.h>
68 #include <sys/stat.h>
69
70 using namespace std;
71
72 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
73
74 DeviceManager::DeviceManager()
75     : OscNode("devicemanager")
76     , m_1394Service( 0 )
77     , m_oscServer( NULL )
78     , m_verboseLevel( DEBUG_LEVEL_NORMAL )
79 {
80     addOption(Util::OptionContainer::Option("slaveMode",false));
81     addOption(Util::OptionContainer::Option("snoopMode",false));
82 }
83
84 DeviceManager::~DeviceManager()
85 {
86     if (m_oscServer) {
87         m_oscServer->stop();
88         delete m_oscServer;
89     }
90
91     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
92           it != m_avDevices.end();
93           ++it )
94     {
95         delete *it;
96     }
97
98     delete m_1394Service;
99 }
100
101 void
102 DeviceManager::setVerboseLevel(int l)
103 {
104     m_verboseLevel=l;
105     setDebugLevel(l);
106
107     if (m_1394Service) m_1394Service->setVerboseLevel(l);
108     if (m_oscServer) m_oscServer->setVerboseLevel(l);
109     OscNode::setVerboseLevel(l);
110
111     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
112           it != m_avDevices.end();
113           ++it )
114     {
115         (*it)->setVerboseLevel(l);
116     }
117 }
118
119 bool
120 DeviceManager::initialize( int port )
121 {
122     m_1394Service = new Ieee1394Service();
123     if ( !m_1394Service ) {
124         debugFatal( "Could not create Ieee1349Service object\n" );
125         return false;
126     }
127
128     if ( !m_1394Service->initialize( port ) ) {
129         debugFatal( "Could not initialize Ieee1349Service object\n" );
130         delete m_1394Service;
131         m_1394Service = 0;
132         return false;
133     }
134
135     m_oscServer = new OSC::OscServer("17820");
136
137     if (!m_oscServer) {
138         debugFatal("failed to create osc server\n");
139         delete m_1394Service;
140         m_1394Service = 0;
141         return false;
142     }
143
144     if (!m_oscServer->init()) {
145         debugFatal("failed to init osc server\n");
146         delete m_oscServer;
147         m_oscServer = NULL;
148         delete m_1394Service;
149         m_1394Service = 0;
150         return false;
151     }
152
153     if (!m_oscServer->registerAtRootNode(this)) {
154         debugFatal("failed to register devicemanager at server\n");
155         delete m_oscServer;
156         m_oscServer = NULL;
157         delete m_1394Service;
158         m_1394Service = 0;
159         return false;
160     }
161
162     if (!m_oscServer->start()) {
163         debugFatal("failed to start osc server\n");
164         delete m_oscServer;
165         m_oscServer = NULL;
166         delete m_1394Service;
167         m_1394Service = 0;
168         return false;
169     }
170
171     setVerboseLevel(m_verboseLevel);
172     return true;
173 }
174
175 bool
176 DeviceManager::discover( )
177 {
178     bool slaveMode=false;
179     if(!getOption("slaveMode", slaveMode)) {
180         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
181     }
182     bool snoopMode=false;
183     if(!getOption("snoopMode", snoopMode)) {
184         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
185     }
186
187     setVerboseLevel(m_verboseLevel);
188
189     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
190           it != m_avDevices.end();
191           ++it )
192     {
193         if (!removeChildOscNode(*it)) {
194             debugWarning("failed to unregister AvDevice from OSC server\n");
195         }
196         delete *it;
197     }
198     m_avDevices.clear();
199
200     if (!slaveMode) {
201         for ( fb_nodeid_t nodeId = 0;
202               nodeId < m_1394Service->getNodeCount();
203               ++nodeId )
204         {
205             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
206
207             if (nodeId == m_1394Service->getLocalNodeId()) {
208                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
209                 continue;
210             }
211
212             std::auto_ptr<ConfigRom> configRom =
213                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
214                                                          nodeId ) );
215             if ( !configRom->initialize() ) {
216                 // \todo If a PHY on the bus is in power safe mode then
217                 // the config rom is missing. So this might be just
218                 // such this case and we can safely skip it. But it might
219                 // be there is a real software problem on our side.
220                 // This should be handlede more carefuly.
221                 debugOutput( DEBUG_LEVEL_NORMAL,
222                              "Could not read config rom from device (node id %d). "
223                              "Skip device discovering for this node\n",
224                              nodeId );
225                 continue;
226             }
227
228             bool isFromCache = false;
229             IAvDevice* avDevice = loadFromCache( *configRom );
230             if ( avDevice ) {
231                 debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
232                 isFromCache = true;
233             } else {
234                 avDevice = getDriverForDevice( configRom, nodeId );
235             }
236
237             if ( avDevice ) {
238                 debugOutput( DEBUG_LEVEL_NORMAL,
239                              "driver found for device %d\n",
240                              nodeId );
241
242                 avDevice->setVerboseLevel( m_verboseLevel );
243
244                 if ( !isFromCache ) {
245                     if ( !avDevice->discover() ) {
246                         debugError( "could not discover device\n" );
247                         delete avDevice;
248                         continue;
249                     }
250                 }
251
252                 if ( !avDevice->setId( m_avDevices.size() ) ) {
253                     debugError( "setting Id failed\n" );
254                 }
255
256                 if (snoopMode) {
257                     debugOutput( DEBUG_LEVEL_VERBOSE,
258                                  "Enabling snoop mode on node %d...\n", nodeId );
259
260                     if(!avDevice->setOption("snoopMode", snoopMode)) {
261                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
262                         delete avDevice;
263                         continue;
264                     }
265                 }
266
267                 if ( m_verboseLevel >= DEBUG_LEVEL_VERBOSE ) {
268                     avDevice->showDevice();
269                 }
270
271                 if ( !isFromCache ) {
272                     if ( !saveCache( avDevice ) ) {
273                         debugWarning( "Could not create cached version of AVC model\n" );
274                     }
275                 }
276
277                 m_avDevices.push_back( avDevice );
278
279                 if (!addChildOscNode(avDevice)) {
280                     debugWarning("failed to register AvDevice at OSC server\n");
281                 }
282
283             }
284         }
285         return true;
286
287     } else { // slave mode
288         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
289         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
290
291         std::auto_ptr<ConfigRom> configRom =
292             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
293                                                      nodeId ) );
294         if ( !configRom->initialize() ) {
295             // \todo If a PHY on the bus is in power safe mode then
296             // the config rom is missing. So this might be just
297             // such this case and we can safely skip it. But it might
298             // be there is a real software problem on our side.
299             // This should be handled more carefuly.
300             debugOutput( DEBUG_LEVEL_NORMAL,
301                          "Could not read config rom from device (node id %d). "
302                          "Skip device discovering for this node\n",
303                          nodeId );
304             return false;
305         }
306
307         IAvDevice* avDevice = getSlaveDriver( configRom );
308         if ( avDevice ) {
309             debugOutput( DEBUG_LEVEL_NORMAL,
310                          "driver found for device %d\n",
311                          nodeId );
312
313             avDevice->setVerboseLevel( m_verboseLevel );
314
315             if ( !avDevice->discover() ) {
316                 debugError( "could not discover device\n" );
317                 delete avDevice;
318                 return false;
319             }
320
321             if ( !avDevice->setId( m_avDevices.size() ) ) {
322                 debugError( "setting Id failed\n" );
323             }
324             if ( m_verboseLevel >= DEBUG_LEVEL_VERBOSE ) {
325                 avDevice->showDevice();
326             }
327
328             m_avDevices.push_back( avDevice );
329         }
330
331         return true;
332     }
333 }
334
335
336 IAvDevice*
337 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
338                                    int id )
339 {
340 #ifdef ENABLE_BEBOB
341     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
342     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
343         return new BeBoB::AvDevice( configRom, *m_1394Service, id );
344     }
345 #endif
346
347 #ifdef ENABLE_BEBOB
348     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
349     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
350         return new MAudio::AvDevice( configRom, *m_1394Service, id );
351     }
352 #endif
353
354 #ifdef ENABLE_MOTU
355     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
356     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
357         return new Motu::MotuDevice( configRom, *m_1394Service, id );
358     }
359 #endif
360
361 #ifdef ENABLE_DICE
362     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
363     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
364         return new Dice::DiceAvDevice( configRom, *m_1394Service, id );
365     }
366 #endif
367
368 #ifdef ENABLE_METRIC_HALO
369     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
370     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
371         return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id );
372     }
373 #endif
374
375 #ifdef ENABLE_RME
376     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
377     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
378         return new Rme::RmeDevice( configRom, *m_1394Service, id );
379     }
380 #endif
381
382 #ifdef ENABLE_BOUNCE
383     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
384     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
385         return new Bounce::BounceDevice( configRom, *m_1394Service, id );
386     }
387 #endif
388
389     return 0;
390 }
391
392 IAvDevice*
393 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
394 {
395
396 #ifdef ENABLE_BOUNCE
397     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
398         return new Bounce::BounceSlaveDevice( configRom, *m_1394Service );
399     }
400 #endif
401
402     return 0;
403 }
404
405 bool
406 DeviceManager::isValidNode(int node)
407 {
408     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
409           it != m_avDevices.end();
410           ++it )
411     {
412         IAvDevice* avDevice = *it;
413
414         if (avDevice->getConfigRom().getNodeId() == node) {
415             return true;
416     }
417     }
418     return false;
419 }
420
421 int
422 DeviceManager::getNbDevices()
423 {
424     return m_avDevices.size();
425 }
426
427 int
428 DeviceManager::getDeviceNodeId( int deviceNr )
429 {
430     if ( ! ( deviceNr < getNbDevices() ) ) {
431         debugError( "Device number out of range (%d)\n", deviceNr );
432         return -1;
433     }
434
435     IAvDevice* avDevice = m_avDevices.at( deviceNr );
436
437     if ( !avDevice ) {
438         debugError( "Could not get device at position (%d)\n",  deviceNr );
439     }
440
441     return avDevice->getConfigRom().getNodeId();
442 }
443
444 IAvDevice*
445 DeviceManager::getAvDevice( int nodeId )
446 {
447     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
448           it != m_avDevices.end();
449           ++it )
450     {
451         IAvDevice* avDevice = *it;
452         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
453             return avDevice;
454         }
455     }
456
457     return 0;
458 }
459
460 IAvDevice*
461 DeviceManager::getAvDeviceByIndex( int idx )
462 {
463     return m_avDevices.at(idx);
464 }
465
466 unsigned int
467 DeviceManager::getAvDeviceCount( )
468 {
469     return m_avDevices.size();
470 }
471
472 /**
473  * Return the streamprocessor that is to be used as
474  * the sync source.
475  *
476  * Algorithm still to be determined
477  *
478  * @return StreamProcessor that is sync source
479  */
480 Streaming::StreamProcessor *
481 DeviceManager::getSyncSource() {
482     IAvDevice* device = getAvDeviceByIndex(0);
483
484     bool slaveMode=false;
485     if(!getOption("slaveMode", slaveMode)) {
486         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
487     }
488
489     #warning TEST CODE FOR BOUNCE DEVICE !!
490     // this makes the bounce slave use the xmit SP as sync source
491     if (slaveMode) {
492         return device->getStreamProcessorByIndex(1);
493     } else {
494         return device->getStreamProcessorByIndex(0);
495     }
496 }
497
498 bool
499 DeviceManager::deinitialize()
500 {
501     return true;
502 }
503
504 bool
505 DeviceManager::buildCache()
506 {
507     bool result = true;
508     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
509           it != m_avDevices.end();
510           ++it )
511     {
512         IAvDevice* pAvDevice = *it;
513         result &= saveCache( pAvDevice );
514     }
515
516     return result;
517 }
518
519 Glib::ustring
520 DeviceManager::getCachePath()
521 {
522     Glib::ustring cachePath;
523     char* pCachePath;
524     if ( asprintf( &pCachePath, "%s/libffado/",  CACHEDIR ) < 0 ) {
525         debugError( "Could not create path string for cache pool (trying '/var/cache/libffado' instead)\n" );
526         cachePath == "/var/cache/libffado/";
527     } else {
528         cachePath = pCachePath;
529         free( pCachePath );
530     }
531     return cachePath;
532 }
533
534 bool
535 DeviceManager::saveCache( IAvDevice* pAvDevice )
536 {
537     // so far only BeBoB based devices needed a cache for speed up.
538     BeBoB::AvDevice* pBeBoBDevice = reinterpret_cast<BeBoB::AvDevice*>( pAvDevice );
539     if ( !pBeBoBDevice ) {
540         return true;
541     }
542
543     // the path looks like this:
544     // PATH_TO_CACHE + GUID + CONFIGURATION_ID
545
546     Glib::ustring sDevicePath = getCachePath() + pAvDevice->getConfigRom().getGuidString();
547     struct stat buf;
548     if ( stat( sDevicePath.c_str(), &buf ) == 0 ) {
549         if ( !S_ISDIR( buf.st_mode ) ) {
550             debugError( "\"%s\" is not a directory\n",  sDevicePath.c_str() );
551             return false;
552         }
553     } else {
554         if (  mkdir( sDevicePath.c_str(), S_IRWXU | S_IRWXG ) != 0 ) {
555             debugError( "Could not create \"%s\" directory\n", sDevicePath.c_str() );
556             return false;
557         }
558     }
559
560     char* configId;
561     asprintf(&configId, "%08x", BeBoB::AvDevice::getConfigurationId( *m_1394Service,
562                                                                      pAvDevice->getNodeId() ) );
563     if ( !configId ) {
564         debugError( "Could not create id string\n" );
565         return false;
566     }
567     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
568     free( configId );
569     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
570
571     Util::XMLSerialize ser( sFileName );
572     return pBeBoBDevice->serialize( "", ser );
573 }
574
575 IAvDevice*
576 DeviceManager::loadFromCache( const ConfigRom& configRom )
577 {
578     Glib::ustring sDevicePath = getCachePath() + configRom.getGuidString();
579     char* configId;
580     asprintf(&configId, "%08x",
581     BeBoB::AvDevice::getConfigurationId(*m_1394Service,
582     configRom.getNodeId()) );
583     if ( !configId ) {
584         debugError( "could not create id string\n" );
585         return false;
586     }
587     Glib::ustring sFileName = sDevicePath + "/" + configId + ".xml";
588     free( configId );
589     debugOutput( DEBUG_LEVEL_NORMAL, "filename %s\n", sFileName.c_str() );
590
591     Util::XMLDeserialize deser( sFileName, m_verboseLevel );
592
593     BeBoB::AvDevice* pBeBoBDevice = BeBoB::AvDevice::deserialize( "",
594                                                                   deser,
595                                                                   *m_1394Service );
596     if ( pBeBoBDevice ) {
597         debugOutput( DEBUG_LEVEL_NORMAL, "could create valid bebob driver from %s\n", sFileName.c_str() );
598         pBeBoBDevice->getConfigRom().setNodeId( configRom.getNodeId() );
599     }
600
601     return pBeBoBDevice;
602 }
603
Note: See TracBrowser for help on using the browser.