root/trunk/libffado/src/devicemanager.cpp

Revision 581, 14.2 kB (checked in by ppalmers, 15 years ago)

- First attempt at mixer control (still disfunctional)
- moved vendor specific code in bebob/*

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