root/branches/libfreebob-2.0/src/motu/motu_avdevice.cpp

Revision 265, 13.1 kB (checked in by jwoithe, 18 years ago)

Start adding detail in MOTU port infrastructure.
Clean up some "signed/unsigned comparison" compiler warnings.

Line 
1 /* motu_avdevice.cpp
2  * Copyright (C) 2006 by Pieter Palmers
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 "motu/motu_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 "libstreaming/MotuStreamProcessor.h"
30 #include "libstreaming/MotuPort.h"
31
32 #include <string>
33 #include <stdint.h>
34 #include <assert.h>
35 #include <netinet/in.h>
36
37 namespace Motu {
38
39 IMPL_DEBUG_MODULE( MotuDevice, MotuDevice, DEBUG_LEVEL_NORMAL );
40
41 char *motufw_modelname[] = {"[unknown]","828MkII", "Traveler"};
42
43 MotuDevice::MotuDevice( Ieee1394Service& ieee1394service,
44                         int nodeId,
45                         int verboseLevel )
46     : m_1394Service( &ieee1394service )
47     , m_motu_model( MOTUFW_MODEL_NONE )
48     , m_nodeId( nodeId )
49     , m_verboseLevel( verboseLevel )
50     , m_id(0)
51     , m_receiveProcessor ( 0 )
52     , m_transmitProcessor ( 0 )
53    
54 {
55     if ( m_verboseLevel ) {
56         setDebugLevel( DEBUG_LEVEL_VERBOSE );
57     }
58     debugOutput( DEBUG_LEVEL_VERBOSE, "Created Motu::MotuDevice (NodeID %d)\n",
59                  nodeId );
60     m_configRom = new ConfigRom( m_1394Service, m_nodeId );
61     m_configRom->initialize();
62
63 }
64
65 MotuDevice::~MotuDevice()
66 {
67         delete m_configRom;
68 }
69
70 ConfigRom&
71 MotuDevice::getConfigRom() const
72 {
73     return *m_configRom;
74 }
75
76 bool
77 MotuDevice::discover()
78 {
79         // Find out if this device is one we know about
80         if (m_configRom->getUnitSpecifierId() == MOTUFW_VENDOR_MOTU) {
81                 switch (m_configRom->getUnitVersion()) {
82                     case MOTUFW_UNITVER_828mkII:
83                         m_motu_model = MOTUFW_MODEL_828mkII;
84                         break;
85                     case MOTUFW_UNITVER_TRAVELER:
86                         m_motu_model = MOTUFW_MODEL_TRAVELER;
87                         break;
88                 }
89         }
90         if (m_motu_model != MOTUFW_MODEL_NONE) {
91                 debugOutput( DEBUG_LEVEL_VERBOSE, "found MOTU %s\n",
92                         motufw_modelname[m_motu_model]);
93                 return true;
94         }
95
96     return false;
97 }
98
99 int
100 MotuDevice::getSamplingFrequency( ) {
101     /*
102      Implement the procedure to retrieve the samplerate here
103     */
104     quadlet_t q = ReadRegister(MOTUFW_REG_RATECTRL);
105     int rate = 0;
106
107     switch (q & ~MOTUFW_BASE_RATE_MASK) {
108         case MOTUFW_BASE_RATE_44100:
109             rate = 44100;
110             break;
111         case MOTUFW_BASE_RATE_48000:
112             rate = 48000;
113             break;
114     }
115     switch (q & ~MOTUFW_RATE_MULTIPLIER_MASK) {
116         case MOTUFW_RATE_MULTIPLIER_2X:
117             rate *= 2;
118             break;
119         case MOTUFW_RATE_MULTIPLIER_4X:
120             rate *= 4;
121             break;
122     }
123     return rate;
124 }
125
126 bool
127 MotuDevice::setSamplingFrequency( ESamplingFrequency samplingFrequency )
128 {
129     /*
130      Implement the procedure to set the samplerate here
131     */
132
133     quadlet_t new_rate=0;
134         int supported=true;
135
136     switch ( samplingFrequency ) {
137         case eSF_22050Hz:
138             supported=false;
139             break;
140         case eSF_24000Hz:
141             supported=false;
142             break;
143         case eSF_32000Hz:
144             supported=false;
145             break;
146         case eSF_44100Hz:
147             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_1X;
148             break;
149         case eSF_48000Hz:
150             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_1X;
151             break;
152         case eSF_88200Hz:
153             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_2X;
154             break;
155         case eSF_96000Hz:
156             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_2X;
157             break;
158         case eSF_176400Hz:
159             new_rate = MOTUFW_BASE_RATE_44100 | MOTUFW_RATE_MULTIPLIER_4X;
160             break;
161         case eSF_192000Hz:
162             new_rate = MOTUFW_BASE_RATE_48000 | MOTUFW_RATE_MULTIPLIER_4X;
163             break;
164         default:
165             supported=false;
166     }
167
168     // update the register.  FIXME: there's more to it than this
169     if (supported) {
170         quadlet_t value=ReadRegister(MOTUFW_REG_RATECTRL);
171         value &= ~(MOTUFW_BASE_RATE_MASK|MOTUFW_RATE_MULTIPLIER_MASK);
172         value |= new_rate;
173 //        value |= 0x04000000;
174         if (WriteRegister(MOTUFW_REG_RATECTRL, value) == 0) {
175             supported=true;
176         } else {
177             supported=false;
178         }
179     }
180     return supported;
181 }
182
183 bool MotuDevice::setId( unsigned int id) {
184     debugOutput( DEBUG_LEVEL_VERBOSE, "Set id to %d...\n", id);
185     m_id=id;
186     return true;
187 }
188
189 void
190 MotuDevice::showDevice() const
191 {
192     printf( "MOTU %s at node %d\n",
193         motufw_modelname[m_motu_model],
194         m_nodeId );
195 }
196
197 bool
198 MotuDevice::prepare() {
199
200     debugOutput(DEBUG_LEVEL_NORMAL, "Preparing MotuDevice...\n" );
201
202         m_receiveProcessor=new FreebobStreaming::MotuReceiveStreamProcessor(
203                                  m_1394Service->getPort(),
204                                  getSamplingFrequency());
205                                  
206         // the first thing is to initialize the processor
207         // this creates the data structures
208         if(!m_receiveProcessor->init()) {
209                 debugFatal("Could not initialize receive processor!\n");
210                 return false;
211        
212         }
213
214     // now we add ports to the processor
215     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to receive processor\n");
216        
217         // TODO: change this into something based upon device detection/configuration
218        
219     char *buff;
220     FreebobStreaming::Port *p=NULL;
221    
222         // example of adding an audio port:
223     asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
224    
225     p=new FreebobStreaming::MotuAudioPort(
226             buff,
227             FreebobStreaming::Port::E_Capture,
228             0,
229             0 // you can add all other port specific stuff you
230               // need to pass by extending MotuXXXPort and MotuPortInfo
231     );
232    
233     free(buff);
234
235     if (!p) {
236         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
237     } else {
238
239         if (!m_receiveProcessor->addPort(p)) {
240             debugWarning("Could not register port with stream processor\n");
241             return false;
242         } else {
243             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
244        
245         }
246     }
247    
248         // example of adding an midi port:
249     asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
250    
251     p=new FreebobStreaming::MotuMidiPort(
252             buff,
253             FreebobStreaming::Port::E_Capture,
254             0 // you can add all other port specific stuff you
255               // need to pass by extending MotuXXXPort and MotuPortInfo
256     );
257    
258     free(buff);
259
260     if (!p) {
261         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
262     } else {
263
264         if (!m_receiveProcessor->addPort(p)) {
265             debugWarning("Could not register port with stream processor\n");
266             return false;
267         } else {
268             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
269        
270         }
271     }
272    
273         // example of adding an control port:
274     asprintf(&buff,"dev%d_cap_%s",m_id,"myportnamehere");
275    
276     p=new FreebobStreaming::MotuControlPort(
277             buff,
278             FreebobStreaming::Port::E_Capture,
279             0 // you can add all other port specific stuff you
280               // need to pass by extending MotuXXXPort and MotuPortInfo
281     );
282    
283     free(buff);
284
285     if (!p) {
286         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
287     } else {
288
289         if (!m_receiveProcessor->addPort(p)) {
290             debugWarning("Could not register port with stream processor\n");
291             return false;
292         } else {
293             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
294        
295         }
296     }
297
298
299         // do the same for the transmit processor
300         m_transmitProcessor=new FreebobStreaming::MotuTransmitStreamProcessor(
301                                  m_1394Service->getPort(),
302                                  getSamplingFrequency());
303                                  
304         m_transmitProcessor->setVerboseLevel(getDebugLevel());
305        
306         if(!m_transmitProcessor->init()) {
307                 debugFatal("Could not initialize transmit processor!\n");
308                 return false;
309        
310         }
311
312     // now we add ports to the processor
313     debugOutput(DEBUG_LEVEL_VERBOSE,"Adding ports to transmit processor\n");
314    
315         // example of adding an audio port:
316         // we change the naming and the direction to E_Playback
317     asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
318    
319     p=new FreebobStreaming::MotuAudioPort(
320             buff,
321             FreebobStreaming::Port::E_Playback,
322             0,
323             0 // you can add all other port specific stuff you
324               // need to pass by extending MotuXXXPort and MotuPortInfo
325     );
326    
327     free(buff);
328
329     if (!p) {
330         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
331     } else {
332
333         if (!m_transmitProcessor->addPort(p)) {
334             debugWarning("Could not register port with stream processor\n");
335             return false;
336         } else {
337             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
338        
339         }
340     }
341    
342         // example of adding an midi port:
343     asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
344    
345     p=new FreebobStreaming::MotuMidiPort(
346             buff,
347             FreebobStreaming::Port::E_Playback,
348             0 // you can add all other port specific stuff you
349               // need to pass by extending MotuXXXPort and MotuPortInfo
350     );
351    
352     free(buff);
353
354     if (!p) {
355         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
356     } else {
357
358         if (!m_transmitProcessor->addPort(p)) {
359             debugWarning("Could not register port with stream processor\n");
360             return false;
361         } else {
362             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
363        
364         }
365     }
366    
367         // example of adding an control port:
368     asprintf(&buff,"dev%d_pbk_%s",m_id,"myportnamehere");
369    
370     p=new FreebobStreaming::MotuControlPort(
371             buff,
372             FreebobStreaming::Port::E_Playback,
373             0 // you can add all other port specific stuff you
374               // need to pass by extending MotuXXXPort and MotuPortInfo
375     );
376    
377     free(buff);
378
379     if (!p) {
380         debugOutput(DEBUG_LEVEL_VERBOSE, "Skipped port %s\n",buff);
381     } else {
382
383         if (!m_transmitProcessor->addPort(p)) {
384             debugWarning("Could not register port with stream processor\n");
385             return false;
386         } else {
387             debugOutput(DEBUG_LEVEL_VERBOSE, "Added port %s\n",buff);
388        
389         }
390     }
391        
392         return true;
393 }
394
395 int
396 MotuDevice::getStreamCount() {
397         return 2; // one receive, one transmit
398 }
399
400 FreebobStreaming::StreamProcessor *
401 MotuDevice::getStreamProcessorByIndex(int i) {
402         switch (i) {
403         case 0:
404                 return m_receiveProcessor;
405         case 1:
406                 return m_transmitProcessor;
407         default:
408                 return NULL;
409         }
410         return 0;
411 }
412
413 int
414 MotuDevice::startStreamByIndex(int i) {
415
416     // NOTE: this assumes that you have two streams
417         switch (i) {
418         case 0:
419         // TODO: do the stuff that is nescessary to make the device
420         // transmit a stream
421
422
423                 // set the streamprocessor channel to the one obtained by
424                 // the connection management
425                 // IMPORTANT!!
426                 m_receiveProcessor->setChannel(1); // TODO: change the channel NR
427                 break;
428         case 1:
429         // TODO: do the stuff that is nescessary to make the device
430         // receive a stream
431
432                 // set the streamprocessor channel to the one obtained by
433                 // the connection management
434                 // IMPORTANT!!
435                 m_transmitProcessor->setChannel(0); // TODO: change the channel NR
436                 break;
437                
438         default: // invalid index
439                 return -1;
440         }
441
442         return 0;
443
444 }
445
446 int
447 MotuDevice::stopStreamByIndex(int i) {
448         // TODO: connection management: break connection
449         // cfr the start function
450
451         return 0;
452 }
453
454
455
456
457 /* ======================================================================== */
458
459 unsigned int MotuDevice::ReadRegister(unsigned int reg) {
460 /*
461  * Attempts to read the requested register from the MOTU.
462  */
463
464 quadlet_t quadlet;
465 assert(m_1394Service);
466        
467   quadlet = 0;
468   // Note: 1394Service::read() expects a physical ID, not the node id
469   if (m_1394Service->read(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &quadlet) < 0) {
470     debugError("Error doing motu read from register 0x%06x\n",reg);
471   }
472
473   return ntohl(quadlet);
474 }
475
476 signed int MotuDevice::WriteRegister(unsigned int reg, quadlet_t data) {
477 /*
478  * Attempts to write the given data to the requested MOTU register.
479  */
480
481   unsigned int err = 0;
482   data = htonl(data);
483
484   // Note: 1394Service::write() expects a physical ID, not the node id
485   if (m_1394Service->write(0xffc0 | m_nodeId, MOTUFW_BASE_ADDR+reg, 4, &data) < 0) {
486     err = 1;
487     debugError("Error doing motu write to register 0x%06x\n",reg);
488   }
489
490   usleep(100);
491   return (err==0)?0:-1;
492 }
493
494 }
Note: See TracBrowser for help on using the browser.