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

Revision 412, 17.3 kB (checked in by pieterpalmers, 16 years ago)

- added some documentation
- added a lock()/unlock() to IAvDevice (see header)
- reimplemented test-freebob to the new C++ api
- started with support for AddressRangeMapping?, i.e. response

to reads/writes of the 1394 memory space on the host

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