root/trunk/libffado/src/devicemanager.cpp

Revision 1543, 39.8 kB (checked in by ppalmers, 15 years ago)

- Clean up class names
- Change probe code for all devices (except MOTU) to use the config file based approach

  • 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 AvDevice 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 AvDevice 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 AvDevice 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 AvDevice 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 AvDevice 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         int i=0;
673         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
674             it != m_avDevices.end();
675             ++it )
676         {
677             if ( !(*it)->setId( i++ ) ) {
678                 debugError( "setting Id failed\n" );
679             }
680         }
681         showDeviceInfo();
682
683     } else { // slave mode
684         // notify any clients
685         signalNotifiers(m_preUpdateNotifiers);
686         Ieee1394Service *portService = m_1394Services.at(0);
687         fb_nodeid_t nodeId = portService->getLocalNodeId();
688         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
689
690         std::auto_ptr<ConfigRom> configRom =
691             std::auto_ptr<ConfigRom>( new ConfigRom( *portService,
692                                                      nodeId ) );
693         if ( !configRom->initialize() ) {
694             // \todo If a PHY on the bus is in power safe mode then
695             // the config rom is missing. So this might be just
696             // such this case and we can safely skip it. But it might
697             // be there is a real software problem on our side.
698             // This should be handled more carefuly.
699             debugOutput( DEBUG_LEVEL_NORMAL,
700                          "Could not read config rom from device (node id %d). "
701                          "Skip device discovering for this node\n",
702                          nodeId );
703             return false;
704         }
705
706         // remove any already present devices
707         for ( FFADODeviceVectorIterator it = m_avDevices.begin();
708             it != m_avDevices.end();
709             ++it )
710         {
711             if (!deleteElement(*it)) {
712                 debugWarning("failed to remove AvDevice from Control::Container\n");
713             }
714             delete *it;
715         }
716
717         m_avDevices.clear();
718
719         // get the slave driver
720         FFADODevice* avDevice = getSlaveDriver( configRom );
721         if ( avDevice ) {
722             debugOutput( DEBUG_LEVEL_NORMAL,
723                          "driver found for device %d\n",
724                          nodeId );
725
726             avDevice->setVerboseLevel( getDebugLevel() );
727
728             if ( !avDevice->discover() ) {
729                 debugError( "could not discover device\n" );
730                 delete avDevice;
731                 return false;
732             }
733
734             if ( !avDevice->setId( m_avDevices.size() ) ) {
735                 debugError( "setting Id failed\n" );
736             }
737             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
738                 avDevice->showDevice();
739             }
740             m_avDevices.push_back( avDevice );
741             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d on port %d done...\n", nodeId, portService->getPort() );
742         }
743
744         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
745     }
746
747     m_DeviceListLock->Unlock();
748     // notify any clients
749     signalNotifiers(m_postUpdateNotifiers);
750     return true;
751 }
752
753 bool
754 DeviceManager::initStreaming()
755 {
756     // iterate over the found devices
757     // add the stream processors of the devices to the managers
758     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
759         it != m_avDevices.end();
760         ++it )
761     {
762         FFADODevice *device = *it;
763         assert(device);
764
765         debugOutput(DEBUG_LEVEL_VERBOSE, "Locking device (%p)\n", device);
766
767         if (!device->lock()) {
768             debugWarning("Could not lock device, skipping device (%p)!\n", device);
769             continue;
770         }
771
772         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting samplerate to %d for (%p)\n",
773                     m_processorManager->getNominalRate(), device);
774
775         // Set the device's sampling rate to that requested
776         // FIXME: does this really belong here?  If so we need to handle errors.
777         if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
778             debugOutput(DEBUG_LEVEL_VERBOSE, " => Retry setting samplerate to %d for (%p)\n",
779                         m_processorManager->getNominalRate(), device);
780
781             // try again:
782             if (!device->setSamplingFrequency(m_processorManager->getNominalRate())) {
783                 debugFatal("Could not set sampling frequency to %d\n",m_processorManager->getNominalRate());
784                 return false;
785             }
786         }
787         // prepare the device
788         device->prepare();
789     }
790
791     // set the sync source
792     if (!m_processorManager->setSyncSource(getSyncSource())) {
793         debugWarning("Could not set processorManager sync source (%p)\n",
794             getSyncSource());
795     }
796
797     return true;
798 }
799
800 bool
801 DeviceManager::prepareStreaming()
802 {
803     if (!m_processorManager->prepare()) {
804         debugFatal("Could not prepare streaming...\n");
805         return false;
806     }
807     return true;
808 }
809
810 bool
811 DeviceManager::finishStreaming() {
812     bool result = true;
813     // iterate over the found devices
814     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
815         it != m_avDevices.end();
816         ++it )
817     {
818         debugOutput(DEBUG_LEVEL_VERBOSE, "Unlocking device (%p)\n", *it);
819
820         if (!(*it)->unlock()) {
821             debugWarning("Could not unlock device (%p)!\n", *it);
822             result = false;
823         }
824     }
825     return result;
826 }
827
828 bool
829 DeviceManager::startStreaming() {
830     // create the connections for all devices
831     // iterate over the found devices
832     // add the stream processors of the devices to the managers
833     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
834         it != m_avDevices.end();
835         ++it )
836     {
837         FFADODevice *device = *it;
838         assert(device);
839
840         int j=0;
841         for(j=0; j < device->getStreamCount(); j++) {
842         debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %p\n", j, device);
843             // start the stream
844             if (!device->startStreamByIndex(j)) {
845                 debugWarning("Could not start stream %d of device %p\n", j, device);
846                 continue;
847             }
848         }
849
850         if (!device->enableStreaming()) {
851             debugWarning("Could not enable streaming on device %p!\n", device);
852         }
853     }
854
855     if(m_processorManager->start()) {
856         return true;
857     } else {
858         stopStreaming();
859         return false;
860     }
861 }
862
863 bool
864 DeviceManager::resetStreaming() {
865     return true;
866 }
867
868 bool
869 DeviceManager::stopStreaming()
870 {
871     bool result = true;
872     m_processorManager->stop();
873
874     // create the connections for all devices
875     // iterate over the found devices
876     // add the stream processors of the devices to the managers
877     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
878         it != m_avDevices.end();
879         ++it )
880     {
881         FFADODevice *device = *it;
882         assert(device);
883
884         if (!device->disableStreaming()) {
885             debugWarning("Could not disable streaming on device %p!\n", device);
886         }
887
888         int j=0;
889         for(j=0; j < device->getStreamCount(); j++) {
890             debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %p\n", j, device);
891             // stop the stream
892             // start the stream
893             if (!device->stopStreamByIndex(j)) {
894                 debugWarning("Could not stop stream %d of device %p\n", j, device);
895                 result = false;
896                 continue;
897             }
898         }
899     }
900     return result;
901 }
902
903 enum DeviceManager::eWaitResult
904 DeviceManager::waitForPeriod() {
905     if(m_processorManager->waitForPeriod()) {
906         return eWR_OK;
907     } else {
908         if(m_processorManager->shutdownNeeded()) {
909             debugWarning("Shutdown requested\n");
910             return eWR_Shutdown;
911         } else {
912             debugWarning("XRUN detected\n");
913             // do xrun recovery
914             if(m_processorManager->handleXrun()) {
915                 return eWR_Xrun;
916             } else {
917                 debugError("Could not handle XRUN\n");
918                 return eWR_Error;
919             }
920         }
921     }
922 }
923
924 bool
925 DeviceManager::setStreamingParams(unsigned int period, unsigned int rate, unsigned int nb_buffers) {
926     m_processorManager->setPeriodSize(period);
927     m_processorManager->setNominalRate(rate);
928     m_processorManager->setNbBuffers(nb_buffers);
929     return true;
930 }
931
932 FFADODevice*
933 DeviceManager::getDriverForDeviceDo( ConfigRom *configRom,
934                                    int id, bool generic )
935 {
936 #ifdef ENABLE_BEBOB
937     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
938     if ( BeBoB::Device::probe( getConfiguration(), *configRom, generic ) ) {
939         return BeBoB::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
940     }
941 #endif
942
943 #ifdef ENABLE_FIREWORKS
944     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying ECHO Audio FireWorks...\n" );
945     if ( FireWorks::Device::probe( getConfiguration(), *configRom, generic ) ) {
946         return FireWorks::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
947     }
948 #endif
949
950 #ifdef ENABLE_OXFORD
951     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Oxford FW90x...\n" );
952     if ( Oxford::Device::probe( getConfiguration(), *configRom, generic ) ) {
953         return Oxford::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
954     }
955 #endif
956
957 #ifdef ENABLE_MAUDIO
958     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
959     if ( MAudio::Device::probe( getConfiguration(), *configRom, generic ) ) {
960         return MAudio::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
961     }
962 #endif
963
964 // we want to try the non-generic AV/C platforms before trying the generic ones
965 #ifdef ENABLE_GENERICAVC
966     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
967     if ( GenericAVC::Device::probe( getConfiguration(), *configRom, generic ) ) {
968         return GenericAVC::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
969     }
970 #endif
971
972 #ifdef ENABLE_MOTU
973     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
974     if ( Motu::MotuDevice::probe( getConfiguration(), *configRom, generic ) ) {
975         return Motu::MotuDevice::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
976     }
977 #endif
978
979 #ifdef ENABLE_DICE
980     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
981     if ( Dice::Device::probe( getConfiguration(), *configRom, generic ) ) {
982         return Dice::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
983     }
984 #endif
985
986 #ifdef ENABLE_METRIC_HALO
987     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
988     if ( MetricHalo::Device::probe( getConfiguration(), *configRom, generic ) ) {
989         return MetricHalo::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
990     }
991 #endif
992
993 #ifdef ENABLE_RME
994     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
995     if ( Rme::Device::probe( getConfiguration(), *configRom, generic ) ) {
996         return Rme::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
997     }
998 #endif
999
1000 #ifdef ENABLE_BOUNCE
1001     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
1002     if ( Bounce::Device::probe( getConfiguration(), *configRom, generic ) ) {
1003         return Bounce::Device::createDevice( *this, std::auto_ptr<ConfigRom>( configRom ) );
1004     }
1005 #endif
1006
1007     return NULL;
1008 }
1009
1010 FFADODevice*
1011 DeviceManager::getDriverForDevice( ConfigRom *configRom,
1012                                    int id )
1013 {
1014     debugOutput( DEBUG_LEVEL_VERBOSE, "Probing for supported device...\n" );
1015     FFADODevice* dev = getDriverForDeviceDo(configRom, id, false);
1016     if(dev) {
1017         debugOutput( DEBUG_LEVEL_VERBOSE, " found supported device...\n" );
1018         dev->setVerboseLevel(getDebugLevel());
1019         return dev;
1020     }
1021
1022     debugOutput( DEBUG_LEVEL_VERBOSE, " no supported device found, trying generic support...\n" );
1023     dev = getDriverForDeviceDo(configRom, id, true);
1024     if(dev) {
1025         debugOutput( DEBUG_LEVEL_VERBOSE, " found generic support for device...\n" );
1026         dev->setVerboseLevel(getDebugLevel());
1027         return dev;
1028     }
1029     debugOutput( DEBUG_LEVEL_VERBOSE, " device not supported...\n" );
1030     return NULL;
1031 }
1032
1033 FFADODevice*
1034 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
1035 {
1036 #ifdef ENABLE_BOUNCE
1037     if ( Bounce::SlaveDevice::probe( getConfiguration(), *configRom, false ) ) {
1038         return Bounce::SlaveDevice::createDevice(  *this, std::auto_ptr<ConfigRom>( configRom ) );
1039     }
1040 #endif
1041     return NULL;
1042 }
1043
1044 bool
1045 DeviceManager::isValidNode(int node)
1046 {
1047     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1048           it != m_avDevices.end();
1049           ++it )
1050     {
1051         FFADODevice* avDevice = *it;
1052
1053         if (avDevice->getConfigRom().getNodeId() == node) {
1054             return true;
1055     }
1056     }
1057     return false;
1058 }
1059
1060 int
1061 DeviceManager::getNbDevices()
1062 {
1063     return m_avDevices.size();
1064 }
1065
1066 int
1067 DeviceManager::getDeviceNodeId( int deviceNr )
1068 {
1069     if ( ! ( deviceNr < getNbDevices() ) ) {
1070         debugError( "Device number out of range (%d)\n", deviceNr );
1071         return -1;
1072     }
1073
1074     FFADODevice* avDevice = m_avDevices.at( deviceNr );
1075
1076     if ( !avDevice ) {
1077         debugError( "Could not get device at position (%d)\n",  deviceNr );
1078     }
1079
1080     return avDevice->getConfigRom().getNodeId();
1081 }
1082
1083 FFADODevice*
1084 DeviceManager::getAvDevice( int nodeId )
1085 {
1086     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1087           it != m_avDevices.end();
1088           ++it )
1089     {
1090         FFADODevice* avDevice = *it;
1091         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
1092             return avDevice;
1093         }
1094     }
1095
1096     return 0;
1097 }
1098
1099 FFADODevice*
1100 DeviceManager::getAvDeviceByIndex( int idx )
1101 {
1102     return m_avDevices.at(idx);
1103 }
1104
1105 unsigned int
1106 DeviceManager::getAvDeviceCount( )
1107 {
1108     return m_avDevices.size();
1109 }
1110
1111 /**
1112  * Return the streamprocessor that is to be used as
1113  * the sync source.
1114  *
1115  * Algorithm still to be determined
1116  *
1117  * @return StreamProcessor that is sync source
1118  */
1119 Streaming::StreamProcessor *
1120 DeviceManager::getSyncSource() {
1121     FFADODevice* device = getAvDeviceByIndex(0);
1122
1123     bool slaveMode=false;
1124     if(!getOption("slaveMode", slaveMode)) {
1125         debugOutput(DEBUG_LEVEL_NORMAL,
1126                     "Could not retrieve slaveMode parameter, defauling to false\n");
1127     }
1128     return device->getStreamProcessorByIndex(0);
1129 /*
1130     #warning TEST CODE FOR BOUNCE DEVICE !!
1131     // this makes the bounce slave use the xmit SP as sync source
1132     if (slaveMode) {
1133         return device->getStreamProcessorByIndex(1);
1134     } else {
1135         return device->getStreamProcessorByIndex(0);
1136     }*/
1137 }
1138
1139 bool
1140 DeviceManager::deinitialize()
1141 {
1142     return true;
1143 }
1144
1145 void
1146 DeviceManager::setVerboseLevel(int l)
1147 {
1148     setDebugLevel(l);
1149     Control::Element::setVerboseLevel(l);
1150     m_processorManager->setVerboseLevel(l);
1151     m_deviceStringParser->setVerboseLevel(l);
1152     m_configuration->setVerboseLevel(l);
1153     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1154           it != m_avDevices.end();
1155           ++it )
1156     {
1157         (*it)->setVerboseLevel(l);
1158     }
1159     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1160           it != m_1394Services.end();
1161           ++it )
1162     {
1163         (*it)->setVerboseLevel(l);
1164     }
1165     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1166 }
1167
1168 void
1169 DeviceManager::showDeviceInfo() {
1170     debugOutput(DEBUG_LEVEL_NORMAL, "===== Device Manager =====\n");
1171     Control::Element::show();
1172
1173     int i=0;
1174     for ( Ieee1394ServiceVectorIterator it = m_1394Services.begin();
1175           it != m_1394Services.end();
1176           ++it )
1177     {
1178         debugOutput(DEBUG_LEVEL_NORMAL, "--- IEEE1394 Service %2d ---\n", i++);
1179         (*it)->show();
1180     }
1181
1182     i=0;
1183     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
1184         it != m_avDevices.end();
1185         ++it )
1186     {
1187         FFADODevice* avDevice = *it;
1188         debugOutput(DEBUG_LEVEL_NORMAL, "--- Device %2d ---\n", i++);
1189         avDevice->showDevice();
1190
1191         debugOutput(DEBUG_LEVEL_NORMAL, "Clock sync sources:\n");
1192         FFADODevice::ClockSourceVector sources=avDevice->getSupportedClockSources();
1193         for ( FFADODevice::ClockSourceVector::const_iterator it
1194                 = sources.begin();
1195             it != sources.end();
1196             ++it )
1197         {
1198             FFADODevice::ClockSource c=*it;
1199             debugOutput(DEBUG_LEVEL_NORMAL, " Type: %s, Id: %2d, Valid: %1d, Active: %1d, Locked %1d, Slipping: %1d, Description: %s\n",
1200                 FFADODevice::ClockSourceTypeToString(c.type), c.id, c.valid, c.active, c.locked, c.slipping, c.description.c_str());
1201         }
1202     }
1203 }
1204 void
1205 DeviceManager::showStreamingInfo() {
1206     m_processorManager->dumpInfo();
1207 }
Note: See TracBrowser for help on using the browser.