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

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

MOTU: Fixed false "missed rx cycle" report following xrun recovery.
Ensure iso rx/tx contexts are deallocated during shutdown/xrun recovery by explicitly deleting IsoHandlers? in IsoHandlerManager::pruneHandlers(). If they aren't deleted here they never get deleted because the reference is lost.
IsoHandler? destructor should only call stop() if the handle is valid.
IsoXmitHandler?'s destructor sets the handle NULL to prevent double-free by the inherited IsoHandler? destructor.
Don't call raw1394_iso_shutdown() from our code. libraw1394 1.2.1 has a bug whereby raw1394_new_handle() fails to initialise the iso_packet_infos field. The bug hits us particularly in IsoRecvHandler::prepare(). It's also not really necessary to call raw1394_iso_shutdown() since raw1394_destroy_handle() will do any cleanups we happen to need.
MOTU: the receive stream no longer falsely complains of buffer problems during device shutdown.
MOTU: fixed a false "missed cycle" detection immediately after the stream was enabled.

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.