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

Revision 404, 13.4 kB (checked in by pieterpalmers, 16 years ago)

- introduce support framework for DICE and Metric Halo
- change probe/discovery code to make adding devices easier
- made conditional compilation effectively work.

./configure now has the following switches:

--enable-bebob build BeBoB support (default=yes)
--enable-motu build Motu support (default=no)
--enable-dice build DICE support (default=no)
--enable-metric-halo build Metric Halo support (note: completely useless)

(default=no)

--enable-rme build RME support (note: completely useless)

(default=no)

--enable-bounce build Bounce device support (default=no)
--enable-all-devices build support for all supported devices (default=no)

these now turn on/off compilation effectively.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1  /* devicemanager.cpp
2  * Copyright (C) 2005,06,07 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "fbtypes.h"
22
23 #include "devicemanager.h"
24 #include "iavdevice.h"
25 #include "configrom.h"
26
27 #include "libfreebobavc/ieee1394service.h"
28 #include "debugmodule/debugmodule.h"
29 #include "bebob/bebob_avdevice.h"
30 #include "bounce/bounce_avdevice.h"
31 #include "motu/motu_avdevice.h"
32 #include "rme/rme_avdevice.h"
33 #include "maudio/maudio_avdevice.h"
34 #include "dice/dice_avdevice.h"
35 #include "metrichalo/mh_avdevice.h"
36
37 #include <iostream>
38 #include <sstream>
39
40 #include <unistd.h>
41
42 using namespace std;
43
44 IMPL_DEBUG_MODULE( DeviceManager, DeviceManager, DEBUG_LEVEL_NORMAL );
45
46 DeviceManager::DeviceManager()
47     : m_1394Service( 0 )
48 {
49
50 }
51
52 DeviceManager::~DeviceManager()
53 {
54     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
55           it != m_avDevices.end();
56           ++it )
57     {
58         delete *it;
59     }
60
61     delete m_1394Service;
62 }
63
64 bool
65 DeviceManager::initialize( int port )
66 {
67     m_1394Service = new Ieee1394Service();
68     if ( !m_1394Service ) {
69         debugFatal( "Could not create Ieee1349Service object\n" );
70         return false;
71     }
72
73     if ( !m_1394Service->initialize( port ) ) {
74         debugFatal( "Could not initialize Ieee1349Service object\n" );
75         delete m_1394Service;
76         m_1394Service = 0;
77         return false;
78     }
79
80     return true;
81 }
82
83 bool
84 DeviceManager::discover( int verboseLevel )
85 {
86
87     setDebugLevel( verboseLevel );
88     m_1394Service->setVerbose( verboseLevel );
89
90     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
91           it != m_avDevices.end();
92           ++it )
93     {
94         delete *it;
95     }
96     m_avDevices.clear();
97
98     for ( fb_nodeid_t nodeId = 0;
99           nodeId < m_1394Service->getNodeCount();
100           ++nodeId )
101     {
102         debugOutput( DEBUG_LEVEL_VERBOSE, "Probing node %d...\n", nodeId );
103
104         std::auto_ptr<ConfigRom> configRom =
105             std::auto_ptr<ConfigRom>( new ConfigRom( *m_1394Service,
106                                                      nodeId ) );
107         if ( !configRom->initialize() ) {
108             // \todo If a PHY on the bus is in power safe mode then
109             // the config rom is missing. So this might be just
110             // such this case and we can safely skip it. But it might
111             // be there is a real software problem on our side.
112             // This should be handled more carefuly.
113             debugOutput( DEBUG_LEVEL_NORMAL,
114                          "Could not read config rom from device (node id %d). "
115                          "Skip device discovering for this node\n",
116                          nodeId );
117             continue;
118         }
119
120         IAvDevice* avDevice = getDriverForDevice( configRom,
121                                                   nodeId,
122                                                   verboseLevel );
123         if ( avDevice ) {
124             debugOutput( DEBUG_LEVEL_NORMAL,
125                          "discover: driver found for device %d\n",
126                          nodeId );
127
128             if ( !avDevice->discover() ) {
129                 debugError( "discover: could not discover device\n" );
130                 delete avDevice;
131                 continue;
132             }
133
134             if ( !avDevice->setId( m_avDevices.size() ) ) {
135                 debugError( "setting Id failed\n" );
136             }
137             if ( verboseLevel ) {
138                 avDevice->showDevice();
139             }
140
141             m_avDevices.push_back( avDevice );
142         }
143     }
144
145     return true;
146 }
147
148
149 IAvDevice*
150 DeviceManager::getDriverForDevice( std::auto_ptr<ConfigRom>( configRom ),
151                                    int id,  int level )
152 {
153 #ifdef ENABLE_BEBOB
154     if ( BeBoB::AvDevice::probe( *configRom.get() ) ) {
155         return new BeBoB::AvDevice( configRom, *m_1394Service, id, level );
156     }
157 #endif
158
159 #ifdef ENABLE_BEBOB
160     if ( MAudio::AvDevice::probe( *configRom.get() ) ) {
161         return new MAudio::AvDevice( configRom, *m_1394Service, id, level );
162     }
163 #endif
164
165 #ifdef ENABLE_MOTU
166     if ( Motu::MotuDevice::probe( *configRom.get() ) ) {
167         return new Motu::MotuDevice( configRom, *m_1394Service, id, level );
168     }
169 #endif
170
171 #ifdef ENABLE_DICE
172     if ( Dice::DiceAvDevice::probe( *configRom.get() ) ) {
173         return new Dice::DiceAvDevice( configRom, *m_1394Service, id, level );
174     }
175 #endif
176
177 #ifdef ENABLE_METRIC_HALO
178     if ( MetricHalo::MHAvDevice::probe( *configRom.get() ) ) {
179         return new MetricHalo::MHAvDevice( configRom, *m_1394Service, id, level );
180     }
181 #endif
182
183 #ifdef ENABLE_RME
184     if ( Rme::RmeDevice::probe( *configRom.get() ) ) {
185         return new Rme::RmeDevice( configRom, *m_1394Service, id, level );
186     }
187 #endif
188
189 #ifdef ENABLE_BOUNCE
190     if ( Bounce::BounceDevice::probe( *configRom.get() ) ) {
191         return new Bounce::BounceDevice( configRom, *m_1394Service, id, level );
192     }
193 #endif
194
195     return 0;
196 }
197
198 bool
199 DeviceManager::isValidNode(int node)
200 {
201     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
202           it != m_avDevices.end();
203           ++it )
204     {
205         IAvDevice* avDevice = *it;
206
207         if (avDevice->getConfigRom().getNodeId() == node) {
208                 return true;
209         }
210     }
211     return false;
212 }
213
214 int
215 DeviceManager::getNbDevices()
216 {
217     return m_avDevices.size();
218 }
219
220 int
221 DeviceManager::getDeviceNodeId( int deviceNr )
222 {
223     if ( ! ( deviceNr < getNbDevices() ) ) {
224         debugError( "Device number out of range (%d)\n", deviceNr );
225         return -1;
226     }
227
228     IAvDevice* avDevice = m_avDevices.at( deviceNr );
229
230     if ( !avDevice ) {
231         debugError( "Could not get device at position (%d)\n",  deviceNr );
232     }
233
234     return avDevice->getConfigRom().getNodeId();
235 }
236
237 IAvDevice*
238 DeviceManager::getAvDevice( int nodeId )
239 {
240     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
241           it != m_avDevices.end();
242           ++it )
243     {
244         IAvDevice* avDevice = *it;
245         if ( avDevice->getConfigRom().getNodeId() == nodeId ) {
246             return avDevice;
247         }
248     }
249
250     return 0;
251 }
252
253 IAvDevice*
254 DeviceManager::getAvDeviceByIndex( int idx )
255 {
256         return m_avDevices.at(idx);
257 }
258
259 unsigned int
260 DeviceManager::getAvDeviceCount( )
261 {
262         return m_avDevices.size();
263 }
264
265 xmlDocPtr
266 DeviceManager::getXmlDescription()
267 {
268     xmlDocPtr doc = xmlNewDoc( BAD_CAST "1.0" );
269     if ( !doc ) {
270         debugError( "Couldn't create new xml doc\n" );
271         return 0;
272     }
273
274     xmlNodePtr rootNode = xmlNewNode( 0,  BAD_CAST "FreeBoBConnectionInfo" );
275     if ( !rootNode ) {
276         debugError( "Couldn't create root node\n" );
277         xmlFreeDoc( doc );
278         xmlCleanupParser();
279         return 0;
280     }
281     xmlDocSetRootElement( doc, rootNode );
282
283     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
284           it != m_avDevices.end();
285           ++it )
286     {
287         IAvDevice* avDevice = *it;
288
289         xmlNodePtr deviceNode = xmlNewChild( rootNode, 0,
290                                              BAD_CAST "Device", 0 );
291         if ( !deviceNode ) {
292             debugError( "Couldn't create device node\n" );
293             xmlFreeDoc( doc );
294             xmlCleanupParser();
295             return 0;
296         }
297
298         char* result;
299         asprintf( &result, "%d", avDevice->getConfigRom().getNodeId() );
300         if ( !xmlNewChild( deviceNode,  0,
301                            BAD_CAST "NodeId",  BAD_CAST result ) )
302         {
303             debugError( "Couldn't create 'NodeId' node" );
304             free(result);
305             return 0;
306         }
307         free( result );
308
309         std::string res = "Connection Information for "
310                           + avDevice->getConfigRom().getVendorName()
311                           +", "
312                           + avDevice->getConfigRom().getModelName()
313                           + " configuration";
314         if ( !xmlNewChild( deviceNode,
315                            0,
316                            BAD_CAST "Comment",
317                            BAD_CAST res.c_str() ) ) {
318             debugError( "Couldn't create comment node\n" );
319             xmlFreeDoc( doc );
320             xmlCleanupParser();
321             free(result);
322             return 0;
323         }
324
325         res = avDevice->getConfigRom().getVendorName();
326
327         if ( !xmlNewChild( deviceNode,
328                            0,
329                            BAD_CAST "Vendor",
330                            BAD_CAST res.c_str() ) ) {
331             debugError( "Couldn't create vendor node\n" );
332             xmlFreeDoc( doc );
333             xmlCleanupParser();
334             free(result);
335             return 0;
336         }
337
338         res = avDevice->getConfigRom().getModelName();
339
340         if ( !xmlNewChild( deviceNode,
341                            0,
342                            BAD_CAST "Model",
343                            BAD_CAST res.c_str() ) ) {
344             debugError( "Couldn't create model node\n" );
345             xmlFreeDoc( doc );
346             xmlCleanupParser();
347             free(result);
348             return 0;
349         }
350
351         asprintf( &result, "%08x%08x",
352                   ( quadlet_t )( avDevice->getConfigRom().getGuid() >> 32 ),
353                   ( quadlet_t )( avDevice->getConfigRom().getGuid() & 0xfffffff ) );
354         if ( !xmlNewChild( deviceNode,  0,
355                            BAD_CAST "GUID",  BAD_CAST result ) ) {
356             debugError( "Couldn't create 'GUID' node\n" );
357             xmlFreeDoc( doc );
358             xmlCleanupParser();
359
360             free(result);
361             return 0;
362         }
363         free( result );
364
365
366         if ( !avDevice->addXmlDescription( deviceNode ) ) {
367             debugError( "Adding XML description failed\n" );
368             xmlFreeDoc( doc );
369             xmlCleanupParser();
370             free(result);
371             return 0;
372         }
373
374         free(result);
375     }
376
377     return doc;
378 }
379
380 bool
381 DeviceManager::deinitialize()
382 {
383     return true;
384 }
385
386 bool
387 DeviceManager::saveCache( Glib::ustring fileName )
388 {
389     int i;
390     i=0; // avoids unused warning
391    
392     for ( IAvDeviceVectorIterator it = m_avDevices.begin();
393           it != m_avDevices.end();
394           ++it )
395     {
396         IAvDevice* pAvDevice;
397         pAvDevice = *it; // avoids unused warning
398        
399         #ifdef ENABLE_BEBOB
400         BeBoB::AvDevice* pBeBoBDevice = reinterpret_cast< BeBoB::AvDevice* >( pAvDevice );
401         if ( pBeBoBDevice ) {
402             // Let's use a very simple path to find the devices later.
403             // Since under hood there will an xml node name this should
404             // adhere the needed naming rules. Of course we could give it
405             // a good node name and add an attribute but that would mean
406             // we have to expose a bigger interface from IOSerialize/IODesialize,
407             // which is just not needed. KISS.
408             ostringstream strstrm;
409             strstrm << "id" << i;
410             Glib::ustring basePath = "BeBoB/" + strstrm.str() + "/";
411
412             Util::XMLSerialize ser( fileName );
413             pBeBoBDevice->serialize( basePath, ser );
414
415             i++;
416             std::cout << "a bebob device serialized" << std::endl;
417         }
418         #endif
419     }
420     return true;
421 }
422
423 bool
424 DeviceManager::loadCache( Glib::ustring fileName )
425 {
426     int i;
427     i=0; // avoids unused warning
428     Util::XMLDeserialize deser( fileName );
429
430     typedef std::vector<ConfigRom*> ConfigRomVector;
431     ConfigRomVector configRoms;
432
433     for ( fb_nodeid_t nodeId = 0;
434           nodeId < m_1394Service->getNodeCount();
435           ++nodeId )
436     {
437         ConfigRom* pConfigRom  =  new ConfigRom( *m_1394Service, nodeId );
438         if ( !pConfigRom->initialize() ) {
439             // \todo If a PHY on the bus is in power safe mode then
440             // the config rom is missing. So this might be just
441             // such this case and we can safely skip it. But it might
442             // be there is a real software problem on our side.
443             // This should be handled more carefuly.
444             debugOutput( DEBUG_LEVEL_NORMAL,
445                          "Could not read config rom from device (node id %d). "
446                          "Skip device discovering for this node\n",
447                          nodeId );
448             delete pConfigRom;
449             continue;
450         }
451         configRoms.push_back( pConfigRom );
452     }
453
454     #ifdef ENABLE_BEBOB
455     BeBoB::AvDevice* pBeBoBDevice = 0;
456     do {
457         ostringstream strstrm;
458         strstrm << "id" << i;
459         pBeBoBDevice = BeBoB::AvDevice::deserialize(
460             "BeBoB/" + strstrm.str() + "/",
461             deser,
462             *m_1394Service );
463
464         ++i;
465         if ( pBeBoBDevice ) {
466             for (ConfigRomVector::iterator it = configRoms.begin();
467                  it != configRoms.end();
468                  ++it )
469             {
470                 ConfigRom* pConfigRom = *it;
471
472                 if ( pBeBoBDevice->getConfigRom() == *pConfigRom ) {
473                     pBeBoBDevice->getConfigRom().setNodeId( pConfigRom->getNodeId() );
474                     // m_avDevices.push_back( pBeBoBDevice );
475
476                 }
477             }
478         }
479     } while ( pBeBoBDevice );
480     #endif
481    
482     return true;
483 }
Note: See TracBrowser for help on using the browser.