root/trunk/libffado/src/devicemanager.cpp

Revision 554, 14.5 kB (checked in by ppalmers, 15 years ago)

Merge echoaudio branch into trunk.

This adds support for the Echo Audiofire devices to FFADO. Possibly also other devices working with the Apple Class Driver will work with this code. It is not fully complete yet, but the main rework is
done.

First of all the IAvDevice class/interface is renamed to FFADODevice, in order to separate the AV/C code from the FFADO API code. A device supported by FFADO implements a FFADODevice.

The BeBoB device has been split up into three groups:
- libavc/* : all code and commands that are specified by AV/C specs. Note that a lot of the code that used to be in BeBoB::AvDevice? now resides in AVC::Unit
- genericavc/* : a FFADODevice that uses AV/C descriptors & commands for discovery and config
- bebob/* : the bebob FFADODevice that inherits from GenericAVC::AvDevice? but that uses BridgeCo? commands for discovery

Everything has been moved as high as possible in the class hierarchy. If necessary, a subclass that uses device specific commands is introduced (e.g. BeBoB::Plug inherits from AVC::Plug and uses the
BridgeCo? extended plug info command to discover it's properties).

There are some other fixes along the way that have been done too.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by Daniel Wagner
3  * Copyright (C) 2005-2007 by Pieter Palmers
4  *
5  * This file is part of FFADO
6  * FFADO = Free Firewire (pro-)audio drivers for linux
7  *
8  * FFADO is based upon FreeBoB.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software Foundation;
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22  * MA 02110-1301 USA
23  */
24
25 #include "fbtypes.h"
26
27 #include "devicemanager.h"
28 #include "ffadodevice.h"
29
30 #include "libieee1394/configrom.h"
31 #include "libieee1394/ieee1394service.h"
32
33 #include "libstreaming/StreamProcessor.h"
34
35 #include "debugmodule/debugmodule.h"
36
37 #ifdef ENABLE_BEBOB
38 #include "bebob/bebob_avdevice.h"
39 #include "maudio/maudio_avdevice.h"
40 #endif
41
42 #ifdef ENABLE_GENERICAVC
43     #include "genericavc/avc_avdevice.h"
44 #endif
45
46 #ifdef ENABLE_BOUNCE
47 #include "bounce/bounce_avdevice.h"
48 #include "bounce/bounce_slave_avdevice.h"
49 #endif
50
51 #ifdef ENABLE_MOTU
52 #include "motu/motu_avdevice.h"
53 #endif
54
55 #ifdef ENABLE_RME
56 #include "rme/rme_avdevice.h"
57 #endif
58
59 #ifdef ENABLE_DICE
60 #include "dice/dice_avdevice.h"
61 #endif
62
63 #ifdef ENABLE_METRIC_HALO
64 #include "metrichalo/mh_avdevice.h"
65 #endif
66
67 #include <iostream>
68 #include <sstream>
69
70 using namespace std;
71
72 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
73
74 DeviceManager::DeviceManager()
75     : OscNode("devicemanager")
76     , m_1394Service( 0 )
77     , m_oscServer( NULL )
78 {
79     addOption(Util::OptionContainer::Option("slaveMode",false));
80     addOption(Util::OptionContainer::Option("snoopMode",false));
81 }
82
83 DeviceManager::~DeviceManager()
84 {
85     if (m_oscServer) {
86         m_oscServer->stop();
87         delete m_oscServer;
88     }
89
90     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
91           it != m_avDevices.end();
92           ++it )
93     {
94         delete *it;
95     }
96
97     delete m_1394Service;
98 }
99
100 void
101 DeviceManager::setVerboseLevel(int l)
102 {
103     debugOutput( DEBUG_LEVEL_NORMAL, "Setting verbose level to %d...\n", l );
104     setDebugLevel(l);
105
106     if (m_1394Service) m_1394Service->setVerboseLevel(l);
107     if (m_oscServer) m_oscServer->setVerboseLevel(l);
108     OscNode::setVerboseLevel(l);
109
110     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
111           it != m_avDevices.end();
112           ++it )
113     {
114         (*it)->setVerboseLevel(l);
115     }
116 }
117
118 bool
119 DeviceManager::initialize( int port )
120 {
121     m_1394Service = new Ieee1394Service();
122     if ( !m_1394Service ) {
123         debugFatal( "Could not create Ieee1349Service object\n" );
124         return false;
125     }
126
127     if ( !m_1394Service->initialize( port ) ) {
128         debugFatal( "Could not initialize Ieee1349Service object\n" );
129         delete m_1394Service;
130         m_1394Service = 0;
131         return false;
132     }
133
134 //     m_oscServer = new OSC::OscServer("17820");
135 //
136 //     if (!m_oscServer) {
137 //         debugFatal("failed to create osc server\n");
138 //         delete m_1394Service;
139 //         m_1394Service = 0;
140 //         return false;
141 //     }
142 //
143 //     if (!m_oscServer->init()) {
144 //         debugFatal("failed to init osc server\n");
145 //         delete m_oscServer;
146 //         m_oscServer = NULL;
147 //         delete m_1394Service;
148 //         m_1394Service = 0;
149 //         return false;
150 //     }
151 //
152 //     if (!m_oscServer->registerAtRootNode(this)) {
153 //         debugFatal("failed to register devicemanager at server\n");
154 //         delete m_oscServer;
155 //         m_oscServer = NULL;
156 //         delete m_1394Service;
157 //         m_1394Service = 0;
158 //         return false;
159 //     }
160 //
161 //     if (!m_oscServer->start()) {
162 //         debugFatal("failed to start osc server\n");
163 //         delete m_oscServer;
164 //         m_oscServer = NULL;
165 //         delete m_1394Service;
166 //         m_1394Service = 0;
167 //         return false;
168 //     }
169
170     setVerboseLevel(getDebugLevel());
171     return true;
172 }
173
174 bool
175 DeviceManager::discover( )
176 {
177     bool slaveMode=false;
178     if(!getOption("slaveMode", slaveMode)) {
179         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
180     }
181     bool snoopMode=false;
182     if(!getOption("snoopMode", snoopMode)) {
183         debugWarning("Could not retrieve snoopMode parameter, defauling to false\n");
184     }
185
186     setVerboseLevel(getDebugLevel());
187
188     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
189           it != m_avDevices.end();
190           ++it )
191     {
192         if (!removeChildOscNode(*it)) {
193             debugWarning("failed to unregister AvDevice from OSC server\n");
194         }
195         delete *it;
196     }
197     m_avDevices.clear();
198
199     if (!slaveMode) {
200         for ( fb_nodeid_t nodeId = 0;
201               nodeId < m_1394Service->getNodeCount();
202               ++nodeId )
203         {
204             debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
205
206             if (nodeId == m_1394Service->getLocalNodeId()) {
207                 debugOutput( DEBUG_LEVEL_VERBOSE, "Skipping local node (%d)...\n", nodeId );
208                 continue;
209             }
210
211             std::auto_ptr<ConfigRom> configRom =
212                 std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
213                                                          nodeId ) );
214             if ( !configRom->initialize() ) {
215                 // \todo If a PHY on the bus is in power safe mode then
216                 // the config rom is missing. So this might be just
217                 // such this case and we can safely skip it. But it might
218                 // be there is a real software problem on our side.
219                 // This should be handlede more carefuly.
220                 debugOutput( DEBUG_LEVEL_NORMAL,
221                              "Could not read config rom from device (node id %d). "
222                              "Skip device discovering for this node\n",
223                              nodeId );
224                 continue;
225             }
226
227             FFADODevice* avDevice = getDriverForDevice( configRom,
228                                                         nodeId );
229
230             if ( avDevice ) {
231                 debugOutput( DEBUG_LEVEL_NORMAL,
232                              "driver found for device %d\n",
233                              nodeId );
234
235                 bool isFromCache = false;
236                 if ( avDevice->loadFromCache() ) {
237                     debugOutput( DEBUG_LEVEL_VERBOSE, "could load from cache\n" );
238                     isFromCache = true;
239                 } else if ( avDevice->discover() ) {
240                     debugOutput( DEBUG_LEVEL_VERBOSE, "discovering successful\n" );
241                     avDevice->setVerboseLevel( getDebugLevel() );
242                 } else {
243                     debugError( "could not discover device\n" );
244                     delete avDevice;
245                     continue;
246                 }
247
248                 if ( !avDevice->setId( m_avDevices.size() ) ) {
249                     debugError( "setting Id failed\n" );
250                 }
251
252                 if (snoopMode) {
253                     debugOutput( DEBUG_LEVEL_VERBOSE,
254                                  "Enabling snoop mode on node %d...\n", nodeId );
255
256                     if(!avDevice->setOption("snoopMode", snoopMode)) {
257                         debugWarning("Could not set snoop mode for device on node %d\n", nodeId);
258                         delete avDevice;
259                         continue;
260                     }
261                 }
262
263                 if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
264                     avDevice->showDevice();
265                 }
266
267                 if ( !isFromCache && !avDevice->saveCache() ) {
268                     debugOutput( DEBUG_LEVEL_VERBOSE, "No cached version of AVC model created\n" );
269                 }
270
271                 m_avDevices.push_back( avDevice );
272
273                 if (!addChildOscNode(avDevice)) {
274                     debugWarning("failed to register AvDevice at OSC server\n");
275                 }
276                
277                 debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
278
279             }
280         }
281
282         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
283
284         return true;
285
286     } else { // slave mode
287         fb_nodeid_t nodeId = m_1394Service->getLocalNodeId();
288         debugOutput( DEBUG_LEVEL_VERBOSE, "Starting in slave mode on node %d...\n", nodeId );
289
290         std::auto_ptr<ConfigRom> configRom =
291             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
292                                                      nodeId ) );
293         if ( !configRom->initialize() ) {
294             // \todo If a PHY on the bus is in power safe mode then
295             // the config rom is missing. So this might be just
296             // such this case and we can safely skip it. But it might
297             // be there is a real software problem on our side.
298             // This should be handled more carefuly.
299             debugOutput( DEBUG_LEVEL_NORMAL,
300                          "Could not read config rom from device (node id %d). "
301                          "Skip device discovering for this node\n",
302                          nodeId );
303             return false;
304         }
305
306         FFADODevice* avDevice = getSlaveDriver( configRom );
307         if ( avDevice ) {
308             debugOutput( DEBUG_LEVEL_NORMAL,
309                          "driver found for device %d\n",
310                          nodeId );
311
312             avDevice->setVerboseLevel( getDebugLevel() );
313
314             if ( !avDevice->discover() ) {
315                 debugError( "could not discover device\n" );
316                 delete avDevice;
317                 return false;
318             }
319
320             if ( !avDevice->setId( m_avDevices.size() ) ) {
321                 debugError( "setting Id failed\n" );
322             }
323             if ( getDebugLevel() >= DEBUG_LEVEL_VERBOSE ) {
324                 avDevice->showDevice();
325             }
326
327             m_avDevices.push_back( avDevice );
328
329             debugOutput( DEBUG_LEVEL_NORMAL, "discovery of node %d done...\n", nodeId );
330         }
331
332         debugOutput( DEBUG_LEVEL_NORMAL, "discovery finished...\n" );
333
334         return true;
335     }
336 }
337
338
339 FFADODevice*
340 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
341                                    int id )
342 {
343 #ifdef ENABLE_BEBOB
344     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying BeBoB...\n" );
345     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
346         return new BeBoB::AvDevice( configRom, *m_1394Service, id );
347     }
348 #endif
349
350 #ifdef ENABLE_GENERICAVC
351     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Generic AV/C...\n" );
352     if ( GenericAVC::AvDevice::probe( *configRom.get() ) ) {
353         return new GenericAVC::AvDevice( configRom, *m_1394Service, id );
354     }
355 #endif
356
357 #ifdef ENABLE_BEBOB
358     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying M-Audio...\n" );
359     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
360         return new MAudio::AvDevice( configRom, *m_1394Service, id );
361     }
362 #endif
363
364 #ifdef ENABLE_MOTU
365     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Motu...\n" );
366     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
367         return new Motu::MotuDevice( configRom, *m_1394Service, id );
368     }
369 #endif
370
371 #ifdef ENABLE_DICE
372     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Dice...\n" );
373     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
374         return new Dice::DiceAvDevice( configRom, *m_1394Service, id );
375     }
376 #endif
377
378 #ifdef ENABLE_METRIC_HALO
379     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Metric Halo...\n" );
380     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
381         return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id );
382     }
383 #endif
384
385 #ifdef ENABLE_RME
386     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying RME...\n" );
387     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
388         return new Rme::RmeDevice( configRom, *m_1394Service, id );
389     }
390 #endif
391
392 #ifdef ENABLE_BOUNCE
393     debugOutput( DEBUG_LEVEL_VERBOSE, "Trying Bounce...\n" );
394     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
395         return new Bounce::BounceDevice( configRom, *m_1394Service, id );
396     }
397 #endif
398
399     return 0;
400 }
401
402 FFADODevice*
403 DeviceManager::getSlaveDriver( std::auto_ptr<ConfigRom>( configRom ) )
404 {
405
406 #ifdef ENABLE_BOUNCE
407     if ( Bounce::BounceSlaveDevice::probe( *configRom.get() ) ) {
408         return new Bounce::BounceSlaveDevice( configRom, *m_1394Service );
409     }
410 #endif
411
412     return 0;
413 }
414
415 bool
416 DeviceManager::isValidNode(int node)
417 {
418     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
419           it != m_avDevices.end();
420           ++it )
421     {
422         FFADODevice* avDevice = *it;
423
424         if (avDevice->getConfigRom().getNodeId() == node) {
425             return true;
426     }
427     }
428     return false;
429 }
430
431 int
432 DeviceManager::getNbDevices()
433 {
434     return m_avDevices.size();
435 }
436
437 int
438 DeviceManager::getDeviceNodeId( int deviceNr )
439 {
440     if ( ! ( deviceNr < getNbDevices() ) ) {
441         debugError( "Device number out of range (%d)\n", deviceNr );
442         return -1;
443     }
444
445     FFADODevice* avDevice = m_avDevices.at( deviceNr );
446
447     if ( !avDevice ) {
448         debugError( "Could not get device at position (%d)\n",  deviceNr );
449     }
450
451     return avDevice->getConfigRom().getNodeId();
452 }
453
454 FFADODevice*
455 DeviceManager::getAvDevice( int nodeId )
456 {
457     for ( FFADODeviceVectorIterator it = m_avDevices.begin();
458           it != m_avDevices.end();
459           ++it )
460     {
461         FFADODevice* avDevice = *it;
462         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
463             return avDevice;
464         }
465     }
466
467     return 0;
468 }
469
470 FFADODevice*
471 DeviceManager::getAvDeviceByIndex( int idx )
472 {
473     return m_avDevices.at(idx);
474 }
475
476 unsigned int
477 DeviceManager::getAvDeviceCount( )
478 {
479     return m_avDevices.size();
480 }
481
482 /**
483  * Return the streamprocessor that is to be used as
484  * the sync source.
485  *
486  * Algorithm still to be determined
487  *
488  * @return StreamProcessor that is sync source
489  */
490 Streaming::StreamProcessor *
491 DeviceManager::getSyncSource() {
492     FFADODevice* device = getAvDeviceByIndex(0);
493
494     bool slaveMode=false;
495     if(!getOption("slaveMode", slaveMode)) {
496         debugWarning("Could not retrieve slaveMode parameter, defauling to false\n");
497     }
498
499     #warning TEST CODE FOR BOUNCE DEVICE !!
500     // this makes the bounce slave use the xmit SP as sync source
501     if (slaveMode) {
502         return device->getStreamProcessorByIndex(1);
503     } else {
504         return device->getStreamProcessorByIndex(0);
505     }
506 }
507
508 bool
509 DeviceManager::deinitialize()
510 {
511     return true;
512 }
Note: See TracBrowser for help on using the browser.