root/trunk/libffado/src/devicemanager.cpp

Revision 560, 15.3 kB (checked in by ppalmers, 15 years ago)

- Sort the FFADODevice vector on GUID before assigning device id's

This results in the same device id for identical device setups,
independent of the way they are connected or the node numbers they
have been assigned.

- Sanitized debug message reporting a bit
- Cosmetic changes

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