root/trunk/libffado/src/devicemanager.cpp

Revision 529, 13.6 kB (checked in by wagi, 15 years ago)

- saveCache and loadFromCache interface added to IAvDevice
- current implenetation of saveCache and loadFromCache moved to bebob
- config parser added for loading vendor and model ids from a file instead hardcoded (not finished yet)

  • 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
66 using namespace std;
67
68 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
69
70 DeviceManager::DeviceManager()
71     : OscNode("devicemanager")
72     , m_1394Service( 0 )
73     , m_oscServer( NULL )
74     , m_verboseLevel( DEBUG_LEVEL_NORMAL )
75 {
76     addOption(Util::OptionContainer::Option("slaveMode",false));
77     addOption(Util::OptionContainer::Option("snoopMode",false));
78 }
79
80 DeviceManager::~DeviceManager()
81 {
82     if (m_oscServer) {
83         m_oscServer->stop();
84         delete m_oscServer;
85     }
86
87     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
88           it != m_avDevices.end();
89           ++it )
90     {
91         delete *it;
92     }
93
94     delete m_1394Service;
95 }
96
97 void
98 DeviceManager::setVerboseLevel(int l)
99 {
100     m_verboseLevel=l;
101     setDebugLevel(l);
102
103     if (m_1394Service) m_1394Service->setVerboseLevel(l);
104     if (m_oscServer) m_oscServer->setVerboseLevel(l);
105     OscNode::setVerboseLevel(l);
106
107     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
108           it != m_avDevices.end();
109           ++it )
110     {
111         (*it)->setVerboseLevel(l);
112     }
113 }
114
115 bool
116 DeviceManager::initialize( int port )
117 {
118     m_1394Service = new Ieee1394Service();
119     if ( !m_1394Service ) {
120         debugFatal( "Could not create Ieee1349Service object\n" );
121         return false;
122     }
123
124     if ( !m_1394Service->initialize( port ) ) {
125         debugFatal( "Could not initialize Ieee1349Service object\n" );
126         delete m_1394Service;
127         m_1394Service = 0;
128         return false;
129     }
130
131     m_oscServer = new OSC::OscServer("17820");
132
133     if (!m_oscServer) {
134         debugFatal("failed to create osc server\n");
135         delete m_1394Service;
136         m_1394Service = 0;
137         return false;
138     }
139
140     if (!m_oscServer->init()) {
141         debugFatal("failed to init osc server\n");
142         delete m_oscServer;
143         m_oscServer = NULL;
144         delete m_1394Service;
145         m_1394Service = 0;
146         return false;
147     }
148
149     if (!m_oscServer->registerAtRootNode(this)) {
150         debugFatal("failed to register devicemanager at server\n");
151         delete m_oscServer;
152         m_oscServer = NULL;
153         delete m_1394Service;
154         m_1394Service = 0;
155         return false;
156     }
157
158     if (!m_oscServer->start()) {
159         debugFatal("failed to start osc server\n");
160         delete m_oscServer;
161         m_oscServer = NULL;
162         delete m_1394Service;
163         m_1394Service = 0;
164         return false;
165     }
166
167     setVerboseLevel(m_verboseLevel);
168     return true;
169 }
170
171 bool
172 DeviceManager::discover( )
173 {
174     bool slaveMode=false;
175     if(!getOption("slaveMode", slaveMode)) {
176         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
177     }
178     bool snoopMode=false;
179     if(!getOption("snoopMode", snoopMode)) {
180         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
181     }
182
183     setVerboseLevel(m_verboseLevel);
184
185     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
186           it != m_avDevices.end();
187           ++it )
188     {
189         if (!removeChildOscNode(*it)) {
190             debugWarning("failed to unregister AvDevice from OSC server\n");
191         }
192         delete *it;
193     }
194     m_avDevices.clear();
195
196     if (!slaveMode) {
197         for ( fb_nodeid_t nodeId = 0;
198               nodeId < m_1394Service->getNodeCount();
199               ++nodeId )
200         {
201             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
202
203             if (nodeId == m_1394Service->getLocalNodeId()) {
204                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
205                 continue;
206             }
207
208             std::auto_ptr<ConfigRom> configRom =
209                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
210                                                          nodeId ) );
211             if ( !configRom->initialize() ) {
212                 // \todo If a PHY on the bus is in power safe mode then
213                 // the config rom is missing. So this might be just
214                 // such this case and we can safely skip it. But it might
215                 // be there is a real software problem on our side.
216                 // This should be handlede more carefuly.
217                 debugOutput( DEBUG_LEVEL_NORMAL,
218                              "Could not read config rom from device (node id %d). "
219                              "Skip device discovering for this node\n",
220                              nodeId );
221                 continue;
222             }
223
224             IAvDevice*avDevice = getDriverForDevice( configRom, nodeId );
225             if ( avDevice ) {
226                 debugOutput( DEBUG_LEVEL_NORMAL,
227                              "driver found for device %d\n",
228                              nodeId );
229
230                 bool isFromCache = false;
231                 if ( avDevice->loadFromCache() ) {
232                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
233                     isFromCache = true;
234                 } else if ( avDevice->discover() ) {
235                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
236                     avDevice->setVerboseLevel( m_verboseLevel );
237                 } else {
238                     debugError( "could not discover device\n" );
239                     delete avDevice;
240                     continue;
241                 }
242
243                 if ( !avDevice->setId( m_avDevices.size() ) ) {
244                     debugError( "setting Id failed\n" );
245                 }
246
247                 if (snoopMode) {
248                     debugOutput( DEBUG_LEVEL_VERBOSE,
249                                  "Enabling snoop mode on node %d...\n", nodeId );
250
251                     if(!avDevice->setOption("snoopMode", snoopMode)) {
252                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
253                         delete avDevice;
254                         continue;
255                     }
256                 }
257
258                 if ( m_verboseLevel >= DEBUG_LEVEL_VERBOSE ) {
259                     avDevice->showDevice();
260                 }
261
262                 if ( !isFromCache && !avDevice->saveCache() ) {
263                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
264                 }
265
266                 m_avDevices.push_back( avDevice );
267
268                 if (!addChildOscNode(avDevice)) {
269                     debugWarning("failed to register AvDevice at OSC server\n");
270                 }
271
272             }
273         }
274         return true;
275
276     } else { // slave mode
277         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
278         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
279
280         std::auto_ptr<ConfigRom> configRom =
281             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
282                                                      nodeId ) );
283         if ( !configRom->initialize() ) {
284             // \todo If a PHY on the bus is in power safe mode then
285             // the config rom is missing. So this might be just
286             // such this case and we can safely skip it. But it might
287             // be there is a real software problem on our side.
288             // This should be handled more carefuly.
289             debugOutput( DEBUG_LEVEL_NORMAL,
290                          "Could not read config rom from device (node id %d). "
291                          "Skip device discovering for this node\n",
292                          nodeId );
293             return false;
294         }
295
296         IAvDevice* avDevice = getSlaveDriver( configRom );
297         if ( avDevice ) {
298             debugOutput( DEBUG_LEVEL_NORMAL,
299                          "driver found for device %d\n",
300                          nodeId );
301
302             avDevice->setVerboseLevel( m_verboseLevel );
303
304             if ( !avDevice->discover() ) {
305                 debugError( "could not discover device\n" );
306                 delete avDevice;
307                 return false;
308             }
309
310             if ( !avDevice->setId( m_avDevices.size() ) ) {
311                 debugError( "setting Id failed\n" );
312             }
313             if ( m_verboseLevel >= DEBUG_LEVEL_VERBOSE ) {
314                 avDevice->showDevice();
315             }
316
317             m_avDevices.push_back( avDevice );
318         }
319
320         return true;
321     }
322 }
323
324
325 IAvDevice*
326 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
327                                    int id )
328 {
329 #ifdef ENABLE_BEBOB
330     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
331     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
332         return new BeBoB::AvDevice( configRom, *m_1394Service, id );
333     }
334 #endif
335
336 #ifdef ENABLE_BEBOB
337     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
338     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
339         return new MAudio::AvDevice( configRom, *m_1394Service, id );
340     }
341 #endif
342
343 #ifdef ENABLE_MOTU
344     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
345     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
346         return new Motu::MotuDevice( configRom, *m_1394Service, id );
347     }
348 #endif
349
350 #ifdef ENABLE_DICE
351     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
352     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
353         return new Dice::DiceAvDevice( configRom, *m_1394Service, id );
354     }
355 #endif
356
357 #ifdef ENABLE_METRIC_HALO
358     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
359     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
360         return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id );
361     }
362 #endif
363
364 #ifdef ENABLE_RME
365     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
366     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
367         return new Rme::RmeDevice( configRom, *m_1394Service, id );
368     }
369 #endif
370
371 #ifdef ENABLE_BOUNCE
372     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
373     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
374         return new Bounce::BounceDevice( configRom, *m_1394Service, id );
375     }
376 #endif
377
378     return 0;
379 }
380
381 IAvDevice*
382 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
383 {
384
385 #ifdef ENABLE_BOUNCE
386     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
387         return new Bounce::BounceSlaveDevice( configRom, *m_1394Service );
388     }
389 #endif
390
391     return 0;
392 }
393
394 bool
395 DeviceManager::isValidNode(int node)
396 {
397     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
398           it != m_avDevices.end();
399           ++it )
400     {
401         IAvDevice* avDevice = *it;
402
403         if (avDevice->getConfigRom().getNodeId() == node) {
404             return true;
405     }
406     }
407     return false;
408 }
409
410 int
411 DeviceManager::getNbDevices()
412 {
413     return m_avDevices.size();
414 }
415
416 int
417 DeviceManager::getDeviceNodeId( int deviceNr )
418 {
419     if ( ! ( deviceNr < getNbDevices() ) ) {
420         debugError( "Device number out of range (%d)\n", deviceNr );
421         return -1;
422     }
423
424     IAvDevice* avDevice = m_avDevices.at( deviceNr );
425
426     if ( !avDevice ) {
427         debugError( "Could not get device at position (%d)\n",  deviceNr );
428     }
429
430     return avDevice->getConfigRom().getNodeId();
431 }
432
433 IAvDevice*
434 DeviceManager::getAvDevice( int nodeId )
435 {
436     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
437           it != m_avDevices.end();
438           ++it )
439     {
440         IAvDevice* avDevice = *it;
441         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
442             return avDevice;
443         }
444     }
445
446     return 0;
447 }
448
449 IAvDevice*
450 DeviceManager::getAvDeviceByIndex( int idx )
451 {
452     return m_avDevices.at(idx);
453 }
454
455 unsigned int
456 DeviceManager::getAvDeviceCount( )
457 {
458     return m_avDevices.size();
459 }
460
461 /**
462  * Return the streamprocessor that is to be used as
463  * the sync source.
464  *
465  * Algorithm still to be determined
466  *
467  * @return StreamProcessor that is sync source
468  */
469 Streaming::StreamProcessor *
470 DeviceManager::getSyncSource() {
471     IAvDevice* device = getAvDeviceByIndex(0);
472
473     bool slaveMode=false;
474     if(!getOption("slaveMode", slaveMode)) {
475         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
476     }
477
478     #warning TEST CODE FOR BOUNCE DEVICE !!
479     // this makes the bounce slave use the xmit SP as sync source
480     if (slaveMode) {
481         return device->getStreamProcessorByIndex(1);
482     } else {
483         return device->getStreamProcessorByIndex(0);
484     }
485 }
486
487 bool
488 DeviceManager::deinitialize()
489 {
490     return true;
491 }
Note: See TracBrowser for help on using the browser.