root/trunk/libffado/src/devicemanager.cpp

Revision 1498, 39.0 kB (checked in by ppalmers, 15 years ago)

Merge all changes from 2.0 branch into trunk (since r1361). This _should_ contain all forward merges done in the mean time. At this moment in time both branches should be in sync.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) version 3 of the License.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  */
24
25 #include "config.h"
26 #include "fbtypes.h"
27
28 #include "devicemanager.h"
29 #include "ffadodevice.h"
30 #include "DeviceStringParser.h"
31
32 #include "libieee1394/configrom.h"
33 #include "libieee1394/ieee1394service.h"
34 #include "libieee1394/IsoHandlerManager.h"
35
36 #include "libstreaming/generic/StreamProcessor.h"
37 #include "libstreaming/StreamProcessorManager.h"
38
39 #include "debugmodule/debugmodule.h"
40
41 #include "libutil/PosixMutex.h"
42
43 #ifdef ENABLE_BEBOB
44 #include "bebob/bebob_avdevice.h"
45 #include "maudio/maudio_avdevice.h"
46 #endif
47
48 #ifdef ENABLE_GENERICAVC
49     #include "genericavc/avc_avdevice.h"
50 #endif
51
52 #ifdef ENABLE_FIREWORKS
53     #include "fireworks/fireworks_device.h"
54 #endif
55
56 #ifdef ENABLE_BOUNCE
57 #include "bounce/bounce_avdevice.h"
58 #include "bounce/bounce_slave_avdevice.h"
59 #endif
60
61 #ifdef ENABLE_MOTU
62 #include "motu/motu_avdevice.h"
63 #endif
64
65 #ifdef ENABLE_RME
66 #include "rme/rme_avdevice.h"
67 #endif
68
69 #ifdef ENABLE_DICE
70 #include "dice/dice_avdevice.h"
71 #endif
72
73 #ifdef ENABLE_METRIC_HALO
74 #include "metrichalo/mh_avdevice.h"
75 #endif
76
77 #include <iostream>
78 #include <sstream>
79
80 #include <algorithm>
81
82 using namespace std;
83
84 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
85
86 DeviceManager::DeviceManager()
87     : Control::Container(NULL, "devicemanager") // this is the control root node
88     , m_DeviceListLock( new Util::PosixMutex("DEVLST") )
89     , m_BusResetLock( new Util::PosixMutex("DEVBR") )
90     , m_processorManager( new Streaming::StreamProcessorManager( *this ) )
91     , m_deviceStringParser( new DeviceStringParser() )
92     , m_configuration ( new Util::Configuration() )
93     , m_used_cache_last_time( false )
94     , m_thread_realtime( false )
95     , m_thread_priority( 0 )
96 {
97     addOption(Util::OptionContainer::Option("slaveMode",false));
98     addOption(Util::OptionContainer::Option("snoopMode",false));
99 }
100
101 DeviceManager::~DeviceManager()
102 {
103     // save configuration
104     if(!m_configuration->save()) {
105         debugWarning("could not save configuration\n");
106     }
107
108     m_BusResetLock->Lock(); // make sure we are not handling a busreset.
109     m_DeviceListLock->Lock(); // make sure nobody is using this
110     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
111           it != m_avDevices.end();
112           ++it )
113     {
114         if (!deleteElement(*it)) {
115             debugWarning("failed to remove AvDevice from Control::Container\n");
116         }
117         delete *it;
118     }
119     m_DeviceListLock->Unlock();
120
121     // the SP's are automatically unregistered from the SPM
122     delete m_processorManager;
123
124     // the device list is empty, so wake up any waiting
125     // reset handlers
126     m_BusResetLock->Unlock();
127
128     // remove the bus-reset handlers
129     for ( FunctorVectorIterator it = m_busreset_functors.begin();
130           it != m_busreset_functors.end();
131           ++it )
132     {
133         delete *it;
134     }
135
136     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
137           it != m_1394Services.end();
138           ++it )
139     {
140         delete *it;
141     }
142
143     delete m_DeviceListLock;
144     delete m_BusResetLock;
145     delete m_deviceStringParser;
146 }
147
148 bool
149 DeviceManager::setThreadParameters(bool rt, int priority) {
150     if (!m_processorManager->setThreadParameters(rt, priority)) {
151         debugError("Could not set processor manager thread parameters\n");
152         return false;
153     }
154     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
155           it != m_1394Services.end();
156           ++it )
157     {
158         if (!(*it)->setThreadParameters(rt, priority)) {
159             debugError("Could not set 1394 service thread parameters\n");
160             return false;
161         }
162     }
163     m_thread_realtime = rt;
164     m_thread_priority = priority;
165     return true;
166 }
167
168 bool
169 DeviceManager::initialize()
170 {
171     assert(m_1394Services.size() == 0);
172     assert(m_busreset_functors.size() == 0);
173
174     m_configuration->openFile( "temporary", Util::Configuration::eFM_Temporary );
175     m_configuration->openFile( USER_CONFIG_FILE, Util::Configuration::eFM_ReadWrite );
176     m_configuration->openFile( SYSTEM_CONFIG_FILE, Util::Configuration::eFM_ReadOnly );
177
178     int nb_detected_ports = Ieee1394Service::detectNbPorts();
179     if (nb_detected_ports < 0) {
180         debugFatal("Failed to detect the number of 1394 adapters. Is the IEEE1394 stack loaded (raw1394)?\n");
181         return false;
182     }
183     if (nb_detected_ports == 0) {
184         debugFatal("No firewire adapters (ports) found.\n");
185         return false;
186     }
187     debugOutput( DEBUG_LEVEL_VERBOSE, "Found %d firewire adapters (ports)\n", nb_detected_ports);
188     for (unsigned int port = 0; port < (unsigned int)nb_detected_ports; port++) {
189         Ieee1394Service* tmp1394Service = new Ieee1394Service();
190         if ( !tmp1394Service ) {
191             debugFatal( "Could not create Ieee1349Service object for port %d\n", port );
192             return false;
193         }
194         tmp1394Service->setVerboseLevel( getDebugLevel() );
195         m_1394Services.push_back(tmp1394Service);
196
197         if(!tmp1394Service->useConfiguration(m_configuration)) {
198             debugWarning("Could not load config to 1394service\n");
199         }
200
201         tmp1394Service->setThreadParameters(m_thread_realtime, m_thread_priority);
202         if ( !tmp1394Service->initialize( port ) ) {
203             debugFatal( "Could not initialize Ieee1349Service object for port %d\n", port );
204             return false;
205         }
206         // add the bus reset handler
207         Util::Functor* tmp_busreset_functor = new Util::MemberFunctor1< DeviceManager*,
208                     void (DeviceManager::*)(Ieee1394Service &), Ieee1394Service & >
209                     ( this, &DeviceManager::busresetHandler, *tmp1394Service, false );
210         if ( !tmp_busreset_functor ) {
211             debugFatal( "Could not create busreset handler for port %d\n", port );
212             return false;
213         }
214         m_busreset_functors.push_back(tmp_busreset_functor);
215
216         tmp1394Service->addBusResetHandler( tmp_busreset_functor );
217     }
218
219     return true;
220 }
221
222 bool
223 DeviceManager::addSpecString(char *s) {
224     std::string spec = s;
225     if(isSpecStringValid(spec)) {
226         debugOutput(DEBUG_LEVEL_VERBOSE, "Adding spec string %s\n", spec.c_str());
227         assert(m_deviceStringParser);
228         m_deviceStringParser->parseString(spec);
229         return true;
230     } else {
231         debugError("Invalid spec string: %s\n", spec.c_str());
232         return false;
233     }
234 }
235
236 bool
237 DeviceManager::isSpecStringValid(std::string s) {
238     assert(m_deviceStringParser);
239     return m_deviceStringParser->isValidString(s);
240 }
241
242 void
243 DeviceManager::busresetHandler(Ieee1394Service &service)
244 {
245     // serialize bus reset handling since it can be that a new one occurs while we're
246     // doing stuff.
247     debugOutput( DEBUG_LEVEL_NORMAL, "Bus reset detected on service %p...\n", &service );
248     Util::MutexLockHelper lock(*m_BusResetLock);
249     debugOutput( DEBUG_LEVEL_NORMAL, " handling busreset...\n" );
250
251     // FIXME: what if the devices are gone? (device should detect this!)
252     // propagate the bus reset to all avDevices
253     m_DeviceListLock->Lock(); // make sure nobody is using this
254     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
255           it != m_avDevices.end();
256           ++it )
257     {
258         if(&service == &((*it)->get1394Service())) {
259             debugOutput(DEBUG_LEVEL_NORMAL,
260                         "issue busreset on device GUID %s\n",
261                         (*it)->getConfigRom().getGuidString().c_str());
262             (*it)->handleBusReset();
263         } else {
264             debugOutput(DEBUG_LEVEL_NORMAL,
265                         "skipping device GUID %s since not on service %p\n",
266                         (*it)->getConfigRom().getGuidString().c_str(), &service);
267         }
268     }
269     m_DeviceListLock->Unlock();
270
271     // now that the devices have been updates, we can request to update the iso streams
272     if(!service.getIsoHandlerManager().handleBusReset()) {
273         debugError("IsoHandlerManager failed to handle busreset\n");
274     }
275
276     // notify the streamprocessormanager of the busreset
277 //     if(m_processorManager) {
278 //         m_processorManager->handleBusReset(service);
279 //     } else {
280 //         debugWarning("No valid SPM\n");
281 //     }
282
283     // rediscover to find new devices
284     // (only for the control server ATM, streaming can't dynamically add/remove devices)
285     if(!discover(m_used_cache_last_time, true)) {
286         debugError("Could not rediscover devices\n");
287     }
288
289     // notify any clients
290     signalNotifiers(m_busResetNotifiers);
291
292     // display the new state
293     if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
294         showDeviceInfo();
295     }
296 }
297
298 void
299 DeviceManager::signalNotifiers(notif_vec_t& list)
300 {
301     for ( notif_vec_t::iterator it = list.begin();
302           it != list.end();
303           ++it )
304     {
305         Util::Functor* func = *it;
306         debugOutput( DEBUG_LEVEL_VERBOSE, " running notifier %p...\n", func );
307         ( *func )();
308     }
309 }
310
311 bool
312 DeviceManager::registerNotification(notif_vec_t& list, Util::Functor *handler)
313 {
314     debugOutput( DEBUG_LEVEL_VERBOSE, "register %p...\n", handler);
315     assert(handler);
316     for ( notif_vec_t::iterator it = list.begin();
317       it != list.end();
318       ++it )
319     {
320         if ( *it == handler ) {
321             debugOutput(DEBUG_LEVEL_VERBOSE, "already registered\n");
322             return false;
323         }
324     }
325     list.push_back(handler);
326     return true;
327 }
328
329 bool
330 DeviceManager::unregisterNotification(notif_vec_t& list, Util::Functor *handler)
331 {
332     debugOutput( DEBUG_LEVEL_VERBOSE, "unregister %p...\n", handler);
333     assert(handler);
334
335     for ( notif_vec_t::iterator it = list.begin();
336       it != list.end();
337       ++it )
338     {
339         if ( *it == handler ) {
340             list.erase(it);
341             return true;
342         }
343     }
344     debugError("Could not find handler (%p)\n", handler);
345     return false; //not found
346 }
347
348 bool
349 DeviceManager::discover( bool useCache, bool rediscover )
350 {
351     debugOutput( DEBUG_LEVEL_NORMAL, "Starting discovery...\n" );
352     useCache = useCache && ENABLE_DISCOVERY_CACHE;
353     m_used_cache_last_time = useCache;
354     bool slaveMode=false;
355     if(!getOption("slaveMode", slaveMode)) {
356         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
357     }
358     bool snoopMode=false;
359     if(!getOption("snoopMode", snoopMode)) {
360         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
361     }
362
363     setVerboseLevel(getDebugLevel());
364
365     // FIXME: it could be that a 1394service has disappeared (cardbus)
366
367     ConfigRomVector configRoms;
368     // build a list of configroms on the bus.
369     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
370         it != m_1394Services.end();
371         ++it )
372     {
373         Ieee1394Service *portService = *it;
374         for ( fb_nodeid_t nodeId = 0;
375             nodeId < portService->getNodeCount();
376             ++nodeId )
377         {
378             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
379
380             if (nodeId == portService->getLocalNodeId()) {
381                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
382                 continue;
383             }
384
385             ConfigRom * configRom = new ConfigRom( *portService, nodeId );
386             if ( !configRom->initialize() ) {
387                 // \todo If a PHY on the bus is in power safe mode then
388                 // the config rom is missing. So this might be just
389                 // such this case and we can safely skip it. But it might
390                 // be there is a real software problem on our side.
391                 // This should be handlede more carefuly.
392                 debugOutput( DEBUG_LEVEL_NORMAL,
393                             "Could not read config rom from device (node id %d). "
394                             "Skip device discovering for this node\n",
395                             nodeId );
396                 continue;
397             }
398             configRoms.push_back(configRom);
399         }
400     }
401
402
403     // notify that we are going to manipulate the list
404     signalNotifiers(m_preUpdateNotifiers);
405     m_DeviceListLock->Lock(); // make sure nobody starts using the list
406     if(rediscover) {
407
408         FFADODeviceVector discovered_devices_on_bus;
409         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
410             it != m_avDevices.end();
411             ++it )
412         {
413             bool seen_device = false;
414             for ( ConfigRomVectorIterator it2 = configRoms.begin();
415                 it2 != configRoms.end();
416                 ++it2 )
417             {
418                 seen_device |= ((*it)->getConfigRom().getGuid() == (*it2)->getGuid());
419             }
420
421             if(seen_device) {
422                 debugOutput( DEBUG_LEVEL_VERBOSE,
423                             "Already discovered device with GUID: %s\n",
424                             (*it)->getConfigRom().getGuidString().c_str() );
425                 // we already discovered this device, and it is still here. keep it
426                 discovered_devices_on_bus.push_back(*it);
427             } else {
428                 debugOutput( DEBUG_LEVEL_VERBOSE,
429                             "Device with GUID: %s disappeared from bus, removing...\n",
430                             (*it)->getConfigRom().getGuidString().c_str() );
431
432                 // the device has disappeared, remove it from the control tree
433                 if (!deleteElement(*it)) {
434                     debugWarning("failed to remove AvDevice from Control::Container\n");
435                 }
436                 // delete the device
437                 // FIXME: this will mess up the any code that waits for bus resets to
438                 //        occur
439                 delete *it;
440             }
441         }
442         // prune the devices that disappeared
443         m_avDevices = discovered_devices_on_bus;
444     } else { // remove everything since we are not rediscovering
445         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
446             it != m_avDevices.end();
447             ++it )
448         {
449             if (!deleteElement(*it)) {
450                 debugWarning("failed to remove AvDevice from Control::Container\n");
451             }
452             delete *it;
453         }
454
455         m_avDevices.clear();
456     }
457
458     // delete the config rom list entries
459     // FIXME: we should reuse it
460     for ( ConfigRomVectorIterator it = configRoms.begin();
461         it != configRoms.end();
462         ++it )
463     {
464         delete *it;
465     }
466
467     assert(m_deviceStringParser);
468     // show the spec strings we're going to use
469     if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
470         m_deviceStringParser->show();
471     }
472
473     if (!slaveMode) {
474         // for the devices that are still in the list check if they require re-discovery
475         FFADODeviceVector failed_to_rediscover;
476         for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin();
477             it_dev != m_avDevices.end();
478             ++it_dev )
479         {
480             FFADODevice* avDevice = *it_dev;
481             if(avDevice->needsRediscovery()) {
482                 debugOutput( DEBUG_LEVEL_NORMAL,
483                              "Device with GUID %s requires rediscovery (state changed)...\n",
484                              avDevice->getConfigRom().getGuidString().c_str());
485
486                 bool isFromCache = false;
487                 if ( useCache && avDevice->loadFromCache() ) {
488                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
489                     isFromCache = true;
490                     // restore the debug level for everything that was loaded
491                     avDevice->setVerboseLevel( getDebugLevel() );
492                 } else if ( avDevice->discover() ) {
493                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" );
494                 } else {
495                     debugError( "could not discover device\n" );
496                     failed_to_rediscover.push_back(avDevice);
497                     continue;
498                 }
499                 if ( !isFromCache && !avDevice->saveCache() ) {
500                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
501                 }
502             } else {
503                 debugOutput( DEBUG_LEVEL_NORMAL,
504                              "Device with GUID %s does not require rediscovery...\n",
505                              avDevice->getConfigRom().getGuidString().c_str());
506             }
507         }
508         // remove devices that failed to rediscover
509         // FIXME: surely there has to be a better way to do this
510         FFADODeviceVector to_keep;
511         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
512             it != m_avDevices.end();
513             ++it )
514         {
515             bool keep_this_device = true;
516             for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin();
517                 it2 != failed_to_rediscover.end();
518                 ++it2 )
519             {
520                 if(*it == *it2) {
521                     debugOutput( DEBUG_LEVEL_NORMAL,
522                                 "Removing device with GUID %s due to failed discovery...\n",
523                                 (*it)->getConfigRom().getGuidString().c_str());
524                     keep_this_device = false;
525                     break;
526                 }
527             }
528             if(keep_this_device) {
529                 to_keep.push_back(*it);
530             }
531         }
532         for ( FFADODeviceVectorIterator it2 = failed_to_rediscover.begin();
533             it2 != failed_to_rediscover.end();
534             ++it2 )
535         {
536             if (!deleteElement(*it2)) {
537                 debugWarning("failed to remove AvDevice from Control::Container\n");
538             }
539             delete *it2;
540         }
541         m_avDevices = to_keep;
542
543         // pick up new devices
544         for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
545             it != m_1394Services.end();
546             ++it )
547         {
548             Ieee1394Service *portService = *it;
549             for ( fb_nodeid_t nodeId = 0;
550                 nodeId < portService->getNodeCount();
551                 ++nodeId )
552             {
553                 debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
554    
555                 if (nodeId == portService->getLocalNodeId()) {
556                     debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
557                     continue;
558                 }
559    
560                 ConfigRom *configRom = new ConfigRom( *portService, nodeId );
561                 if ( !configRom->initialize() ) {
562                     // \todo If a PHY on the bus is in power safe mode then
563                     // the config rom is missing. So this might be just
564                     // such this case and we can safely skip it. But it might
565                     // be there is a real software problem on our side.
566                     // This should be handlede more carefuly.
567                     debugOutput( DEBUG_LEVEL_NORMAL,
568                                 "Could not read config rom from device (node id %d). "
569                                 "Skip device discovering for this node\n",
570                                 nodeId );
571                     continue;
572                 }
573
574                 bool already_in_vector = false;
575                 for ( FFADODeviceVectorIterator it_dev = m_avDevices.begin();
576                     it_dev != m_avDevices.end();
577                     ++it_dev )
578                 {
579                     if ((*it_dev)->getConfigRom().getGuid() == configRom->getGuid()) {
580                         already_in_vector = true;
581                         break;
582                     }
583                 }
584                 if(already_in_vector) {
585                     if(!rediscover) {
586                         debugWarning("Device with GUID %s already discovered on other port, skipping device...\n",
587                                     configRom->getGuidString().c_str());
588                     }
589                     continue;
590                 }
591
592                 if(getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
593                     configRom->printConfigRomDebug();
594                 }
595
596                 // if spec strings are given, only add those devices
597                 // that match the spec string(s).
598                 // if no (valid) spec strings are present, grab all
599                 // supported devices.
600                 if(m_deviceStringParser->countDeviceStrings() &&
601                   !m_deviceStringParser->match(*configRom)) {
602                     debugOutput(DEBUG_LEVEL_VERBOSE, "Device doesn't match any of the spec strings. skipping...\n");
603                     continue;
604                 }
605
606                 // find a driver
607                 FFADODevice* avDevice = getDriverForDevice( configRom,
608                                                             nodeId );
609
610                 if ( avDevice ) {
611                     debugOutput( DEBUG_LEVEL_NORMAL,
612                                 "driver found for device %d\n",
613                                 nodeId );
614
615                     avDevice->setVerboseLevel( getDebugLevel() );
616                     bool isFromCache = false;
617                     if ( useCache && avDevice->loadFromCache() ) {
618                         debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
619                         isFromCache = true;
620                         // restore the debug level for everything that was loaded
621                         avDevice->setVerboseLevel( getDebugLevel() );
622                     } else if ( avDevice->discover() ) {
623                         debugOutput( DEBUG_LEVEL_VERBOSE, "discovery successful\n" );
624                     } else {
625                         debugError( "could not discover device\n" );
626                         delete avDevice;
627                         continue;
628                     }
629
630                     if (snoopMode) {
631                         debugOutput( DEBUG_LEVEL_VERBOSE,
632                                     "Enabling snoop mode on node %d...\n", nodeId );
633
634                         if(!avDevice->setOption("snoopMode", snoopMode)) {
635                             debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
636                             delete avDevice;
637                             continue;
638                         }
639                     }
640
641                     if ( !isFromCache && !avDevice->saveCache() ) {
642                         debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
643                     }
644                     m_avDevices.push_back( avDevice );
645
646                     if (!addElement(avDevice)) {
647                         debugWarning("failed to add AvDevice to Control::Container\n");
648                     }
649
650                     debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
651                 } else {
652                     // we didn't get a device, hence we have to delete the configrom ptr manually
653                     delete configRom;
654                 }
655             }
656         }
657
658         debugOutput( DEBUG_LEVEL_NORMAL, "Discovery finished...\n" );
659         // FIXME: do better sorting
660         // sort the m_avDevices vector on their GUID
661         // then assign reassign the id's to the devices
662         // the side effect of this is that for the same set of attached devices,
663         // a device id always corresponds to the same device
664         sort(m_avDevices.begin(), m_avDevices.end(), FFADODevice::compareGUID);
665         int i=0;
666         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
667             it != m_avDevices.end();
668             ++it )
669         {
670             if ( !(*it)->setId( i++ ) ) {
671                 debugError( "setting Id failed\n" );
672             }
673         }
674         showDeviceInfo();
675
676     } else { // slave mode
677         // notify any clients
678         signalNotifiers(m_preUpdateNotifiers);
679         Ieee1394Service *portService = m_1394Services.at(0);
680         fb_nodeid_t nodeId = portService->getLocalNodeId();
681         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
682
683         std::auto_ptr<ConfigRom> configRom =
684             std::auto_ptr<ConfigRom>( new ConfigRom( *portService,
685                                                      nodeId ) );
686         if ( !configRom->initialize() ) {
687             // \todo If a PHY on the bus is in power safe mode then
688             // the config rom is missing. So this might be just
689             // such this case and we can safely skip it. But it might
690             // be there is a real software problem on our side.
691             // This should be handled more carefuly.
692             debugOutput( DEBUG_LEVEL_NORMAL,
693                          "Could not read config rom from device (node id %d). "
694                          "Skip device discovering for this node\n",
695                          nodeId );
696             return false;
697         }
698
699         // remove any already present devices
700         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
701             it != m_avDevices.end();
702             ++it )
703         {
704             if (!deleteElement(*it)) {
705                 debugWarning("failed to remove AvDevice from Control::Container\n");
706             }
707             delete *it;
708         }
709
710         m_avDevices.clear();
711
712         // get the slave driver
713         FFADODevice* avDevice = getSlaveDriver( configRom );
714         if ( avDevice ) {
715             debugOutput( DEBUG_LEVEL_NORMAL,
716                          "driver found for device %d\n",
717                          nodeId );
718
719             avDevice->setVerboseLevel( getDebugLevel() );
720
721             if ( !avDevice->discover() ) {
722                 debugError( "could not discover device\n" );
723                 delete avDevice;
724                 return false;
725             }
726
727             if ( !avDevice->setId( m_avDevices.size() ) ) {
728                 debugError( "setting Id failed\n" );
729             }
730             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
731                 avDevice->showDevice();
732             }
733             m_avDevices.push_back( avDevice );
734             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
735         }
736
737         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
738     }
739
740     m_DeviceListLock->Unlock();
741     // notify any clients
742     signalNotifiers(m_postUpdateNotifiers);
743     return true;
744 }
745
746 bool
747 DeviceManager::initStreaming()
748 {
749     // iterate over the found devices
750     // add the stream processors of the devices to the managers
751     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
752         it != m_avDevices.end();
753         ++it )
754     {
755         FFADODevice *device = *it;
756         assert(device);
757
758         debugOutput(DEBUG_LEVEL_VERBOSE, "Locking device (%p)\n", device);
759
760         if (!device->lock()) {
761             debugWarning("Could not lock device, skipping device (%p)!\n", device);
762             continue;
763         }
764
765         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting samplerate to %d for (%p)\n",
766                     m_processorManager->getNominalRate(), device);
767
768         // Set the device's sampling rate to that requested
769         // FIXME: does this really belong here?  If so we need to handle errors.
770         if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
771             debugOutput(DEBUG_LEVEL_VERBOSE, " => Retry setting samplerate to %d for (%p)\n",
772                         m_processorManager->getNominalRate(), device);
773
774             // try again:
775             if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
776                 debugFatal("Could not set sampling frequency to %d\n",m_processorManager->getNominalRate());
777                 return false;
778             }
779         }
780         // prepare the device
781         device->prepare();
782     }
783
784     // set the sync source
785     if (!m_processorManager->setSyncSource(getSyncSource())) {
786         debugWarning("Could not set processorManager sync source (%p)\n",
787             getSyncSource());
788     }
789
790     return true;
791 }
792
793 bool
794 DeviceManager::prepareStreaming()
795 {
796     if (!m_processorManager->prepare()) {
797         debugFatal("Could not prepare streaming...\n");
798         return false;
799     }
800     return true;
801 }
802
803 bool
804 DeviceManager::finishStreaming() {
805     bool result = true;
806     // iterate over the found devices
807     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
808         it != m_avDevices.end();
809         ++it )
810     {
811         debugOutput(DEBUG_LEVEL_VERBOSE, "Unlocking device (%p)\n", *it);
812
813         if (!(*it)->unlock()) {
814             debugWarning("Could not unlock device (%p)!\n", *it);
815             result = false;
816         }
817     }
818     return result;
819 }
820
821 bool
822 DeviceManager::startStreaming() {
823     // create the connections for all devices
824     // iterate over the found devices
825     // add the stream processors of the devices to the managers
826     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
827         it != m_avDevices.end();
828         ++it )
829     {
830         FFADODevice *device = *it;
831         assert(device);
832
833         int j=0;
834         for(j=0; j < device->getStreamCount(); j++) {
835         debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %p\n", j, device);
836             // start the stream
837             if (!device->startStreamByIndex(j)) {
838                 debugWarning("Could not start stream %d of device %p\n", j, device);
839                 continue;
840             }
841         }
842
843         if (!device->enableStreaming()) {
844             debugWarning("Could not enable streaming on device %p!\n", device);
845         }
846     }
847
848     if(m_processorManager->start()) {
849         return true;
850     } else {
851         stopStreaming();
852         return false;
853     }
854 }
855
856 bool
857 DeviceManager::resetStreaming() {
858     return true;
859 }
860
861 bool
862 DeviceManager::stopStreaming()
863 {
864     bool result = true;
865     m_processorManager->stop();
866
867     // create the connections for all devices
868     // iterate over the found devices
869     // add the stream processors of the devices to the managers
870     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
871         it != m_avDevices.end();
872         ++it )
873     {
874         FFADODevice *device = *it;
875         assert(device);
876
877         if (!device->disableStreaming()) {
878             debugWarning("Could not disable streaming on device %p!\n", device);
879         }
880
881         int j=0;
882         for(j=0; j < device->getStreamCount(); j++) {
883             debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %p\n", j, device);
884             // stop the stream
885             // start the stream
886             if (!device->stopStreamByIndex(j)) {
887                 debugWarning("Could not stop stream %d of device %p\n", j, device);
888                 result = false;
889                 continue;
890             }
891         }
892     }
893     return result;
894 }
895
896 enum DeviceManager::eWaitResult
897 DeviceManager::waitForPeriod() {
898     if(m_processorManager->waitForPeriod()) {
899         return eWR_OK;
900     } else {
901         if(m_processorManager->shutdownNeeded()) {
902             debugWarning("Shutdown requested\n");
903             return eWR_Shutdown;
904         } else {
905             debugWarning("XRUN detected\n");
906             // do xrun recovery
907             if(m_processorManager->handleXrun()) {
908                 return eWR_Xrun;
909             } else {
910                 debugError("Could not handle XRUN\n");
911                 return eWR_Error;
912             }
913         }
914     }
915 }
916
917 bool
918 DeviceManager::setStreamingParams(unsigned int period, unsigned int rate, unsigned int nb_buffers) {
919     m_processorManager->setPeriodSize(period);
920     m_processorManager->setNominalRate(rate);
921     m_processorManager->setNbBuffers(nb_buffers);
922     return true;
923 }
924
925 FFADODevice*
926 DeviceManager::getDriverForDeviceDo( ConfigRom *configRom,
927                                    int id, bool generic )
928 {
929 #ifdef ENABLE_BEBOB
930     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
931     if ( BeBoB::AvDevice::probe( getConfiguration(), *configRom, generic ) ) {
932         return BeBoB::AvDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
933     }
934 #endif
935
936 #ifdef ENABLE_FIREWORKS
937     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
938     if ( FireWorks::Device::probe( getConfiguration(), *configRom, generic ) ) {
939         return FireWorks::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
940     }
941 #endif
942
943 // we want to try the non-generic AV/C platforms before trying the generic ones
944 #ifdef ENABLE_GENERICAVC
945     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
946     if ( GenericAVC::AvDevice::probe( getConfiguration(), *configRom, generic ) ) {
947         return GenericAVC::AvDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
948     }
949 #endif
950
951 #ifdef ENABLE_MOTU
952     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
953     if ( Motu::MotuDevice::probe( getConfiguration(), *configRom, generic ) ) {
954         return Motu::MotuDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
955     }
956 #endif
957
958 #ifdef ENABLE_DICE
959     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
960     if ( Dice::DiceAvDevice::probe( *configRom, generic ) ) {
961         return Dice::DiceAvDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
962     }
963 #endif
964
965 #ifdef ENABLE_METRIC_HALO
966     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
967     if ( MetricHalo::MHAvDevice::probe( *configRom, generic ) ) {
968         return MetricHalo::MHAvDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
969     }
970 #endif
971
972 #ifdef ENABLE_RME
973     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
974     if ( Rme::RmeDevice::probe( *configRom, generic ) ) {
975         return Rme::RmeDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
976     }
977 #endif
978
979 #ifdef ENABLE_BOUNCE
980     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
981     if ( Bounce::BounceDevice::probe( *configRom, generic ) ) {
982         return Bounce::BounceDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
983     }
984 #endif
985
986     return NULL;
987 }
988
989 FFADODevice*
990 DeviceManager::getDriverForDevice( ConfigRom *configRom,
991                                    int id )
992 {
993     debugOutput( DEBUG_LEVEL_VERBOSE, "Probing for supported device...\n" );
994     FFADODevice* dev = getDriverForDeviceDo(configRom, id, false);
995     if(dev) {
996         debugOutput( DEBUG_LEVEL_VERBOSE, " found supported device...\n" );
997         return dev;
998     }
999
1000     debugOutput( DEBUG_LEVEL_VERBOSE, " no supported device found, trying generic support...\n" );
1001     dev = getDriverForDeviceDo(configRom, id, true);
1002     if(dev) {
1003         debugOutput( DEBUG_LEVEL_VERBOSE, " found generic support for device...\n" );
1004         return dev;
1005     }
1006     debugOutput( DEBUG_LEVEL_VERBOSE, " device not supported...\n" );
1007     return 0;
1008 }
1009
1010 FFADODevice*
1011 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
1012 {
1013
1014 #ifdef ENABLE_BOUNCE
1015     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
1016         return Bounce::BounceSlaveDevice::createDevice( configRom );
1017     }
1018 #endif
1019
1020     return 0;
1021 }
1022
1023 bool
1024 DeviceManager::isValidNode(int node)
1025 {
1026     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1027           it != m_avDevices.end();
1028           ++it )
1029     {
1030         FFADODevice* avDevice = *it;
1031
1032         if (avDevice->getConfigRom().getNodeId() == node) {
1033             return true;
1034     }
1035     }
1036     return false;
1037 }
1038
1039 int
1040 DeviceManager::getNbDevices()
1041 {
1042     return m_avDevices.size();
1043 }
1044
1045 int
1046 DeviceManager::getDeviceNodeId( int deviceNr )
1047 {
1048     if ( ! ( deviceNr < getNbDevices() ) ) {
1049         debugError( "Device number out of range (%d)\n", deviceNr );
1050         return -1;
1051     }
1052
1053     FFADODevice* avDevice = m_avDevices.at( deviceNr );
1054
1055     if ( !avDevice ) {
1056         debugError( "Could not get device at position (%d)\n",  deviceNr );
1057     }
1058
1059     return avDevice->getConfigRom().getNodeId();
1060 }
1061
1062 FFADODevice*
1063 DeviceManager::getAvDevice( int nodeId )
1064 {
1065     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1066           it != m_avDevices.end();
1067           ++it )
1068     {
1069         FFADODevice* avDevice = *it;
1070         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
1071             return avDevice;
1072         }
1073     }
1074
1075     return 0;
1076 }
1077
1078 FFADODevice*
1079 DeviceManager::getAvDeviceByIndex( int idx )
1080 {
1081     return m_avDevices.at(idx);
1082 }
1083
1084 unsigned int
1085 DeviceManager::getAvDeviceCount( )
1086 {
1087     return m_avDevices.size();
1088 }
1089
1090 /**
1091  * Return the streamprocessor that is to be used as
1092  * the sync source.
1093  *
1094  * Algorithm still to be determined
1095  *
1096  * @return StreamProcessor that is sync source
1097  */
1098 Streaming::StreamProcessor *
1099 DeviceManager::getSyncSource() {
1100     FFADODevice* device = getAvDeviceByIndex(0);
1101
1102     bool slaveMode=false;
1103     if(!getOption("slaveMode", slaveMode)) {
1104         debugOutput(DEBUG_LEVEL_NORMAL,
1105                     "Could not retrieve slaveMode parameter, defauling to false\n");
1106     }
1107     return device->getStreamProcessorByIndex(0);
1108 /*
1109     #warning TEST CODE FOR BOUNCE DEVICE !!
1110     // this makes the bounce slave use the xmit SP as sync source
1111     if (slaveMode) {
1112         return device->getStreamProcessorByIndex(1);
1113     } else {
1114         return device->getStreamProcessorByIndex(0);
1115     }*/
1116 }
1117
1118 bool
1119 DeviceManager::deinitialize()
1120 {
1121     return true;
1122 }
1123
1124 void
1125 DeviceManager::setVerboseLevel(int l)
1126 {
1127     setDebugLevel(l);
1128     Control::Element::setVerboseLevel(l);
1129     m_processorManager->setVerboseLevel(l);
1130     m_deviceStringParser->setVerboseLevel(l);
1131     m_configuration->setVerboseLevel(l);
1132     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1133           it != m_avDevices.end();
1134           ++it )
1135     {
1136         (*it)->setVerboseLevel(l);
1137     }
1138     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1139           it != m_1394Services.end();
1140           ++it )
1141     {
1142         (*it)->setVerboseLevel(l);
1143     }
1144     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1145 }
1146
1147 void
1148 DeviceManager::showDeviceInfo() {
1149     debugOutput(DEBUG_LEVEL_NORMAL, "===== Device Manager =====\n");
1150     Control::Element::show();
1151
1152     int i=0;
1153     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1154           it != m_1394Services.end();
1155           ++it )
1156     {
1157         debugOutput(DEBUG_LEVEL_NORMAL, "--- IEEE1394 Service %2d ---\n", i++);
1158         (*it)->show();
1159     }
1160
1161     i=0;
1162     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1163         it != m_avDevices.end();
1164         ++it )
1165     {
1166         FFADODevice* avDevice = *it;
1167         debugOutput(DEBUG_LEVEL_NORMAL, "--- Device %2d ---\n", i++);
1168         avDevice->showDevice();
1169
1170         debugOutput(DEBUG_LEVEL_NORMAL, "Clock sync sources:\n");
1171         FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
1172         for ( FFADODevice::ClockSourceVector::const_iterator it
1173                 = sources.begin();
1174             it != sources.end();
1175             ++it )
1176         {
1177             FFADODevice::ClockSource c=*it;
1178             debugOutput(DEBUG_LEVEL_NORMAL, " Type: %s, Id: %2d, Valid: %1d, Active: %1d, Locked %1d, Slipping: %1d, Description: %s\n",
1179                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.locked, c.slipping, c.description.c_str());
1180         }
1181     }
1182 }
1183 void
1184 DeviceManager::showStreamingInfo() {
1185     m_processorManager->dumpInfo();
1186 }
Note: See TracBrowser for help on using the browser.