root/trunk/libffado/src/devicemanager.cpp

Revision 490, 17.0 kB (checked in by wagi, 14 years ago)

saveCache: create save path "PATH_TO_CACHE + GUID + CONFIGURATION_ID"

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