root/branches/streaming-rework/src/maudio/maudio_avdevice.cpp

Revision 404, 17.3 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.

Line 
1 /* maudio_avdevice.cpp
2  * Copyright (C) 2006 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 #ifdef ENABLE_BEBOB
22
23 #include "maudio/maudio_avdevice.h"
24 #include "configrom.h"
25
26 #include "libfreebobavc/ieee1394service.h"
27 #include "libfreebobavc/avc_definitions.h"
28
29 #include "debugmodule/debugmodule.h"
30
31 #include <libxml/xmlmemory.h>
32 #include <libxml/parser.h>
33
34 #include <string>
35 #include <stdint.h>
36
37 namespace MAudio {
38
39 IMPL_DEBUG_MODULE( AvDevice, AvDevice, DEBUG_LEVEL_NORMAL );
40
41 AvDevice::AvDevice( std::auto_ptr< ConfigRom >( configRom ),
42                     Ieee1394Service& ieee1394service,
43                     int iNodeId,
44                     int iVerboseLevel )
45     :  m_pConfigRom( configRom )
46     , m_p1394Service( &ieee1394service )
47     , m_iNodeId( iNodeId )
48     , m_iVerboseLevel( iVerboseLevel )
49     , m_pFilename( 0 )
50     , m_id(0)
51     , m_receiveProcessor ( 0 )
52     , m_receiveProcessorBandwidth ( -1 )
53     , m_transmitProcessor ( 0 )
54     , m_transmitProcessorBandwidth ( -1 )
55 {
56     setDebugLevel( iVerboseLevel );
57    
58     debugOutput( DEBUG_LEVEL_VERBOSE, "Created MAudio::AvDevice (NodeID %d)\n",
59                  iNodeId );
60 }
61
62 AvDevice::~AvDevice()
63 {
64 }
65
66 ConfigRom&
67 AvDevice::getConfigRom() const
68 {
69     return *m_pConfigRom;
70 }
71
72 struct VendorModelEntry {
73     unsigned int m_iVendorId;
74     unsigned int m_iModelId;
75     const char*  m_pFilename;
76 };
77
78 static VendorModelEntry supportedDeviceList[] =
79 {
80     //{0x0007f5, 0x00010048, "refdesign.xml"},  // BridgeCo, RD Audio1
81
82     {0x000d6c, 0x00010046, "fw410.xml"},       // M-Audio, FW 410
83     {0x000d6c, 0x00010058, "fw410.xml"},       // M-Audio, FW 410; Version 5.10.0.5036
84     {0x000d6c, 0x00010060, "fwap.xml"},        // M-Audio, FW Audiophile (to be verified);
85
86    
87 };
88
89 bool
90 AvDevice::probe( ConfigRom& configRom )
91 {
92     unsigned int iVendorId = configRom.getNodeVendorId();
93     unsigned int iModelId = configRom.getModelId();
94
95     for ( unsigned int i = 0;
96           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
97           ++i )
98     {
99         if ( ( supportedDeviceList[i].m_iVendorId == iVendorId )
100              && ( supportedDeviceList[i].m_iModelId == iModelId ) )
101         {
102             return true;
103         }
104     }
105
106     return false;
107 }
108
109 bool
110 AvDevice::discover()
111 {
112     unsigned int iVendorId = m_pConfigRom->getNodeVendorId();
113     unsigned int iModelId = m_pConfigRom->getModelId();
114     for ( unsigned int i = 0;
115           i < ( sizeof( supportedDeviceList )/sizeof( VendorModelEntry ) );
116           ++i )
117     {
118         if ( ( supportedDeviceList[i].m_iVendorId == iVendorId )
119              && ( supportedDeviceList[i].m_iModelId == iModelId ) )
120         {
121             m_pFilename = supportedDeviceList[i].m_pFilename;
122             break;
123         }
124     }
125
126     return m_pFilename != 0;   
127    
128 }
129
130 bool
131 AvDevice::setSamplingFrequency( ESamplingFrequency eSamplingFrequency )
132 {
133     // not supported
134     return false;
135 }
136
137 int AvDevice::getSamplingFrequency( ) {
138     return 44100;
139 }
140
141
142 void
143 AvDevice::showDevice() const
144 {
145 }
146
147 bool
148 AvDevice::addXmlDescription( xmlNodePtr pDeviceNode )
149 {
150     char* pFilename;
151     if ( asprintf( &pFilename, "%s/libfreebob/maudio/%s", DATADIR, m_pFilename ) < 0 ) {
152         debugError( "addXmlDescription: Could not create filename string\n" );
153         return false;
154     }
155
156     xmlDocPtr pDoc = xmlParseFile( pFilename );
157
158     if ( !pDoc ) {
159         debugError( "addXmlDescription: No file '%s' found'\n", pFilename );
160         free( pFilename );
161         return false;;
162     }
163
164     xmlNodePtr pCur = xmlDocGetRootElement( pDoc );
165     if ( !pCur ) {
166         debugError( "addXmlDescription: Document '%s' has not root element\n", pFilename );
167         xmlFreeDoc( pDoc );
168         free( pFilename );
169         return false;
170     }
171
172     if ( xmlStrcmp( pCur->name, ( const xmlChar * ) "FreeBoBConnectionInfo" ) ) {
173         debugError( "addXmlDescription: No node 'FreeBoBConnectionInfo' found\n" );
174         xmlFreeDoc( pDoc );
175         free( pFilename );
176         return false;
177     }
178
179     pCur = pCur->xmlChildrenNode;
180     while ( pCur ) {
181         if ( !xmlStrcmp( pCur->name, ( const xmlChar * ) "Device" ) ) {
182             break;
183         }
184         pCur = pCur->next;
185     }
186
187     if ( pCur ) {
188         pCur = pCur->xmlChildrenNode;
189         while ( pCur ) {
190             if ( ( !xmlStrcmp( pCur->name, ( const xmlChar * ) "ConnectionSet" ) ) ) {
191                 xmlNodePtr pDevDesc = xmlCopyNode( pCur, 1 );
192                 if ( !pDevDesc ) {
193                     debugError( "addXmlDescription: Could not copy node 'ConnectionSet'\n" );
194                     xmlFreeDoc( pDoc );
195                     free( pFilename );
196                     return false;
197                 }
198
199                 // set correct node id
200                 for ( xmlNodePtr pNode = pDevDesc->xmlChildrenNode; pNode; pNode = pNode->next ) {
201                     if ( ( !xmlStrcmp( pNode->name,  ( const xmlChar * ) "Connection" ) ) ) {
202                         for ( xmlNodePtr pSubNode = pNode->xmlChildrenNode; pSubNode; pSubNode = pSubNode->next ) {
203                             if ( ( !xmlStrcmp( pSubNode->name,  ( const xmlChar * ) "Node" ) ) ) {
204                                 char* result;
205                                 asprintf( &result, "%d", m_iNodeId );
206                                 xmlNodeSetContent( pSubNode, BAD_CAST result );
207                                 free( result );
208                             }
209                         }
210                     }
211                 }
212
213                 xmlAddChild( pDeviceNode, pDevDesc );
214             }
215             if ( ( !xmlStrcmp( pCur->name, ( const xmlChar * ) "StreamFormats" ) ) ) {
216                 xmlNodePtr pDevDesc = xmlCopyNode( pCur, 1 );
217                 if ( !pDevDesc ) {
218                     debugError( "addXmlDescription: Could not copy node 'StreamFormats'\n" );
219                     xmlFreeDoc( pDoc );
220                     free( pFilename );
221                     return false;
222                 }
223                 xmlAddChild( pDeviceNode, pDevDesc );
224             }
225
226             pCur = pCur->next;
227         }
228     }
229
230     xmlFreeDoc( pDoc );
231     free( pFilename );
232
233     return true;
234 }
235
236 bool AvDevice::setId( unsigned int id)
237 {
238     // FIXME: decent ID system nescessary
239     m_id=id;
240     return true;
241 }
242
243 bool
244 AvDevice::prepare() {
245 /*    ///////////
246     // get plugs
247
248     AvPlug* inputplug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Input, 0 );
249     if ( !inputplug ) {
250         debugError( "setSampleRate: Could not retrieve iso input plug 0\n" );
251         return false;
252     }
253     AvPlug* outputPlug = getPlugById( m_pcrPlugs, AvPlug::eAPD_Output, 0 );
254     if ( !inputplug ) {
255         debugError( "setSampleRate: Could not retrieve iso output plug 0\n" );
256         return false;
257     }
258
259     int samplerate=outputPlug->getSampleRate();
260     m_receiveProcessor=new FreebobStreaming::AmdtpReceiveStreamProcessor(
261                              m_p1394Service->getPort(),
262                              samplerate,
263                              outputPlug->getNrOfChannels());
264
265     if(!m_receiveProcessor->init()) {
266         debugFatal("Could not initialize receive processor!\n");
267         return false;
268     }
269
270     if (!addPlugToProcessor(*outputPlug,m_receiveProcessor,
271         FreebobStreaming::AmdtpAudioPort::E_Capture)) {
272         debugFatal("Could not add plug to processor!\n");
273         return false;
274     }
275
276     // do the transmit processor
277 //     if (m_snoopMode) {
278 //         // we are snooping, so these are receive too.
279 //         samplerate=inputPlug->getSampleRate();
280 //         m_receiveProcessor2=new FreebobStreaming::AmdtpReceiveStreamProcessor(
281 //                                   channel,
282 //                                   m_p1394Service->getPort(),
283 //                                   samplerate,
284 //                                   inputPlug->getNrOfChannels());
285 //         
286 //         if(!m_receiveProcessor2->init()) {
287 //             debugFatal("Could not initialize snooping receive processor!\n");
288 //             return false;
289 //         }
290 //         if (!addPlugToProcessor(*inputPlug,m_receiveProcessor2,
291 //             FreebobStreaming::AmdtpAudioPort::E_Capture)) {
292 //             debugFatal("Could not add plug to processor!\n");
293 //             return false;
294 //         }
295 //     } else {
296         // do the transmit processor
297         samplerate=inputPlug->getSampleRate();
298         m_transmitProcessor=new FreebobStreaming::AmdtpTransmitStreamProcessor(
299                                 m_p1394Service->getPort(),
300                                 samplerate,
301                                 inputPlug->getNrOfChannels());
302                                
303         if(!m_transmitProcessor->init()) {
304             debugFatal("Could not initialize transmit processor!\n");
305             return false;
306        
307         }
308        
309         // FIXME: do this the proper way!
310         m_transmitProcessor->syncmaster=m_receiveProcessor;
311    
312         if (!addPlugToProcessor(*inputPlug,m_transmitProcessor,
313             FreebobStreaming::AmdtpAudioPort::E_Playback)) {
314             debugFatal("Could not add plug to processor!\n");
315             return false;
316         }
317 //     }
318 */
319     return true;
320 }
321
322 // bool
323 // AvDevice::addPlugToProcessor(
324 //     AvPlug& plug,
325 //     FreebobStreaming::StreamProcessor *processor,
326 //     FreebobStreaming::AmdtpAudioPort::E_Direction direction) {
327 //
328 //     AvPlug::ClusterInfoVector& clusterInfos = plug.getClusterInfos();
329 //     for ( AvPlug::ClusterInfoVector::const_iterator it = clusterInfos.begin();
330 //           it != clusterInfos.end();
331 //           ++it )
332 //     {
333 //         const AvPlug::ClusterInfo* clusterInfo = &( *it );
334 //
335 //         AvPlug::ChannelInfoVector channelInfos = clusterInfo->m_channelInfos;
336 //         for ( AvPlug::ChannelInfoVector::const_iterator it = channelInfos.begin();
337 //               it != channelInfos.end();
338 //               ++it )
339 //         {
340 //             const AvPlug::ChannelInfo* channelInfo = &( *it );
341 //             std::ostringstream portname;
342 //             
343 //             portname << "dev" << m_id << "_" << channelInfo->m_name;
344 //             
345 //             FreebobStreaming::Port *p=NULL;
346 //             switch(clusterInfo->m_portType) {
347 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Speaker:
348 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Headphone:
349 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Microphone:
350 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Line:
351 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Analog:
352 //                 p=new FreebobStreaming::AmdtpAudioPort(
353 //                         portname.str(),
354 //                         direction,
355 //                         // \todo: streaming backend expects indexing starting from 0
356 //                         // but bebob reports it starting from 1. Decide where
357 //                         // and how to handle this (pp: here)
358 //                         channelInfo->m_streamPosition - 1,
359 //                         channelInfo->m_location,
360 //                         FreebobStreaming::AmdtpPortInfo::E_MBLA,
361 //                         clusterInfo->m_portType
362 //                 );
363 //                 break;
364 //
365 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MIDI:
366 //                 p=new FreebobStreaming::AmdtpMidiPort(
367 //                         portname.str(),
368 //                         direction,
369 //                         // \todo: streaming backend expects indexing starting from 0
370 //                         // but bebob reports it starting from 1. Decide where
371 //                         // and how to handle this (pp: here)
372 //                         channelInfo->m_streamPosition - 1,
373 //                         channelInfo->m_location,
374 //                         FreebobStreaming::AmdtpPortInfo::E_Midi,
375 //                         clusterInfo->m_portType
376 //                 );
377 //
378 //                 break;
379 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_SPDIF:
380 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_ADAT:
381 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_TDIF:
382 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_MADI:
383 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_Digital:
384 //             case ExtendedPlugInfoClusterInfoSpecificData::ePT_NoType:
385 //             default:
386 //             // unsupported
387 //                 break;
388 //             }
389 //
390 //             if (!p) {
391 //                 debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",channelInfo->m_name.c_str());
392 //             } else {
393 //         
394 //                 if (!processor->addPort(p)) {
395 //                     debugWarning("Could not register port with stream processor\n");
396 //                     return false;
397 //                 }
398 //             }
399 //          }
400 //     }
401 //     return true;
402 // }
403
404 int
405 AvDevice::getStreamCount() {
406     return 0;
407 //     return 2; // one receive, one transmit
408 }
409
410 FreebobStreaming::StreamProcessor *
411 AvDevice::getStreamProcessorByIndex(int i) {
412     switch (i) {
413     case 0:
414         return m_receiveProcessor;
415     case 1:
416 //         if (m_snoopMode) {
417 //             return m_receiveProcessor2;
418 //         } else {
419             return m_transmitProcessor;
420 //         }
421     default:
422         return NULL;
423     }
424     return 0;
425 }
426
427 int
428 AvDevice::startStreamByIndex(int i) {
429     int iso_channel=0;
430     int plug=0;
431     int hostplug=-1;
432    
433 //     if (m_snoopMode) {
434 //     
435 //         switch (i) {
436 //         case 0:
437 //             // snooping doesn't use CMP, but obtains the info of the channel
438 //             // from the target plug
439 //             
440 //             // TODO: get isochannel from plug
441 //             
442 //             // set the channel obtained by the connection management
443 //             m_receiveProcessor->setChannel(iso_channel);
444 //             break;
445 //         case 1:
446 //             // snooping doesn't use CMP, but obtains the info of the channel
447 //             // from the target plug
448 //             
449 //             // TODO: get isochannel from plug
450 //             
451 //             // set the channel obtained by the connection management
452 //             m_receiveProcessor2->setChannel(iso_channel);
453 //
454 //             break;
455 //         default:
456 //             return 0;
457 //         }
458 //     } else {
459    
460         switch (i) {
461         case 0:
462             // do connection management: make connection
463             iso_channel = iec61883_cmp_connect(
464                 m_p1394Service->getHandle(),
465                 m_iNodeId | 0xffc0,
466                 &plug,
467                 raw1394_get_local_id (m_p1394Service->getHandle()),
468                 &hostplug,
469                 &m_receiveProcessorBandwidth);
470            
471             // set the channel obtained by the connection management
472             m_receiveProcessor->setChannel(iso_channel);
473             break;
474         case 1:
475             // do connection management: make connection
476             iso_channel = iec61883_cmp_connect(
477                 m_p1394Service->getHandle(),
478                 raw1394_get_local_id (m_p1394Service->getHandle()),
479                 &hostplug,
480                 m_iNodeId | 0xffc0,
481                 &plug,
482                 &m_transmitProcessorBandwidth);
483            
484             // set the channel obtained by the connection management
485             m_transmitProcessor->setChannel(iso_channel);
486             break;
487         default:
488             return 0;
489         }
490 //     }
491    
492     return 0;
493
494 }
495
496 int
497 AvDevice::stopStreamByIndex(int i) {
498     // do connection management: break connection
499
500     int plug=0;
501     int hostplug=-1;
502 //     if (m_snoopMode) {
503 //         switch (i) {
504 //         case 0:
505 //             // do connection management: break connection
506 //     
507 //             break;
508 //         case 1:
509 //             // do connection management: break connection
510 //
511 //             break;
512 //         default:
513 //             return 0;
514 //         }
515 //     } else {
516         switch (i) {
517         case 0:
518             // do connection management: break connection
519             iec61883_cmp_disconnect(
520                 m_p1394Service->getHandle(),
521                 m_iNodeId | 0xffc0,
522                 plug,
523                 raw1394_get_local_id (m_p1394Service->getHandle()),
524                 hostplug,
525                 m_receiveProcessor->getChannel(),
526                 m_receiveProcessorBandwidth);
527    
528             break;
529         case 1:
530             // do connection management: break connection
531             iec61883_cmp_disconnect(
532                 m_p1394Service->getHandle(),
533                 raw1394_get_local_id (m_p1394Service->getHandle()),
534                 hostplug,
535                 m_iNodeId | 0xffc0,
536                 plug,
537                 m_transmitProcessor->getChannel(),
538                 m_transmitProcessorBandwidth);
539
540             break;
541         default:
542             return 0;
543         }
544 //     }
545    
546     return 0;
547 }
548
549 }
550
551 #endif //#ifdef ENABLE_BEBOB
Note: See TracBrowser for help on using the browser.