root/trunk/libffado/src/devicemanager.cpp

Revision 1789, 42.6 kB (checked in by arnonym, 14 years ago)

Use the GUID as the id and get rid of setId(). This is part of making the port names unique and persistent per device.

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