root/branches/libfreebob-2.0/src/maudio/maudio_avdevice.cpp

Revision 338, 17.2 kB (checked in by pieterpalmers, 16 years ago)

add xml file for maudio fw audiophile (experimental)

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