root/branches/libfreebob-2.0/src/libstreaming/MotuStreamProcessor.cpp

Revision 310, 44.4 kB (checked in by jwoithe, 16 years ago)

MOTU: fix optical mode detection and clear up some associated packet sizing issues.

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005,2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *   Copyright (C) 2006 Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
11  *
12  *   This program is free software {} you can redistribute it and/or modify
13  *   it under the terms of the GNU General Public License as published by
14  *   the Free Software Foundation {} either version 2 of the License, or
15  *   (at your option) any later version.
16  *
17  *   This program is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with this program {} if not, write to the Free Software
24  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  *
27  *
28  */
29
30
31 #include "MotuStreamProcessor.h"
32 #include "Port.h"
33 #include "MotuPort.h"
34
35 #include <math.h>
36
37 #include <netinet/in.h>
38
39 namespace FreebobStreaming {
40
41 IMPL_DEBUG_MODULE( MotuTransmitStreamProcessor, MotuTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
42 IMPL_DEBUG_MODULE( MotuReceiveStreamProcessor, MotuReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
43
44 // Set to 1 to enable the generation of a 1 kHz test tone in analog output 1
45 #define TESTTONE 1
46
47 // A macro to extract specific bits from a native endian quadlet
48 #define get_bits(_d,_start,_len) (((_d)>>((_start)-(_len)+1)) & ((1<<(_len))-1))
49
50 /* transmit */
51 MotuTransmitStreamProcessor::MotuTransmitStreamProcessor(int port, int framerate,
52                 unsigned int event_size)
53         : TransmitStreamProcessor(port, framerate), m_event_size(event_size),
54         m_tx_dbc(0), m_cycle_count(-1), m_cycle_ofs(0.0), m_next_cycle(-1),
55         m_ticks_per_frame(NULL), m_closedown_count(-1), m_streaming_active(0) {
56 }
57
58 MotuTransmitStreamProcessor::~MotuTransmitStreamProcessor() {
59         freebob_ringbuffer_free(m_event_buffer);
60         free(m_tmp_event_buffer);
61 }
62
63 bool MotuTransmitStreamProcessor::init() {
64
65         debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing (%p)...\n");
66         // call the parent init
67         // this has to be done before allocating the buffers,
68         // because this sets the buffersizes from the processormanager
69         if(!TransmitStreamProcessor::init()) {
70                 debugFatal("Could not do base class init (%p)\n",this);
71                 return false;
72         }
73         m_next_cycle = -1;
74         m_closedown_count = -1;
75         m_streaming_active = 0;
76         m_cycle_count = -1;
77         m_cycle_ofs = 0.0;
78
79         return true;
80 }
81
82 void MotuTransmitStreamProcessor::setVerboseLevel(int l) {
83         setDebugLevel(l); // sets the debug level of the current object
84         TransmitStreamProcessor::setVerboseLevel(l); // also set the level of the base class
85 }
86
87
88 enum raw1394_iso_disposition
89 MotuTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
90                       unsigned char *tag, unsigned char *sy,
91                       int cycle, unsigned int dropped, unsigned int max_length) {
92
93 // FIXME: the actual delays in the system need to be worked out so
94 // we can get this thing synchronised.  For now this seems to work.
95 #define CYCLE_DELAY 1
96
97         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
98         quadlet_t *quadlet = (quadlet_t *)data;
99         signed int i;
100         signed int unwrapped_cycle = cycle;
101
102         // Signal that streaming is still active
103         m_streaming_active = 1;
104
105         // The MOTU transmit stream is 'always' ready
106         m_running = true;
107        
108         // Initialise the cycle counter if this is the first time
109         // iso data has been requested.
110         if (!m_disabled && m_cycle_count<0) {
111                 m_cycle_count = cycle;
112                 m_cycle_ofs = 0.0;
113         }
114
115         // Similarly, initialise the "next cycle".  This can be done
116         // whenever iso data is seen - it doesn't have to wait until
117         // the stream is initialised.
118         if (m_next_cycle < 0)
119                 m_next_cycle = cycle;
120
121         // Do housekeeping expected for all packets sent to the MOTU, even
122         // for packets containing no audio data.
123         *sy = 0x00;
124         *tag = 1;      // All MOTU packets have a CIP-like header
125
126         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "get packet...\n");
127
128         // Size of a single data frame in quadlets
129         unsigned dbs = m_event_size / 4;
130
131         // The number of events expected by the MOTU is solely dependent on
132         // the current sample rate.  An 'event' is one sample from all channels
133         // plus possibly other midi and control data.
134         signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32);
135
136         // Size of data to read from the event buffer, in bytes.
137         unsigned int read_size = n_events * m_event_size;
138
139         // Detect a missed cycle and attempt to "catch up".
140         if (!m_disabled && m_next_cycle>=0 && cycle!=m_next_cycle) {
141                 float ftmp;
142                 signed int ccount = m_next_cycle;
143                 debugOutput(DEBUG_LEVEL_VERBOSE, "tx cycle miss: %d requested, %d expected\n",cycle,m_next_cycle);
144
145                 while (ccount!=cycle) {
146                         unwrapped_cycle = ccount;
147                         if (m_cycle_count-ccount > 7900)
148                                 unwrapped_cycle += 8000;
149
150                         if (unwrapped_cycle < m_cycle_count) {
151                                 if (++ccount == 8000)
152                                         ccount = 0;
153                                 continue;
154                         }
155                         // Advance buffers and counters as if this cycle had been dealt with
156                         m_tx_dbc += n_events;
157                         incrementFrameCounter(n_events);
158
159                         ftmp = m_cycle_ofs+n_events*(*m_ticks_per_frame);
160                         m_cycle_count += (unsigned int)ftmp/3072;
161                         m_cycle_count %= 8000;
162                         m_cycle_ofs = fmod(ftmp, 3072);
163
164                         if (++ccount == 8000)
165                                 ccount = 0;
166
167                         // Also advance the event buffer to keep things in sync
168                         freebob_ringbuffer_read_advance(m_event_buffer,read_size);
169                 }
170                 m_tx_dbc &= 0xff;
171                 debugOutput(DEBUG_LEVEL_VERBOSE, "  resuming with cyclecount=%d, cycleofs=%g (ticksperfame=%g)\n",
172                         m_cycle_count, m_cycle_ofs, *m_ticks_per_frame);
173
174                 m_next_cycle = cycle;
175         }
176
177         if  (!m_disabled) {
178                 if (++m_next_cycle >= 8000)
179                         m_next_cycle -= 8000;
180         } else
181                 m_next_cycle = -1;
182
183         // Deal cleanly with potential wrap-around cycle counter conditions
184         unwrapped_cycle = cycle;
185         if (m_cycle_count-cycle > 7900)
186                 unwrapped_cycle += 8000;
187
188         // Increment the dbc (data block count).  This is only done if the
189         // packet will contain events - that is, we are due to send some
190         // data.  Otherwise a pad packet is sent which contains the DBC of
191         // the previously sent packet.  This regime also means that the very
192         // first packet containing data will have a DBC of n_events, which
193         // matches what is observed from other systems.
194         if (!m_disabled && unwrapped_cycle>=m_cycle_count) {
195                 m_tx_dbc += n_events;
196                 if (m_tx_dbc > 0xff)
197                         m_tx_dbc -= 0x100;
198         }
199
200         // construct the packet CIP-like header.  Even if this is a data-less
201         // packet the dbs field is still set as if there were data blocks
202         // present.  For data-less packets the dbc is the same as the previously
203         // transmitted block.
204         *quadlet = htonl(0x00000400 | ((getNodeId()&0x3f)<<24) | m_tx_dbc | (dbs<<16));
205         quadlet++;
206         *quadlet = htonl(0x8222ffff);
207         quadlet++;
208         *length = 8;
209
210         // If the stream is disabled or the MOTU transmission cycle count is
211         // ahead of the ieee1394 cycle timer, we send a data-less packet
212         // with only the 8 byte CIP-like header set up previously.
213         if (m_disabled || unwrapped_cycle<m_cycle_count) {
214                 return RAW1394_ISO_OK;
215         }
216
217         // In the disabled state simply zero all data sent to the MOTU.  If
218         // a stream of empty packets are sent once iso streaming is enabled
219         // the MOTU tends to emit high-pitched audio (approx 10 kHz) for
220         // some reason.  This is not completely sufficient, however (zeroed
221         // packets must also be sent on iso closedown).
222
223         // FIXME: Currently we simply send empty packets to the MOTU when
224         // the stream is disabled so the "m_disabled == 0" code is never
225         // executed.  However, this may change in future so it's left in
226         // for the moment for reference.
227         // FIXME: Currently we don't read the buffer at all during closedown.
228         // We could (and silently junk the contents) if it turned out to be
229         // more helpful.
230         if (!m_disabled && m_closedown_count<0) {
231                 // We read the packet data from a ringbuffer because of
232                 // efficiency; it allows us to construct the packets one
233                 // period at once.
234                 i = freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size) <
235                         read_size;
236         } else {
237                 memset(data+8, 0, read_size);
238                 i = 0;
239         }
240         if (i == 1) {
241                 /* there is no more data in the ringbuffer */
242                 debugWarning("Transmit buffer underrun (cycle %d, FC=%d, PC=%d)\n",
243                         cycle, m_framecounter, m_handler->getPacketCount());
244
245                 // signal underrun
246                 m_xruns++;
247
248                 retval=RAW1394_ISO_DEFER; // make raw1394_loop_iterate exit its inner loop
249                 n_events = 0;
250
251         } else {
252                 retval=RAW1394_ISO_OK;
253                 *length += read_size;
254
255                 // FIXME: if we choose to read the buffer even during closedown,
256                 // here is where the data is silenced.
257                 //   if (m_closedown_count >= 0)
258                 //     memset(data+8, 0, read_size);
259                 if (m_closedown_count > 0)
260                         m_closedown_count--;
261
262                 // Set up each frames's SPH.  Note that the (int) typecast
263                 // appears to do rounding.
264                 //
265                 // CYCLE_DELAY accounts for the delay between the cycle
266                 // audio is sent in and when the MOTU can actually play
267                 // that audio.  The SPH timestamp must account for this
268                 // so it doesn't demand to be played before it's possible.
269                 // For the duration of the event loop, account for the
270                 // CYCLE_DELAY within m_cycle_count to save having to wrap
271                 // (m_cycle_count+CYCLE_DELAY) and m_cycle_count separately
272                 // within the event loop.  Once the loop is finished we
273                 // reset m_cyle_count to once again refer to the send
274                 // cycle rather than the audio presentation cycle.
275                 //
276                 // This seemingly messy treatment saves one modulo operation
277                 // per loop iteration.  Since the loop count ranges from 8
278                 // (for 1x sample rates) to 32 there are considerable
279                 // savings to be made even at 1x rates.
280                 if ((m_cycle_count+=CYCLE_DELAY) >= 8000)
281                         m_cycle_count -= 8000;
282                 for (i=0; i<n_events; i++, quadlet += dbs) {
283                         *quadlet = htonl( (m_cycle_count<<12) + (int)m_cycle_ofs);
284 #if TESTTONE
285                         // FIXME: remove this hacked in 1 kHz test signal to
286                         // analog-1 when testing is complete.  Note that the tone is
287                         // *never* added during closedown.
288                         if (m_closedown_count<0) {
289                                 static signed int a_cx = 0;
290                                 signed int val;
291                                 val = (int)(0x7fffff*sin(1000.0*2.0*M_PI*(a_cx/24576000.0)));
292                                 if ((a_cx+=512) >= 24576000) {
293                                         a_cx -= 24576000;
294                                 }
295                                 *(data+8+i*m_event_size+16) = (val >> 16) & 0xff;
296                                 *(data+8+i*m_event_size+17) = (val >> 8) & 0xff;
297                                 *(data+8+i*m_event_size+18) = val & 0xff;
298                         }
299 #endif
300                         if ((m_cycle_ofs+=*m_ticks_per_frame) >= 3072) {
301                                 m_cycle_ofs -= 3072;
302                                 if (++m_cycle_count > 7999)
303                                         m_cycle_count -= 8000;
304                         }
305                 }
306                 // Reset m_cycle_count to the send cycle
307                 if ((m_cycle_count-=CYCLE_DELAY) < 0)
308                         m_cycle_count += 8000;
309
310                 // Process all ports that should be handled on a per-packet base
311                 // this is MIDI for AMDTP (due to the need of DBC, which is lost
312                 // when putting the events in the ringbuffer)
313                 // for motu this might also be control data, however as control
314                 // data isn't time specific I would also include it in the period
315                 // based processing
316        
317                 // FIXME: m_tx_dbc probably needs to be initialised to a non-zero
318                 // value somehow so MIDI sync is possible.  For now we ignore
319                 // this issue.
320                 if (!encodePacketPorts((quadlet_t *)(data+8), n_events, m_tx_dbc)) {
321                         debugWarning("Problem encoding Packet Ports\n");
322                 }
323         }
324    
325         // Update the frame counter
326         incrementFrameCounter(n_events);
327
328         // Keep this at the end, because otherwise the raw1394_loop_iterate
329         // functions inner loop keeps requesting packets, that are not
330         // nescessarily ready
331
332 // Amdtp has this commented out
333         if (m_framecounter > (signed int)m_period) {
334                 retval=RAW1394_ISO_DEFER;
335         }
336        
337         return retval;
338 }
339
340 bool MotuTransmitStreamProcessor::isOnePeriodReady() {
341         // TODO: this is the way you can implement sync
342         //       only when this returns true, one period will be
343         //       transferred to the audio api side.
344         //       you can delay this moment as long as you
345         //       want (provided that there is enough buffer space)
346        
347         // this implementation just waits until there is one period of samples
348         // transmitted from the buffer
349
350 // Amdtp has this commented out and simply return true.
351         return (m_framecounter > (signed int)m_period);
352 //      return true;
353 }
354  
355 bool MotuTransmitStreamProcessor::prefill() {
356         // this is needed because otherwise there is no data to be
357         // sent when the streaming starts
358    
359         int i = m_nb_buffers;
360         while (i--) {
361                 if(!transferSilence(m_period)) {
362                         debugFatal("Could not prefill transmit stream\n");
363                         return false;
364                 }
365         }
366         return true;
367 }
368
369 bool MotuTransmitStreamProcessor::reset() {
370
371         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
372
373         // reset the event buffer, discard all content
374         freebob_ringbuffer_reset(m_event_buffer);
375    
376         // reset all non-device specific stuff
377         // i.e. the iso stream and the associated ports
378         if (!TransmitStreamProcessor::reset()) {
379                 debugFatal("Could not do base class reset\n");
380                 return false;
381         }
382
383         // we should prefill the event buffer
384         if (!prefill()) {
385                 debugFatal("Could not prefill buffers\n");
386                 return false;   
387         }
388
389         m_next_cycle = -1;
390         m_closedown_count = -1;
391         m_streaming_active = 0;
392         m_cycle_count = -1;
393         m_cycle_ofs = 0.0;
394
395         return true;
396 }
397
398 bool MotuTransmitStreamProcessor::prepare() {
399    
400         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
401    
402         // prepare all non-device specific stuff
403         // i.e. the iso stream and the associated ports
404         if (!TransmitStreamProcessor::prepare()) {
405                 debugFatal("Could not prepare base class\n");
406                 return false;
407         }
408
409         m_PeriodStat.setName("XMT PERIOD");
410         m_PacketStat.setName("XMT PACKET");
411         m_WakeupStat.setName("XMT WAKEUP");
412
413         debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
414    
415         // allocate the event buffer
416         unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
417    
418         if( !(m_event_buffer=freebob_ringbuffer_create(
419           m_event_size * ringbuffer_size_frames))) {
420                 debugFatal("Could not allocate memory event ringbuffer");
421                 return false;
422         }
423
424         // Allocate the temporary event buffer.  This is needed for the
425         // efficient transfer() routine.  Its size has to be equal to one
426         // 'event'.
427         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
428                 debugFatal("Could not allocate temporary event buffer");
429                 freebob_ringbuffer_free(m_event_buffer);
430                 return false;
431         }
432
433         // Set the parameters of ports we can: we want the audio ports to be
434         // period buffered, and the midi ports to be packet buffered.
435         for ( PortVectorIterator it = m_Ports.begin();
436           it != m_Ports.end();
437           ++it ) {
438                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
439                 if(!(*it)->setBufferSize(m_period)) {
440                         debugFatal("Could not set buffer size to %d\n",m_period);
441                         return false;
442                 }
443
444                 switch ((*it)->getPortType()) {
445                 case Port::E_Audio:
446                         if (!(*it)->setSignalType(Port::E_PeriodSignalled)) {
447                                 debugFatal("Could not set signal type to PeriodSignalling");
448                                 return false;
449                         }
450                         break;
451
452                 case Port::E_Midi:
453                         if (!(*it)->setSignalType(Port::E_PacketSignalled)) {
454                                 debugFatal("Could not set signal type to PacketSignalling");
455                                 return false;
456                         }
457                         break;
458                
459                 case Port::E_Control:
460                         if (!(*it)->setSignalType(Port::E_PeriodSignalled)) {
461                                 debugFatal("Could not set signal type to PeriodSignalling");
462                                 return false;
463                         }
464                         break;
465
466                 default:
467                         debugWarning("Unsupported port type specified\n");
468                         break;
469                 }
470         }
471
472         // The API specific settings of the ports are already set before
473         // this routine is called, therefore we can init&prepare the ports
474         if (!initPorts()) {
475                 debugFatal("Could not initialize ports!\n");
476                 return false;
477         }
478
479         if(!preparePorts()) {
480                 debugFatal("Could not initialize ports!\n");
481                 return false;
482         }
483
484         // We should prefill the event buffer
485         if (!prefill()) {
486                 debugFatal("Could not prefill buffers\n");
487                 return false;   
488         }
489
490         return true;
491 }
492
493 bool MotuTransmitStreamProcessor::transferSilence(unsigned int size) {
494    
495         // This function should tranfer 'size' frames of 'silence' to the event buffer
496         unsigned int write_size=size*m_event_size;
497         char *dummybuffer=(char *)calloc(size,m_event_size);
498
499         transmitSilenceBlock(dummybuffer, size, 0);
500
501         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
502                 debugWarning("Could not write to event buffer\n");
503         }
504
505         free(dummybuffer);
506
507         return true;
508 }
509
510 /**
511  * \brief write events queued for transmission from the port ringbuffers
512  * to the event buffer.
513  */
514 bool MotuTransmitStreamProcessor::transfer() {
515         m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/m_event_size);
516
517         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
518         // TODO: improve
519 /* a naive implementation would look like this:
520
521         unsigned int write_size=m_period*m_event_size;
522         char *dummybuffer=(char *)calloc(m_period,m_event_size);
523
524         transmitBlock(dummybuffer, m_period, 0, 0);
525
526         if (freebob_ringbuffer_write(m_event_buffer,(char *)(dummybuffer),write_size) < write_size) {
527                 debugWarning("Could not write to event buffer\n");
528         }
529
530         free(dummybuffer);
531 */
532 /* but we're not that naive anymore... */
533         int xrun;
534         unsigned int offset=0;
535
536         freebob_ringbuffer_data_t vec[2];
537         // There is one period of frames to transfer.  This is
538         // period_size*m_event_size of events.
539         unsigned int bytes2write=m_period*m_event_size;
540
541         /* Write bytes2write bytes to the event ringbuffer.  First see if it can
542          * be done in one write; if so, ok.
543          * Otherwise write up to a multiple of events directly to the buffer
544          * then do the buffer wrap around using ringbuffer_write.  Then
545          * write the remaining data directly to the buffer in a third pass.
546          * Make sure that we cannot end up on a non-cluster aligned
547          * position!
548          */
549         while(bytes2write>0) {
550                 int byteswritten=0;
551        
552                 unsigned int frameswritten=(m_period*m_event_size-bytes2write)/m_event_size;
553                 offset=frameswritten;
554
555                 freebob_ringbuffer_get_write_vector(m_event_buffer, vec);
556
557                 if (vec[0].len==0) { // this indicates a full event buffer
558                         debugError("XMT: Event buffer overrun in processor %p\n",this);
559                         break;
560                 }
561
562                 /* If we don't take care we will get stuck in an infinite
563                  * loop because we align to a event boundary later.  The
564                  * remaining nb of bytes in one write operation can be
565                  * smaller than one event; this can happen because the
566                  * ringbuffer size is always a power of 2.
567                  */
568                 if(vec[0].len<m_event_size) {
569            
570                         // encode to the temporary buffer
571                         xrun = transmitBlock(m_tmp_event_buffer, 1, offset);
572            
573                         if (xrun<0) {
574                                 // xrun detected
575                                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
576                                 break;
577                         }
578
579                         // Use the ringbuffer function to write one event.
580                         // The write function handles the wrap around.
581                         freebob_ringbuffer_write(m_event_buffer,
582                                 m_tmp_event_buffer, m_event_size);
583                
584                         // we advanced one m_event_size
585                         bytes2write-=m_event_size;
586                
587                 } else {
588            
589                         if (bytes2write>vec[0].len) {
590                                 // align to an event boundary
591                                 byteswritten=vec[0].len-(vec[0].len%m_event_size);
592                         } else {
593                                 byteswritten=bytes2write;
594                         }
595
596                         xrun = transmitBlock(vec[0].buf,
597                                 byteswritten/m_event_size, offset);
598            
599                         if (xrun<0) {
600                                 // xrun detected
601                                 debugError("XMT: Frame buffer underrun in processor %p\n",this);
602                                 break;
603                         }
604
605                         freebob_ringbuffer_write_advance(m_event_buffer, byteswritten);
606                         bytes2write -= byteswritten;
607                 }
608
609                 // the bytes2write should always be event aligned
610                 assert(bytes2write%m_event_size==0);
611         }
612
613         return true;
614 }
615 /*
616  * write received events to the stream ringbuffers.
617  */
618
619 int MotuTransmitStreamProcessor::transmitBlock(char *data,
620                        unsigned int nevents, unsigned int offset) {
621         signed int problem=0;
622         unsigned int i;
623
624         // FIXME: ensure the MIDI and control streams are all zeroed until
625         // such time as they are fully implemented.
626         for (i=0; i<nevents; i++) {
627                 memset(data+4+i*m_event_size, 0x00, 6);
628         }
629
630         for ( PortVectorIterator it = m_PeriodPorts.begin();
631           it != m_PeriodPorts.end();
632           ++it ) {
633                 // If this port is disabled, don't process it
634                 if((*it)->isDisabled()) {continue;};
635        
636                 //FIXME: make this into a static_cast when not DEBUG?
637                 Port *port=dynamic_cast<Port *>(*it);
638                
639                 switch(port->getPortType()) {
640                
641                 case Port::E_Audio:
642                         if (encodePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
643                                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
644                                 problem=1;
645                         }
646                         break;
647                 // midi is a packet based port, don't process
648                 //      case MotuPortInfo::E_Midi:
649                 //              break;
650
651                 default: // ignore
652                         break;
653                 }
654         }
655         return problem;
656 }
657
658 int MotuTransmitStreamProcessor::transmitSilenceBlock(char *data,
659                        unsigned int nevents, unsigned int offset) {
660         // This is the same as the non-silence version, except that is
661         // doesn't read from the port buffers.
662
663         int problem=0;
664
665         for ( PortVectorIterator it = m_PeriodPorts.begin();
666           it != m_PeriodPorts.end();
667           ++it ) {
668                 //FIXME: make this into a static_cast when not DEBUG?
669                 Port *port=dynamic_cast<Port *>(*it);
670                
671                 switch(port->getPortType()) {
672                
673                 case Port::E_Audio:
674                         if (encodeSilencePortToMBLAEvents(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
675                                 debugWarning("Could not encode port %s to MBLA events",(*it)->getName().c_str());
676                                 problem=1;
677                         }
678                         break;
679                 // midi is a packet based port, don't process
680                 //      case MotuPortInfo::E_Midi:
681                 //              break;
682
683                 default: // ignore
684                         break;
685                 }
686         }
687         return problem;
688 }
689
690 /**
691  * @brief decode a packet for the packet-based ports
692  *
693  * @param data Packet data
694  * @param nevents number of events in data (including events of other ports & port types)
695  * @param dbc DataBlockCount value for this packet
696  * @return true if all successfull
697  */
698 bool MotuTransmitStreamProcessor::encodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
699 {
700     bool ok=true;
701     char byte;
702    
703     quadlet_t *target_event=NULL;
704     int j;
705
706     for ( PortVectorIterator it = m_PacketPorts.begin();
707           it != m_PacketPorts.end();
708           ++it )
709     {
710
711 #ifdef DEBUG
712         MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
713         assert(pinfo); // this should not fail!!
714
715         // the only packet type of events for AMDTP is MIDI in mbla
716 //         assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
717 #endif
718        
719         MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
720        
721         // TODO: decode the midi (or other type) stuff here
722
723     }
724        
725     return ok;
726 }
727
728 int MotuTransmitStreamProcessor::encodePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
729                        unsigned int offset, unsigned int nevents) {
730 // Encodes nevents worth of data from the given port into the given buffer.  The
731 // format of the buffer is precisely that which will be sent to the MOTU.
732 // The basic idea:
733 //   iterate over the ports
734 //     * get port buffer address
735 //     * loop over events
736 //         - pick right sample in event based upon PortInfo
737 //         - convert sample from Port format (E_Int24, E_Float, ..) to MOTU
738 //           native format
739 //
740 // We include the ability to start the transfer from the given offset within
741 // the port (expressed in frames) so the 'efficient' transfer method can be
742 // utilised.
743
744         unsigned int j=0;
745
746         // Use char here since the target address won't necessarily be
747         // aligned; use of an unaligned quadlet_t may cause issues on certain
748         // architectures.  Besides, the target (data going directly to the MOTU)
749         // isn't structured in quadlets anyway; it mainly consists of packed
750         // 24-bit integers.
751         unsigned char *target;
752         target = (unsigned char *)data + p->getPosition();
753
754         switch(p->getDataType()) {
755                 default:
756                 case Port::E_Int24:
757                         {
758                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
759
760                                 assert(nevents + offset <= p->getBufferSize());
761
762                                 // Offset is in frames, but each port is only a single
763                                 // channel, so the number of frames is the same as the
764                                 // number of quadlets to offset (assuming the port buffer
765                                 // uses one quadlet per sample, which is the case currently).
766                                 buffer+=offset;
767
768                                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
769                                         *target = (*buffer >> 16) & 0xff;
770                                         *(target+1) = (*buffer >> 8) & 0xff;
771                                         *(target+2) = (*buffer) & 0xff;
772
773                                         buffer++;
774                                         target+=m_event_size;
775                                 }
776                         }
777                         break;
778                 case Port::E_Float:
779                         {
780                                 const float multiplier = (float)(0x7FFFFF);
781                                 float *buffer=(float *)(p->getBufferAddress());
782
783                                 assert(nevents + offset <= p->getBufferSize());
784
785                                 buffer+=offset;
786
787                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
788                                         unsigned int v = (int)(*buffer * multiplier);
789                                         *target = (v >> 16) & 0xff;
790                                         *(target+1) = (v >> 8) & 0xff;
791                                         *(target+2) = v & 0xff;
792
793                                         buffer++;
794                                         target+=m_event_size;
795                                 }
796                         }
797                         break;
798         }
799
800         return 0;
801 }
802
803 int MotuTransmitStreamProcessor::encodeSilencePortToMBLAEvents(MotuAudioPort *p, quadlet_t *data,
804                        unsigned int offset, unsigned int nevents) {
805         unsigned int j=0;
806         unsigned char *target = (unsigned char *)data + p->getPosition();
807
808         switch (p->getDataType()) {
809         default:
810         case Port::E_Int24:
811         case Port::E_Float:
812                 for (j = 0; j < nevents; j++) {
813                         *target = *(target+1) = *(target+2) = 0;
814                         target += m_event_size;
815                 }
816                 break;
817         }
818
819         return 0;
820 }
821
822 bool MotuTransmitStreamProcessor::preparedForStop() {
823
824         // If the stream is disabled or isn't running there's no need to
825         // wait since the MOTU *should* still be in a "zero data" state.
826         //
827         // If the m_streaming_active flag is 0 it indicates that the
828         // transmit callback hasn't been called since a closedown was
829         // requested when this function was last called.  This effectively
830         // signifies that the streaming thread has been exitted due to an
831         // xrun in either the receive or transmit handlers.  In this case
832         // there's no point in waiting for the closedown count to hit zero
833         // because it never will; the zero data will never get to the MOTU.
834         // It's best to allow an immediate stop and let the xrun handler
835         // proceed as best it can.
836         //
837         // The ability to detect the lack of streaming also prevents the
838         // "wait for stop" in the stream processor manager's stop() method
839         // from hitting its timeout which in turn seems to increase the
840         // probability of a successful recovery.
841         if (m_disabled || !isRunning() || !m_streaming_active)
842                 return true;
843
844         if (m_closedown_count < 0) {
845                 // No closedown has been initiated, so start one now.  Set
846                 // the closedown count to the number of zero packets which
847                 // will be sent to the MOTU before closing off the iso
848                 // streams.  FIXME: 128 packets (each containing 8 frames at
849                 // 48 kHz) is the experimentally-determined figure for 48
850                 // kHz with a period size of 1024.  It seems that at least
851                 // one period of zero samples need to be sent to allow for
852                 // inter-thread communication occuring on period boundaries.
853                 // This needs to be confirmed for other rates and period
854                 // sizes.
855                 signed n_events = m_framerate<=48000?8:(m_framerate<=96000?16:32);
856                 m_closedown_count = m_period / n_events;
857
858                 // Set up a test to confirm that streaming is still active.
859                 // If the streaming function hasn't been called by the next
860                 // iteration through this function there's no point in
861                 // continuing since it means the zero data will never get to
862                 // the MOTU.
863                 m_streaming_active = 0;
864                 return false;
865         }
866
867         // We are "go" for closedown once all requested zero packets
868         // (initiated by a previous call to this function) have been sent to
869         // the MOTU.
870         return m_closedown_count == 0;
871 }
872
873 /* --------------------- RECEIVE ----------------------- */
874
875 MotuReceiveStreamProcessor::MotuReceiveStreamProcessor(int port, int framerate,
876         unsigned int event_size)
877     : ReceiveStreamProcessor(port, framerate), m_event_size(event_size),
878         m_last_cycle_ofs(-1), m_next_cycle(-1), m_closedown_active(0) {
879
880         // Set up the Delay-locked-loop to track audio frequency relative
881         // to the cycle timer.  The seed value is the "ideal" value.
882         m_ticks_per_frame = 24576000.0/framerate;
883 }
884
885 MotuReceiveStreamProcessor::~MotuReceiveStreamProcessor() {
886         freebob_ringbuffer_free(m_event_buffer);
887         free(m_tmp_event_buffer);
888 }
889
890 bool MotuReceiveStreamProcessor::init() {
891
892     // call the parent init
893     // this has to be done before allocating the buffers,
894     // because this sets the buffersizes from the processormanager
895     if(!ReceiveStreamProcessor::init()) {
896         debugFatal("Could not do base class init (%d)\n",this);
897         return false;
898     }
899
900     return true;
901 }
902
903 enum raw1394_iso_disposition
904 MotuReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
905                   unsigned char channel, unsigned char tag, unsigned char sy,
906                   unsigned int cycle, unsigned int dropped) {
907    
908     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
909     signed int have_lost_cycles = 0;
910
911     // Detect missed receive cycles
912     // FIXME: it would be nice to advance the rx buffer by the amount of
913     // frames missed.  However, since the MOTU transmits more frames per
914     // cycle than the average and "catches up" with periodic empty cycles
915     // it's not trivial to work out precisely how many frames were missed.
916     // Ultimately I think we need to do so if sync is to be maintained
917     // across a transient receive failure.
918     if (m_next_cycle < 0)
919         m_next_cycle = cycle;
920     if ((signed)cycle != m_next_cycle) {
921         debugOutput(DEBUG_LEVEL_VERBOSE, "lost rx cycles; received %d, expected %d\n",
922             cycle, m_next_cycle);
923         m_next_cycle = cycle;
924         have_lost_cycles = 1;
925     }
926     if (!m_disabled) {
927         if (++m_next_cycle >= 8000)
928             m_next_cycle -= 8000;
929     } else
930         m_next_cycle = -1;
931
932     // If the packet length is 8 bytes (ie: just a CIP-like header) there is
933     // no isodata.
934     if (length > 8) {
935         // The iso data blocks from the MOTUs comprise a CIP-like header
936         // followed by a number of events (8 for 1x rates, 16 for 2x rates,
937         // 32 for 4x rates).
938         quadlet_t *quadlet = (quadlet_t *)data;
939         unsigned int dbs = get_bits(ntohl(quadlet[0]), 23, 8);  // Size of one event in terms of fdf_size
940         unsigned int fdf_size = get_bits(ntohl(quadlet[1]), 23, 8) == 0x22 ? 32:0; // Event unit size in bits
941         unsigned int event_length = (fdf_size * dbs) / 8;       // Event size in bytes
942         unsigned int n_events = (length-8) / event_length;
943
944         // Don't even attempt to process a packet if it isn't what we expect
945         // from a MOTU
946         if (tag!=1 || fdf_size!=32) {
947                 return RAW1394_ISO_OK;
948         }
949
950         // Signal that we're running
951         if (n_events) m_running=true;
952
953         /* Send actual ticks-per-frame values (as deduced by the incoming
954          * SPHs) to the DLL for averaging.  Doing this here means the DLL
955          * should acquire a reasonable estimation of the ticks per frame
956          * even while the stream is formally disabled.  This in turn means
957          * the transmit stream should have access to a very realistic
958          * estimate by the time it is enabled.  The major disadvantage
959          * is a small increase in the overheads of this function compared
960          * to what would be the case if this was delayed by pushing it into
961          * the decode functions.
962          */
963         unsigned int ev;
964         signed int sph_ofs;
965
966         /* If this is the first block received or we have lost cycles,
967          * initialise the m_last_cycle_ofs to a value which won't cause the
968          * DLL to become polluted with an inappropriate ticks-per-frame
969          * estimate.
970          */
971         if (m_last_cycle_ofs<0 || have_lost_cycles) {
972                 sph_ofs = ntohl(*(quadlet_t *)(data+8)) & 0xfff;
973                 m_last_cycle_ofs = sph_ofs-(int)(m_ticks_per_frame);
974         }
975         for (ev=0; ev<n_events; ev++) {
976                 sph_ofs = ntohl(*(quadlet_t *)(data+8+ev*m_event_size)) & 0xfff;
977                 signed int sph_diff = (sph_ofs - m_last_cycle_ofs);
978                 // Handle wraparound of the cycle offset
979                 if (sph_diff < 0)
980                         sph_diff += 3072;
981                 float err = sph_diff - m_ticks_per_frame;
982                 // FIXME: originally we used a value of 0.0005 for the coefficient
983                 // which mirrored the value used in
984                 // AmdtpReceiveStreamProcessor::putPacket() for a similar purpose.
985                 // However, tests showed that this introduced discontinuities in
986                 // the output audio signal, so an alternative value was sought.
987                 // Further tests are needed, but a value of 0.015 seems to work
988                 // well, at least at a sample rate of 48 kHz.
989                 m_ticks_per_frame += 0.015*err;
990                 m_last_cycle_ofs = sph_ofs;
991         }
992
993         // Don't process the stream when it is not enabled
994         if (m_disabled) {
995                 return RAW1394_ISO_OK;
996         }
997        
998         // If closedown is active we also just throw data way, but in this case
999         // we keep the frame counter going to prevent a false xrun detection
1000         if (m_closedown_active) {
1001                 incrementFrameCounter(n_events);
1002                 if (m_framecounter > (signed int)m_period)
1003                         return RAW1394_ISO_DEFER;
1004                 return RAW1394_ISO_OK;
1005         }
1006
1007         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "put packet...\n");
1008
1009         // Add the data payload (events) to the ringbuffer.  We'll just copy
1010         // everything including the 4 byte timestamp at the start of each
1011         // event (that is, everything except the CIP-like header).  The
1012         // demultiplexer can deal with the complexities such as the channel
1013         // 24-bit data.
1014         unsigned int write_size = length-8;
1015         if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size) {
1016                 debugWarning("Receive buffer overrun (cycle %d, FC=%d, PC=%d)\n",
1017                         cycle, m_framecounter, m_handler->getPacketCount());
1018                 m_xruns++;
1019
1020                 retval=RAW1394_ISO_DEFER;
1021         } else {
1022                 retval=RAW1394_ISO_OK;
1023                 // Process all ports that should be handled on a per-packet basis
1024                 // This is MIDI for AMDTP (due to the need of DBC)
1025                 int dbc = get_bits(ntohl(quadlet[0]), 8, 8);  // Low byte of CIP quadlet 0
1026                 if (!decodePacketPorts((quadlet_t *)(data+8), n_events, dbc)) {
1027                         debugWarning("Problem decoding Packet Ports\n");
1028                         retval=RAW1394_ISO_DEFER;
1029                 }
1030                 // time stamp processing can be done here
1031         }
1032
1033         // update the frame counter
1034         incrementFrameCounter(n_events);
1035         // keep this at the end, because otherwise the raw1394_loop_iterate functions inner loop
1036         // keeps requesting packets without going to the xmit handler, leading to xmit starvation
1037         if(m_framecounter>(signed int)m_period) {
1038                 retval=RAW1394_ISO_DEFER;
1039         }
1040        
1041     } else { // no events in packet
1042         // discard packet
1043         // can be important for sync though
1044     }
1045    
1046     return retval;
1047 }
1048
1049 bool MotuReceiveStreamProcessor::isOnePeriodReady() {
1050      // TODO: this is the way you can implement sync
1051      //       only when this returns true, one period will be
1052      //       transferred to the audio api side.
1053      //       you can delay this moment as long as you
1054      //       want (provided that there is enough buffer space)
1055      
1056      // this implementation just waits until there is one period of samples
1057      // received into the buffer
1058     if(m_framecounter > (signed int)m_period) {
1059         return true;
1060     }
1061     return false;
1062 }
1063
1064 void MotuReceiveStreamProcessor::setVerboseLevel(int l) {
1065         setDebugLevel(l);
1066         ReceiveStreamProcessor::setVerboseLevel(l);
1067
1068 }
1069
1070
1071 bool MotuReceiveStreamProcessor::reset() {
1072
1073         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
1074
1075         // reset the event buffer, discard all content
1076         freebob_ringbuffer_reset(m_event_buffer);
1077
1078         // reset all non-device specific stuff
1079         // i.e. the iso stream and the associated ports
1080         if(!ReceiveStreamProcessor::reset()) {
1081                 debugFatal("Could not do base class reset\n");
1082                 return false;
1083         }
1084
1085         m_next_cycle = -1;
1086
1087         return true;
1088 }
1089
1090 bool MotuReceiveStreamProcessor::prepare() {
1091
1092         // prepare all non-device specific stuff
1093         // i.e. the iso stream and the associated ports
1094         if(!ReceiveStreamProcessor::prepare()) {
1095                 debugFatal("Could not prepare base class\n");
1096                 return false;
1097         }
1098
1099         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
1100
1101         m_PeriodStat.setName("RCV PERIOD");
1102         m_PacketStat.setName("RCV PACKET");
1103         m_WakeupStat.setName("RCV WAKEUP");
1104
1105     // setup any specific stuff here
1106
1107         debugOutput( DEBUG_LEVEL_VERBOSE, "Event size: %d\n", m_event_size);
1108    
1109         // allocate the event buffer
1110         unsigned int ringbuffer_size_frames=m_nb_buffers * m_period;
1111
1112         if( !(m_event_buffer=freebob_ringbuffer_create(
1113                         m_event_size * ringbuffer_size_frames))) {
1114                 debugFatal("Could not allocate memory event ringbuffer");
1115                 return false;
1116         }
1117
1118         // allocate the temporary event buffer
1119         if( !(m_tmp_event_buffer=(char *)calloc(1,m_event_size))) {
1120                 debugFatal("Could not allocate temporary event buffer");
1121                 freebob_ringbuffer_free(m_event_buffer);
1122                 return false;
1123         }
1124
1125         // set the parameters of ports we can:
1126         // we want the audio ports to be period buffered,
1127         // and the midi ports to be packet buffered
1128         for ( PortVectorIterator it = m_Ports.begin();
1129                   it != m_Ports.end();
1130                   ++it )
1131         {
1132                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1133                
1134                 if(!(*it)->setBufferSize(m_period)) {
1135                         debugFatal("Could not set buffer size to %d\n",m_period);
1136                         return false;
1137                 }
1138
1139                 switch ((*it)->getPortType()) {
1140                         case Port::E_Audio:
1141                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1142                                         debugFatal("Could not set signal type to PeriodSignalling");
1143                                         return false;
1144                                 }
1145                                 break;
1146                         case Port::E_Midi:
1147                                 if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
1148                                         debugFatal("Could not set signal type to PacketSignalling");
1149                                         return false;
1150                                 }
1151                                 break;
1152                         case Port::E_Control:
1153                                 if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1154                                         debugFatal("Could not set signal type to PeriodSignalling");
1155                                         return false;
1156                                 }
1157                                 break;
1158                         default:
1159                                 debugWarning("Unsupported port type specified\n");
1160                                 break;
1161                 }
1162
1163         }
1164
1165         // The API specific settings of the ports are already set before
1166         // this routine is called, therefore we can init&prepare the ports
1167         if(!initPorts()) {
1168                 debugFatal("Could not initialize ports!\n");
1169                 return false;
1170         }
1171
1172         if(!preparePorts()) {
1173                 debugFatal("Could not initialize ports!\n");
1174                 return false;
1175         }
1176        
1177         return true;
1178
1179 }
1180
1181 bool MotuReceiveStreamProcessor::transfer() {
1182
1183     // the same idea as the transmit processor
1184    
1185         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
1186        
1187 /* another naive section:       
1188         unsigned int read_size=m_period*m_event_size;
1189         char *dummybuffer=(char *)calloc(m_period,m_event_size);
1190         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) {
1191                 debugWarning("Could not read from event buffer\n");
1192         }
1193
1194         receiveBlock(dummybuffer, m_period, 0);
1195
1196         free(dummybuffer);
1197 */
1198         int xrun;
1199         unsigned int offset=0;
1200        
1201         freebob_ringbuffer_data_t vec[2];
1202         // We received one period of frames from each channel.
1203         // This is period_size*m_event_size bytes.
1204         unsigned int bytes2read = m_period * m_event_size;
1205
1206         // If closedown is in progress just pretend that data's been transferred
1207         // to prevent false underrun detections on the event buffer.
1208         if (m_closedown_active)
1209                 return true;
1210
1211         /* Read events2read bytes from the ringbuffer.
1212         *  First see if it can be done in one read.  If so, ok.
1213         *  Otherwise read up to a multiple of events directly from the buffer
1214         *  then do the buffer wrap around using ringbuffer_read
1215         *  then read the remaining data directly from the buffer in a third pass
1216         *  Make sure that we cannot end up on a non-event aligned position!
1217         */
1218         while(bytes2read>0) {
1219                 unsigned int framesread=(m_period*m_event_size-bytes2read)/m_event_size;
1220                 offset=framesread;
1221                
1222                 int bytesread=0;
1223
1224                 freebob_ringbuffer_get_read_vector(m_event_buffer, vec);
1225                        
1226                 if(vec[0].len==0) { // this indicates an empty event buffer
1227                         debugError("RCV: Event buffer underrun in processor %p\n",this);
1228                         break;
1229                 }
1230                        
1231                 /* if we don't take care we will get stuck in an infinite loop
1232                 * because we align to an event boundary later
1233                 * the remaining nb of bytes in one read operation can be smaller than one event
1234                 * this can happen because the ringbuffer size is always a power of 2
1235                 */
1236                 if(vec[0].len<m_event_size) {
1237                         // use the ringbuffer function to read one event
1238                         // the read function handles wrap around
1239                         freebob_ringbuffer_read(m_event_buffer,m_tmp_event_buffer,m_event_size);
1240
1241                         xrun = receiveBlock(m_tmp_event_buffer, 1, offset);
1242                                
1243                         if(xrun<0) {
1244                                 // xrun detected
1245                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1246                                 break;
1247                         }
1248                                
1249                         // We advanced one m_event_size
1250                         bytes2read-=m_event_size;
1251                                
1252                 } else { //
1253                        
1254                         if(bytes2read>vec[0].len) {
1255                                         // align to an event boundary
1256                                 bytesread=vec[0].len-(vec[0].len%m_event_size);
1257                         } else {
1258                                 bytesread=bytes2read;
1259                         }
1260                                
1261                         xrun = receiveBlock(vec[0].buf, bytesread/m_event_size, offset);
1262                                
1263                         if(xrun<0) {
1264                                 // xrun detected
1265                                 debugError("RCV: Frame buffer overrun in processor %p\n",this);
1266                                 break;
1267                         }
1268
1269                         freebob_ringbuffer_read_advance(m_event_buffer, bytesread);
1270                         bytes2read -= bytesread;
1271                 }
1272                        
1273                 // the bytes2read should always be event aligned
1274                 assert(bytes2read%m_event_size==0);
1275         }
1276
1277         return true;
1278 }
1279
1280 /**
1281  * \brief write received events to the port ringbuffers.
1282  */
1283 int MotuReceiveStreamProcessor::receiveBlock(char *data,
1284                                            unsigned int nevents, unsigned int offset)
1285 {
1286         int problem=0;
1287         for ( PortVectorIterator it = m_PeriodPorts.begin();
1288           it != m_PeriodPorts.end();
1289           ++it ) {
1290                 if((*it)->isDisabled()) {continue;};
1291
1292                 //FIXME: make this into a static_cast when not DEBUG?
1293                 Port *port=dynamic_cast<Port *>(*it);
1294                
1295                 switch(port->getPortType()) {
1296                
1297                 case Port::E_Audio:
1298                         if(decodeMBLAEventsToPort(static_cast<MotuAudioPort *>(*it), (quadlet_t *)data, offset, nevents)) {
1299                                 debugWarning("Could not decode packet MBLA to port %s",(*it)->getName().c_str());
1300                                 problem=1;
1301                         }
1302                         break;
1303                 // midi is a packet based port, don't process
1304                 //      case MotuPortInfo::E_Midi:
1305                 //              break;
1306
1307                 default: // ignore
1308                         break;
1309                 }
1310         }
1311         return problem;
1312 }
1313
1314 /**
1315  * @brief decode a packet for the packet-based ports
1316  *
1317  * @param data Packet data
1318  * @param nevents number of events in data (including events of other ports & port types)
1319  * @param dbc DataBlockCount value for this packet
1320  * @return true if all successfull
1321  */
1322 bool MotuReceiveStreamProcessor::decodePacketPorts(quadlet_t *data, unsigned int nevents, unsigned int dbc)
1323 {
1324         bool ok=true;
1325        
1326         quadlet_t *target_event=NULL;
1327         int j;
1328        
1329         for ( PortVectorIterator it = m_PacketPorts.begin();
1330           it != m_PacketPorts.end();
1331           ++it ) {
1332
1333 #ifdef DEBUG
1334                 MotuPortInfo *pinfo=dynamic_cast<MotuPortInfo *>(*it);
1335                 assert(pinfo); // this should not fail!!
1336
1337                 // the only packet type of events for AMDTP is MIDI in mbla
1338 //              assert(pinfo->getFormat()==MotuPortInfo::E_Midi);
1339 #endif
1340                 MotuMidiPort *mp=static_cast<MotuMidiPort *>(*it);
1341                
1342
1343         // do decoding here
1344
1345         }
1346        
1347         return ok;
1348 }
1349
1350 signed int MotuReceiveStreamProcessor::decodeMBLAEventsToPort(MotuAudioPort *p,
1351                 quadlet_t *data, unsigned int offset, unsigned int nevents)
1352 {
1353         unsigned int j=0;
1354
1355         // Use char here since a port's source address won't necessarily be
1356         // aligned; use of an unaligned quadlet_t may cause issues on
1357         // certain architectures.  Besides, the source (data coming directly
1358         // from the MOTU) isn't structured in quadlets anyway; it mainly
1359         // consists of packed 24-bit integers.
1360
1361         unsigned char *src_data;
1362         src_data = (unsigned char *)data + p->getPosition();
1363
1364         switch(p->getDataType()) {
1365                 default:
1366                 case Port::E_Int24:
1367                         {
1368                                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
1369
1370                                 assert(nevents + offset <= p->getBufferSize());
1371
1372                                 // Offset is in frames, but each port is only a single
1373                                 // channel, so the number of frames is the same as the
1374                                 // number of quadlets to offset (assuming the port buffer
1375                                 // uses one quadlet per sample, which is the case currently).
1376                                 buffer+=offset;
1377
1378                                 for(j = 0; j < nevents; j += 1) { // Decode nsamples
1379                                         *buffer = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1380                                         // Sign-extend highest bit of 24-bit int.
1381                                         // FIXME: this isn't strictly needed since E_Int24 is a 24-bit,
1382                                         // but doing so shouldn't break anything and makes the data
1383                                         // easier to deal with during debugging.
1384                                         if (*src_data & 0x80)
1385                                                 *buffer |= 0xff000000;
1386
1387                                         buffer++;
1388                                         src_data+=m_event_size;
1389                                 }
1390                         }
1391                         break;
1392                 case Port::E_Float:
1393                         {
1394                                 const float multiplier = 1.0f / (float)(0x7FFFFF);
1395                                 float *buffer=(float *)(p->getBufferAddress());
1396
1397                                 assert(nevents + offset <= p->getBufferSize());
1398
1399                                 buffer+=offset;
1400
1401                                 for(j = 0; j < nevents; j += 1) { // decode max nsamples               
1402        
1403                                         unsigned int v = (*src_data<<16)+(*(src_data+1)<<8)+*(src_data+2);
1404
1405                                         // sign-extend highest bit of 24-bit int
1406                                         int tmp = (int)(v << 8) / 256;
1407                
1408                                         *buffer = tmp * multiplier;
1409                                
1410                                         buffer++;
1411                                         src_data+=m_event_size;
1412                                 }
1413                         }
1414                         break;
1415         }
1416
1417         return 0;
1418 }
1419
1420 signed int MotuReceiveStreamProcessor::setEventSize(unsigned int size) {
1421         m_event_size = size;
1422         return 0;
1423 }
1424
1425 unsigned int MotuReceiveStreamProcessor::getEventSize(void) {
1426 //
1427 // Return the size of a single event sent by the MOTU as part of an iso
1428 // data packet in bytes.
1429 //
1430         return m_event_size;
1431 }
1432
1433 bool MotuReceiveStreamProcessor::preparedForStop() {
1434
1435         // A MOTU receive stream can stop at any time.  However, signify
1436         // that stopping is in progress because other streams (notably the
1437         // transmit stream) may keep going for some time and cause an
1438         // overflow in the receive buffers.  If a closedown is in progress
1439         // the receive handler simply throws all incoming data away so
1440         // no buffer overflow can occur.
1441         m_closedown_active = 1;
1442         return true;
1443 }
1444                
1445 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.