root/branches/ppalmers-streaming/src/devicemanager.cpp

Revision 705, 15.8 kB (checked in by ppalmers, 16 years ago)

restructure the streaming directory

  • 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/generic/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     // add the bus reset handler
168     m_busreset_functor = new MemberFunctor0< DeviceManager*,
169                 void (DeviceManager::*)() >
170                 ( this, &DeviceManager::busresetHandler, false );
171     m_1394Service->addBusResetHandler( m_busreset_functor );
172
173     setVerboseLevel(getDebugLevel());
174     return true;
175 }
176
177 void
178 DeviceManager::busresetHandler()
179 {
180     debugOutput( DEBUG_LEVEL_VERBOSE, "Bus reset...\n" );
181
182     // propagate the bus reset to all avDevices
183     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
184           it != m_avDevices.end();
185           ++it )
186     {
187         (*it)->handleBusReset();
188     }
189 }
190
191 bool
192 DeviceManager::discover( )
193 {
194     bool slaveMode=false;
195     if(!getOption("slaveMode", slaveMode)) {
196         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
197     }
198     bool snoopMode=false;
199     if(!getOption("snoopMode", snoopMode)) {
200         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
201     }
202
203     setVerboseLevel(getDebugLevel());
204
205     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
206           it != m_avDevices.end();
207           ++it )
208     {
209         if (!deleteElement(*it)) {
210             debugWarning("failed to remove AvDevice from Control::Container\n");
211         }
212         delete *it;
213     }
214     m_avDevices.clear();
215
216     if (!slaveMode) {
217         for ( fb_nodeid_t nodeId = 0;
218               nodeId < m_1394Service->getNodeCount();
219               ++nodeId )
220         {
221             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
222
223             if (nodeId == m_1394Service->getLocalNodeId()) {
224                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
225                 continue;
226             }
227
228             std::auto_ptr<ConfigRom> configRom =
229                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
230                                                          nodeId ) );
231             if ( !configRom->initialize() ) {
232                 // \todo If a PHY on the bus is in power safe mode then
233                 // the config rom is missing. So this might be just
234                 // such this case and we can safely skip it. But it might
235                 // be there is a real software problem on our side.
236                 // This should be handlede more carefuly.
237                 debugOutput( DEBUG_LEVEL_NORMAL,
238                              "Could not read config rom from device (node id %d). "
239                              "Skip device discovering for this node\n",
240                              nodeId );
241                 continue;
242             }
243
244             FFADODevice* avDevice = getDriverForDevice( configRom,
245                                                         nodeId );
246
247             if ( avDevice ) {
248                 debugOutput( DEBUG_LEVEL_NORMAL,
249                              "driver found for device %d\n",
250                              nodeId );
251
252                 avDevice->setVerboseLevel( getDebugLevel() );
253                 bool isFromCache = false;
254                 if ( avDevice->loadFromCache() ) {
255                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
256                     isFromCache = true;
257                 } else if ( avDevice->discover() ) {
258                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
259                 } else {
260                     debugError( "could not discover device\n" );
261                     delete avDevice;
262                     continue;
263                 }
264
265                 if (snoopMode) {
266                     debugOutput( DEBUG_LEVEL_VERBOSE,
267                                  "Enabling snoop mode on node %d...\n", nodeId );
268
269                     if(!avDevice->setOption("snoopMode", snoopMode)) {
270                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
271                         delete avDevice;
272                         continue;
273                     }
274                 }
275
276                 if ( !isFromCache && !avDevice->saveCache() ) {
277                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
278                 }
279
280                 m_avDevices.push_back( avDevice );
281
282                 if (!addElement(avDevice)) {
283                     debugWarning("failed to add AvDevice to Control::Container\n");
284                 }
285                
286                 debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
287
288             }
289         }
290
291         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
292
293         // sort the m_avDevices vector on their GUID
294         // then assign reassign the id's to the devices
295         // the side effect of this is that for the same set of attached devices,
296         // a device id always corresponds to the same device
297         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
298        
299         int i=0;
300         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
301             it != m_avDevices.end();
302             ++it )
303         {
304             if ( !(*it)->setId( i++ ) ) {
305                 debugError( "setting Id failed\n" );
306             }
307         }
308
309         show();
310         return true;
311
312     } else { // slave mode
313         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
314         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
315
316         std::auto_ptr<ConfigRom> configRom =
317             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
318                                                      nodeId ) );
319         if ( !configRom->initialize() ) {
320             // \todo If a PHY on the bus is in power safe mode then
321             // the config rom is missing. So this might be just
322             // such this case and we can safely skip it. But it might
323             // be there is a real software problem on our side.
324             // This should be handled more carefuly.
325             debugOutput( DEBUG_LEVEL_NORMAL,
326                          "Could not read config rom from device (node id %d). "
327                          "Skip device discovering for this node\n",
328                          nodeId );
329             return false;
330         }
331
332         FFADODevice* avDevice = getSlaveDriver( configRom );
333         if ( avDevice ) {
334             debugOutput( DEBUG_LEVEL_NORMAL,
335                          "driver found for device %d\n",
336                          nodeId );
337
338             avDevice->setVerboseLevel( getDebugLevel() );
339
340             if ( !avDevice->discover() ) {
341                 debugError( "could not discover device\n" );
342                 delete avDevice;
343                 return false;
344             }
345
346             if ( !avDevice->setId( m_avDevices.size() ) ) {
347                 debugError( "setting Id failed\n" );
348             }
349             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
350                 avDevice->showDevice();
351             }
352
353             m_avDevices.push_back( avDevice );
354
355             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
356         }
357
358         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
359
360         return true;
361     }
362 }
363
364 FFADODevice*
365 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
366                                    int id )
367 {
368 #ifdef ENABLE_BEBOB
369     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
370     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
371         return BeBoB::AvDevice::createDevice( *m_1394Service, configRom );
372     }
373 #endif
374
375 #ifdef ENABLE_GENERICAVC
376     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
377     if ( GenericAVC::AvDevice::probe( *configRom.get() ) ) {
378         return GenericAVC::AvDevice::createDevice( *m_1394Service, configRom );
379     }
380 #endif
381
382 #ifdef ENABLE_FIREWORKS
383     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
384     if ( FireWorks::Device::probe( *configRom.get() ) ) {
385         return FireWorks::Device::createDevice( *m_1394Service, configRom );
386     }
387 #endif
388
389 #ifdef ENABLE_BEBOB
390     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
391     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
392         return MAudio::AvDevice::createDevice( *m_1394Service, configRom );
393     }
394 #endif
395
396 #ifdef ENABLE_MOTU
397     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
398     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
399         return Motu::MotuDevice::createDevice( *m_1394Service, configRom );
400     }
401 #endif
402
403 #ifdef ENABLE_DICE
404     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
405     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
406         return Dice::DiceAvDevice::createDevice( *m_1394Service, configRom );
407     }
408 #endif
409
410 #ifdef ENABLE_METRIC_HALO
411     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
412     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
413         return MetricHalo::MHAvDevice::createDevice( *m_1394Service, configRom );
414     }
415 #endif
416
417 #ifdef ENABLE_RME
418     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
419     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
420         return Rme::RmeDevice::createDevice( *m_1394Service, configRom );
421     }
422 #endif
423
424 #ifdef ENABLE_BOUNCE
425     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
426     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
427         return Bounce::BounceDevice::createDevice( *m_1394Service, configRom );
428     }
429 #endif
430
431     return 0;
432 }
433
434 FFADODevice*
435 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
436 {
437
438 #ifdef ENABLE_BOUNCE
439     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
440         return Bounce::BounceSlaveDevice::createDevice( *m_1394Service, configRom );
441     }
442 #endif
443
444     return 0;
445 }
446
447 bool
448 DeviceManager::isValidNode(int node)
449 {
450     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
451           it != m_avDevices.end();
452           ++it )
453     {
454         FFADODevice* avDevice = *it;
455
456         if (avDevice->getConfigRom().getNodeId() == node) {
457             return true;
458     }
459     }
460     return false;
461 }
462
463 int
464 DeviceManager::getNbDevices()
465 {
466     return m_avDevices.size();
467 }
468
469 int
470 DeviceManager::getDeviceNodeId( int deviceNr )
471 {
472     if ( ! ( deviceNr < getNbDevices() ) ) {
473         debugError( "Device number out of range (%d)\n", deviceNr );
474         return -1;
475     }
476
477     FFADODevice* avDevice = m_avDevices.at( deviceNr );
478
479     if ( !avDevice ) {
480         debugError( "Could not get device at position (%d)\n",  deviceNr );
481     }
482
483     return avDevice->getConfigRom().getNodeId();
484 }
485
486 FFADODevice*
487 DeviceManager::getAvDevice( int nodeId )
488 {
489     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
490           it != m_avDevices.end();
491           ++it )
492     {
493         FFADODevice* avDevice = *it;
494         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
495             return avDevice;
496         }
497     }
498
499     return 0;
500 }
501
502 FFADODevice*
503 DeviceManager::getAvDeviceByIndex( int idx )
504 {
505     return m_avDevices.at(idx);
506 }
507
508 unsigned int
509 DeviceManager::getAvDeviceCount( )
510 {
511     return m_avDevices.size();
512 }
513
514 /**
515  * Return the streamprocessor that is to be used as
516  * the sync source.
517  *
518  * Algorithm still to be determined
519  *
520  * @return StreamProcessor that is sync source
521  */
522 Streaming::StreamProcessor *
523 DeviceManager::getSyncSource() {
524     FFADODevice* device = getAvDeviceByIndex(0);
525
526     bool slaveMode=false;
527     if(!getOption("slaveMode", slaveMode)) {
528         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
529     }
530
531     #warning TEST CODE FOR BOUNCE DEVICE !!
532     // this makes the bounce slave use the xmit SP as sync source
533     if (slaveMode) {
534         return device->getStreamProcessorByIndex(1);
535     } else {
536         return device->getStreamProcessorByIndex(0);
537     }
538 }
539
540 bool
541 DeviceManager::deinitialize()
542 {
543     return true;
544 }
Note: See TracBrowser for help on using the browser.