root/trunk/libffado/src/devicemanager.cpp

Revision 661, 15.2 kB (checked in by ppalmers, 15 years ago)

- Implement more complete mixer support for the saffire pro
- fix some cleanup issues with control elements

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