root/branches/ppalmers-streaming/src/libstreaming/generic/StreamProcessor.cpp

Revision 722, 52.0 kB (checked in by ppalmers, 13 years ago)

more rewrite of streaming

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "StreamProcessor.h"
25 #include "../util/cycletimer.h"
26 #include "../StreamProcessorManager.h"
27
28 #include "libutil/Atomic.h"
29
30 #include <assert.h>
31 #include <math.h>
32
33 namespace Streaming {
34
35 IMPL_DEBUG_MODULE( StreamProcessor, StreamProcessor, DEBUG_LEVEL_VERBOSE );
36
37 StreamProcessor::StreamProcessor(enum eProcessorType type, int port)
38     : IsoStream((type==ePT_Receive ? IsoStream::eST_Receive : IsoStream::eST_Transmit), port)
39     , m_processor_type ( type )
40     , m_state( ePS_Created )
41     , m_next_state( ePS_Invalid )
42     , m_cycle_to_switch_state( 0 )
43     , m_manager( NULL )
44     , m_ticks_per_frame( 0 )
45     , m_last_cycle( -1 )
46     , m_sync_delay( 0 )
47     , m_in_xrun( false )
48     , m_last_timestamp(0)
49     , m_last_timestamp2(0)
50     , m_dropped(0)
51 {
52     // create the timestamped buffer and register ourselves as its client
53     m_data_buffer=new Util::TimestampedBuffer(this);
54 }
55
56 StreamProcessor::~StreamProcessor() {
57     if (m_data_buffer) delete m_data_buffer;
58 }
59
60 uint64_t StreamProcessor::getTimeNow() {
61     return m_handler->getCycleTimerTicks();
62 }
63
64 int StreamProcessor::getMaxFrameLatency() {
65     if (getType() == ePT_Receive) {
66         return (int)(m_handler->getWakeupInterval() * TICKS_PER_CYCLE);
67     } else {
68         return (int)(m_handler->getWakeupInterval() * TICKS_PER_CYCLE);
69     }
70 }
71
72 /***********************************************
73  * Buffer management and manipulation          *
74  ***********************************************/
75 int StreamProcessor::getBufferFill() {
76     return m_data_buffer->getBufferFill();
77 }
78
79 bool
80 StreamProcessor::dropFrames(unsigned int nbframes)
81 {
82     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "StreamProcessor::dropFrames(%d)\n", nbframes);
83     return m_data_buffer->dropFrames(nbframes);
84 }
85
86 int64_t
87 StreamProcessor::getTimeUntilNextPeriodSignalUsecs()
88 {
89     uint64_t time_at_period=getTimeAtPeriod();
90
91     // we delay the period signal with the sync delay
92     // this makes that the period signals lag a little compared to reality
93     // ISO buffering causes the packets to be received at max
94     // m_handler->getWakeupInterval() later than the time they were received.
95     // hence their payload is available this amount of time later. However, the
96     // period boundary is predicted based upon earlier samples, and therefore can
97     // pass before these packets are processed. Adding this extra term makes that
98     // the period boundary is signalled later
99     time_at_period = addTicks(time_at_period, m_manager->getSyncSource().getSyncDelay());
100
101     uint64_t cycle_timer=m_handler->getCycleTimerTicks();
102
103     // calculate the time until the next period
104     int32_t until_next=diffTicks(time_at_period,cycle_timer);
105
106     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11ld\n",
107         time_at_period, cycle_timer, until_next
108         );
109
110     // now convert to usecs
111     // don't use the mapping function because it only works
112     // for absolute times, not the relative time we are
113     // using here (which can also be negative).
114     return (int64_t)(((float)until_next) / TICKS_PER_USEC);
115 }
116
117 uint64_t
118 StreamProcessor::getTimeAtPeriodUsecs()
119 {
120     return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC);
121 }
122
123 uint64_t
124 StreamProcessor::getTimeAtPeriod()
125 {
126     if (getType() == ePT_Receive) {
127         ffado_timestamp_t next_period_boundary=m_data_buffer->getTimestampFromHead(m_manager->getPeriodSize());
128    
129         #ifdef DEBUG
130         ffado_timestamp_t ts;
131         signed int fc;
132         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
133    
134         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
135             next_period_boundary, ts, fc, getTicksPerFrame()
136             );
137         #endif
138         return (uint64_t)next_period_boundary;
139     } else {
140         ffado_timestamp_t next_period_boundary=m_data_buffer->getTimestampFromTail((m_manager->getNbBuffers()-1) * m_manager->getPeriodSize());
141    
142         #ifdef DEBUG
143         ffado_timestamp_t ts;
144         signed int fc;
145         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
146    
147         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
148             next_period_boundary, ts, fc, getTicksPerFrame()
149             );
150         #endif
151         return (uint64_t)next_period_boundary;
152     }
153 }
154
155 float
156 StreamProcessor::getTicksPerFrame()
157 {
158     assert(m_data_buffer != NULL);
159     return m_data_buffer->getRate();
160 }
161
162 bool
163 StreamProcessor::canClientTransferFrames(unsigned int nbframes)
164 {
165     bool can_transfer;
166     unsigned int fc = m_data_buffer->getFrameCounter();
167     if (getType() == ePT_Receive) {
168         can_transfer = (fc >= nbframes);
169     } else {
170         // there has to be enough space to put the frames in
171         can_transfer = m_data_buffer->getBufferSize() - fc > nbframes;
172         // or the buffer is transparent
173         can_transfer |= m_data_buffer->isTransparent();
174     }
175    
176     #ifdef DEBUG
177     if (!can_transfer) {
178         debugWarning("(%p, %s) cannot transfer since fc == %u, nbframes == %u\n",
179             this, ePTToString(getType()), fc, nbframes);
180     }
181     #endif
182    
183     return can_transfer;
184 }
185
186 /***********************************************
187  * I/O API                                     *
188  ***********************************************/
189
190 // Packet transfer API
191 enum raw1394_iso_disposition
192 StreamProcessor::putPacket(unsigned char *data, unsigned int length,
193                            unsigned char channel, unsigned char tag, unsigned char sy,
194                            unsigned int cycle, unsigned int dropped) {
195     int dropped_cycles = 0;
196     if (m_last_cycle != (int)cycle && m_last_cycle != -1) {
197         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
198         if (dropped_cycles < 0) debugWarning("(%p) dropped < 1 (%d)\n", this, dropped_cycles);
199         if (dropped_cycles > 0) {
200             debugWarning("(%p) dropped %d packets on cycle %u\n", this, dropped_cycles, cycle);
201             m_dropped += dropped_cycles;
202         }
203         m_last_cycle = cycle;
204     }
205
206     // bypass based upon state
207     if (m_state == ePS_Invalid) {
208         debugError("Should not have state %s\n", ePSToString(m_state) );
209         return RAW1394_ISO_ERROR;
210     }
211     if (m_state == ePS_Created) {
212         return RAW1394_ISO_DEFER;
213     }
214
215     // store the previous timestamp
216     m_last_timestamp2 = m_last_timestamp;
217
218     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
219     //       it happens on the first 'good' cycle for the wait condition
220     //       or on the first received cycle that is received afterwards (might be a problem)
221
222     // check whether we are waiting for a stream to be disabled
223     if(m_state == ePS_WaitingForStreamDisable) {
224         // we then check whether we have to switch on this cycle
225         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
226             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
227             m_next_state = ePS_DryRunning;
228             if (!updateState()) { // we are allowed to change the state directly
229                 debugError("Could not update state!\n");
230                 return RAW1394_ISO_ERROR;
231             }
232         } else {
233             // not time to disable yet
234         }
235         // the received data can be discarded while waiting for the stream
236         // to be disabled
237         return RAW1394_ISO_OK;
238     }
239
240     // check whether we are waiting for a stream to be enabled
241     else if(m_state == ePS_WaitingForStreamEnable) {
242         // we then check whether we have to switch on this cycle
243         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
244             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
245             m_next_state = ePS_Running;
246             if (!updateState()) { // we are allowed to change the state directly
247                 debugError("Could not update state!\n");
248                 return RAW1394_ISO_ERROR;
249             }
250         } else {
251             // not time to enable yet
252         }
253         // we are dryRunning hence data should be processed in any case
254     }
255
256     // check the packet header
257     enum eChildReturnValue result = processPacketHeader(data, length, channel, tag, sy, cycle, dropped_cycles);
258     if (result == eCRV_OK) {
259         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n",
260                 cycle, m_last_timestamp);
261         // update some accounting
262         m_last_good_cycle = cycle;
263         m_last_dropped = dropped_cycles;
264
265         // check whether we are waiting for a stream to startup
266         // this requires that the packet is good
267         if(m_state == ePS_WaitingForStream) {
268             // since we have a packet with an OK header,
269             // we can indicate that the stream started up
270
271             // we then check whether we have to switch on this cycle
272             if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
273                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning due to good packet\n");
274                 // hence go to the dryRunning state
275                 m_next_state = ePS_DryRunning;
276                 if (!updateState()) { // we are allowed to change the state directly
277                     debugError("Could not update state!\n");
278                     return RAW1394_ISO_ERROR;
279                 }
280             } else {
281                 // not time (yet) to switch state
282             }
283             // in both cases we don't want to process the data
284             return RAW1394_ISO_OK;
285         }
286
287         // check whether a state change has been requested
288         // note that only the wait state changes are synchronized with the cycles
289         else if(m_state != m_next_state) {
290             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
291                                              ePSToString(m_state), ePSToString(m_next_state));
292             // execute the requested change
293             if (!updateState()) { // we are allowed to change the state directly
294                 debugError("Could not update state!\n");
295                 return RAW1394_ISO_ERROR;
296             }
297         }
298
299         // handle dropped cycles
300         if(dropped_cycles) {
301             // they represent a discontinuity in the timestamps, and hence are
302             // to be dealt with
303             debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this);
304             m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
305
306             // this is an xrun situation
307             m_in_xrun = true;
308             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to dropped packet xrun\n");
309             m_cycle_to_switch_state = cycle + 1; // switch in the next cycle
310             m_next_state = ePS_WaitingForStreamDisable;
311             // execute the requested change
312             if (!updateState()) { // we are allowed to change the state directly
313                 debugError("Could not update state!\n");
314                 return RAW1394_ISO_ERROR;
315             }
316             return RAW1394_ISO_DEFER;
317         }
318
319         // for all states that reach this we are allowed to
320         // do protocol specific data reception
321         enum eChildReturnValue result2 = processPacketData(data, length, channel, tag, sy, cycle, dropped_cycles);
322
323         // if an xrun occured, switch to the dryRunning state and
324         // allow for the xrun to be picked up
325         if (result2 == eCRV_XRun) {
326             m_in_xrun = true;
327             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
328             m_cycle_to_switch_state = cycle+1; // switch in the next cycle
329             m_next_state = ePS_WaitingForStreamDisable;
330             // execute the requested change
331             if (!updateState()) { // we are allowed to change the state directly
332                 debugError("Could not update state!\n");
333                 return RAW1394_ISO_ERROR;
334             }
335             return RAW1394_ISO_DEFER;
336         } else if(result2 == eCRV_OK) {
337             // no problem here
338             return RAW1394_ISO_OK;
339         } else {
340             debugError("Invalid response\n");
341             return RAW1394_ISO_ERROR;
342         }
343     } else if(result == eCRV_Invalid) {
344         // apparently we don't have to do anything when the packets are not valid
345         return RAW1394_ISO_OK;
346     } else {
347         debugError("Invalid response\n");
348         return RAW1394_ISO_ERROR;
349     }
350     debugError("reached the unreachable\n");
351     return RAW1394_ISO_ERROR;
352 }
353
354 enum raw1394_iso_disposition
355 StreamProcessor::getPacket(unsigned char *data, unsigned int *length,
356                            unsigned char *tag, unsigned char *sy,
357                            int cycle, unsigned int dropped, unsigned int max_length) {
358     if (cycle<0) {
359         *tag = 0;
360         *sy = 0;
361         *length = 0;
362         return RAW1394_ISO_OK;
363     }
364
365     int dropped_cycles = 0;
366     if (m_last_cycle != cycle && m_last_cycle != -1) {
367         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
368         if (dropped_cycles < 0) debugWarning("(%p) dropped < 1 (%d)\n", this, dropped_cycles);
369         if (dropped_cycles > 0) {
370             debugWarning("(%p) dropped %d packets on cycle %u\n", this, dropped_cycles, cycle);
371             m_dropped += dropped_cycles;
372         }
373         m_last_cycle = cycle;
374     }
375
376     // bypass based upon state
377     if (m_state == ePS_Invalid) {
378         debugError("Should not have state %s\n", ePSToString(m_state) );
379         return RAW1394_ISO_ERROR;
380     }
381     if (m_state == ePS_Created) {
382         *tag = 0;
383         *sy = 0;
384         *length = 0;
385         return RAW1394_ISO_DEFER;
386     }
387
388     // normal processing
389     // note that we can't use getCycleTimer directly here,
390     // because packets are queued in advance. This means that
391     // we the packet we are constructing will be sent out
392     // on 'cycle', not 'now'.
393     unsigned int ctr = m_handler->getCycleTimer();
394     int now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr);
395
396     // the difference between the cycle this
397     // packet is intended for and 'now'
398     int cycle_diff = diffCycles(cycle, now_cycles);
399
400     #ifdef DEBUG
401     if(cycle_diff < 0) {
402         debugWarning("Requesting packet for cycle %04d which is in the past (now=%04dcy)\n",
403             cycle, now_cycles);
404     }
405     #endif
406
407     // store the previous timestamp
408     m_last_timestamp2 = m_last_timestamp;
409
410     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
411     //       it happens on the first 'good' cycle for the wait condition
412     //       or on the first received cycle that is received afterwards (might be a problem)
413
414     // check whether we are waiting for a stream to be disabled
415     if(m_state == ePS_WaitingForStreamDisable) {
416         // we then check whether we have to switch on this cycle
417         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
418             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
419             m_next_state = ePS_DryRunning;
420             if (!updateState()) { // we are allowed to change the state directly
421                 debugError("Could not update state!\n");
422                 return RAW1394_ISO_ERROR;
423             }
424         } else {
425             // not time to disable yet
426         }
427     }
428     // check whether we are waiting for a stream to be enabled
429     else if(m_state == ePS_WaitingForStreamEnable) {
430         // we then check whether we have to switch on this cycle
431         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
432             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
433             m_next_state = ePS_Running;
434             if (!updateState()) { // we are allowed to change the state directly
435                 debugError("Could not update state!\n");
436                 return RAW1394_ISO_ERROR;
437             }
438         } else {
439             // not time to enable yet
440         }
441         // we are dryRunning hence data should be processed in any case
442     }
443     // check whether we are waiting for a stream to startup
444     else if(m_state == ePS_WaitingForStream) {
445         // as long as the cycle parameter is not in sync with
446         // the current time, the stream is considered not
447         // to be 'running'
448         // we then check whether we have to switch on this cycle
449         if ((cycle_diff >= 0) && (diffCycles(cycle, m_cycle_to_switch_state) >= 0)) {
450             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning due to good packet\n");
451             // hence go to the dryRunning state
452             m_next_state = ePS_DryRunning;
453             if (!updateState()) { // we are allowed to change the state directly
454                 debugError("Could not update state!\n");
455                 return RAW1394_ISO_ERROR;
456             }
457         } else {
458             // not time (yet) to switch state
459         }
460     }
461     else if(m_state == ePS_Running) {
462         // check the packet header
463         enum eChildReturnValue result = generatePacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
464         if (result == eCRV_Packet) {
465             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT: CY=%04u TS=%011llu\n",
466                     cycle, m_last_timestamp);
467             // update some accounting
468             m_last_good_cycle = cycle;
469             m_last_dropped = dropped_cycles;
470
471             // check whether a state change has been requested
472             // note that only the wait state changes are synchronized with the cycles
473             if(m_state != m_next_state) {
474                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
475                                                 ePSToString(m_state), ePSToString(m_next_state));
476                 // execute the requested change
477                 if (!updateState()) { // we are allowed to change the state directly
478                     debugError("Could not update state!\n");
479                     return RAW1394_ISO_ERROR;
480                 }
481             }
482
483             enum eChildReturnValue result2 = generatePacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
484             // if an xrun occured, switch to the dryRunning state and
485             // allow for the xrun to be picked up
486             if (result2 == eCRV_XRun) {
487                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
488                 m_in_xrun = true;
489                 m_cycle_to_switch_state = cycle+1; // switch in the next cycle
490                 m_next_state = ePS_WaitingForStreamDisable;
491                 // execute the requested change
492                 if (!updateState()) { // we are allowed to change the state directly
493                     debugError("Could not update state!\n");
494                     return RAW1394_ISO_ERROR;
495                 }
496                 goto send_empty_packet;
497             }
498             return RAW1394_ISO_OK;
499         } else if (result == eCRV_XRun) { // pick up the possible xruns
500             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to header xrun\n");
501             m_in_xrun = true;
502             m_cycle_to_switch_state = cycle+1; // switch in the next cycle
503             m_next_state = ePS_WaitingForStreamDisable;
504             // execute the requested change
505             if (!updateState()) { // we are allowed to change the state directly
506                 debugError("Could not update state!\n");
507                 return RAW1394_ISO_ERROR;
508             }
509         } else if (result == eCRV_EmptyPacket) {
510             if(m_state != m_next_state) {
511                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
512                                                 ePSToString(m_state), ePSToString(m_next_state));
513                 // execute the requested change
514                 if (!updateState()) { // we are allowed to change the state directly
515                     debugError("Could not update state!\n");
516                     return RAW1394_ISO_ERROR;
517                 }
518             }
519             goto send_empty_packet;
520         } else if (result == eCRV_Again) {
521             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "have to retry cycle %d\n", cycle);
522             if(m_state != m_next_state) {
523                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
524                                                 ePSToString(m_state), ePSToString(m_next_state));
525                 // execute the requested change
526                 if (!updateState()) { // we are allowed to change the state directly
527                     debugError("Could not update state!\n");
528                     return RAW1394_ISO_ERROR;
529                 }
530             }
531             // force some delay
532             usleep(125);
533             return RAW1394_ISO_AGAIN;
534         } else {
535             debugError("Invalid return value: %d\n", result);
536             return RAW1394_ISO_ERROR;
537         }
538     }
539     // we are not running, so send an empty packet
540     // we should generate a valid packet any time
541 send_empty_packet:
542     // note that only the wait state changes are synchronized with the cycles
543     if(m_state != m_next_state) {
544         debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
545                                         ePSToString(m_state), ePSToString(m_next_state));
546         // execute the requested change
547         if (!updateState()) { // we are allowed to change the state directly
548             debugError("Could not update state!\n");
549             return RAW1394_ISO_ERROR;
550         }
551     }
552
553     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT EMPTY: CY=%04u\n", cycle);
554     generateSilentPacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
555     generateSilentPacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
556     return RAW1394_ISO_DEFER;
557 }
558
559
560 // Frame Transfer API
561 /**
562  * Transfer a block of frames from the event buffer to the port buffers
563  * @param nbframes number of frames to transfer
564  * @param ts the timestamp that the LAST frame in the block should have
565  * @return
566  */
567 bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
568     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.getFrames(%d, %11llu)", nbframes, ts);
569     assert( getType() == ePT_Receive );
570     if(isDryRunning()) return getFramesDry(nbframes, ts);
571     else return getFramesWet(nbframes, ts);
572 }
573
574 bool StreamProcessor::getFramesWet(unsigned int nbframes, int64_t ts) {
575 // FIXME: this should be done somewhere else
576 #ifdef DEBUG
577     uint64_t ts_expected;
578     signed int fc;
579     int32_t lag_ticks;
580     float lag_frames;
581
582     // in order to sync up multiple received streams, we should
583     // use the ts parameter. It specifies the time of the block's
584     // last sample.
585     float srate = m_manager->getSyncSource().getTicksPerFrame();
586     assert(srate != 0.0);
587     int64_t this_block_length_in_ticks = (int64_t)(((float)nbframes) * srate);
588
589     ffado_timestamp_t ts_head_tmp;
590     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);
591     ts_expected = addTicks((uint64_t)ts_head_tmp, this_block_length_in_ticks);
592
593     lag_ticks = diffTicks(ts, ts_expected);
594     lag_frames = (((float)lag_ticks) / srate);
595     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
596                  this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
597     if (lag_frames >= 1.0) {
598         // the stream lags
599         debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
600                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
601     } else if (lag_frames <= -1.0) {
602         // the stream leads
603         debugWarning( "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
604                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
605     }
606 #endif
607     // ask the buffer to process nbframes of frames
608     // using it's registered client's processReadBlock(),
609     // which should be ours
610     m_data_buffer->blockProcessReadFrames(nbframes);
611     return true;
612 }
613
614 bool StreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) {
615     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n",
616                  this, nbframes, ts);
617
618     // dry run on this side means that we put silence in all enabled ports
619     // since there is do data put into the ringbuffer in the dry-running state
620     return provideSilenceBlock(nbframes, 0);
621 }
622
623 bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts) {
624     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.putFrames(%d, %11llu)", nbframes, ts);
625     assert( getType() == ePT_Transmit );
626     if(isDryRunning()) return putFramesDry(nbframes, ts);
627     else return putFramesWet(nbframes, ts);
628 }
629
630 bool
631 StreamProcessor::putFramesWet(unsigned int nbframes, int64_t ts) {
632     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesWet(%d, %llu)\n", nbframes, ts);
633     // transfer the data
634     m_data_buffer->blockProcessWriteFrames(nbframes, ts);
635     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts);
636     return true; // FIXME: what about failure?
637 }
638
639 bool
640 StreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts) {
641     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesDry(%d, %llu)\n", nbframes, ts);
642     // do nothing
643     return true;
644 }
645
646 /***********************************************
647  * State related API                           *
648  ***********************************************/
649 bool StreamProcessor::init()
650 {
651     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "init...\n");
652
653     // initialization can be done without requesting it
654     // from the packet loop
655     m_next_state = ePS_Created;
656     return true;
657 }
658
659 bool StreamProcessor::prepare()
660 {
661     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "prepare...\n");
662     if(!m_manager) {
663         debugFatal("Not attached to a manager!\n");
664         return false;
665     }
666
667     if (!prepareChild()) {
668         debugFatal("Could not prepare child\n");
669         return false;
670     }
671
672     // initialization can be done without requesting it
673     // from the packet loop
674     m_next_state = ePS_Stopped;
675     return updateState();
676 }
677
678 bool
679 StreamProcessor::scheduleStateTransition(enum eProcessorState state, uint64_t time_instant)
680 {
681     // first set the time, since in the packet loop we first check m_state == m_next_state before
682     // using the time
683     m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant);
684     m_next_state = state;
685     return true;
686 }
687
688 bool
689 StreamProcessor::waitForState(enum eProcessorState state, unsigned int timeout_ms)
690 {
691     debugOutput(DEBUG_LEVEL_VERBOSE, "Waiting for state %s\n", ePSToString(state));
692     int cnt = timeout_ms;
693     while (m_state != state && cnt) {
694         usleep(1000);
695         cnt--;
696     }
697     if(cnt==0) {
698         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout\n");
699         return false;
700     }
701     return true;
702 }
703
704 bool StreamProcessor::scheduleStartDryRunning(int64_t t) {
705     uint64_t tx;
706     if (t < 0) {
707         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
708     } else {
709         tx = t;
710     }
711     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
712     uint64_t now = m_handler->getCycleTimerTicks();
713     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
714                           now,
715                           (unsigned int)TICKS_TO_SECS(now),
716                           (unsigned int)TICKS_TO_CYCLES(now),
717                           (unsigned int)TICKS_TO_OFFSET(now));
718     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
719                           tx,
720                           (unsigned int)TICKS_TO_SECS(tx),
721                           (unsigned int)TICKS_TO_CYCLES(tx),
722                           (unsigned int)TICKS_TO_OFFSET(tx));
723     if (m_state == ePS_Stopped) {
724         return scheduleStateTransition(ePS_WaitingForStream, tx);
725     } else if (m_state == ePS_Running) {
726         return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
727     } else {
728         debugError("Cannot switch to ePS_DryRunning from %s\n", ePSToString(m_state));
729         return false;
730     }
731 }
732
733 bool StreamProcessor::scheduleStartRunning(int64_t t) {
734     uint64_t tx;
735     if (t < 0) {
736         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
737     } else {
738         tx = t;
739     }
740     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
741     uint64_t now = m_handler->getCycleTimerTicks();
742     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
743                           now,
744                           (unsigned int)TICKS_TO_SECS(now),
745                           (unsigned int)TICKS_TO_CYCLES(now),
746                           (unsigned int)TICKS_TO_OFFSET(now));
747     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
748                           tx,
749                           (unsigned int)TICKS_TO_SECS(tx),
750                           (unsigned int)TICKS_TO_CYCLES(tx),
751                           (unsigned int)TICKS_TO_OFFSET(tx));
752     return scheduleStateTransition(ePS_WaitingForStreamEnable, tx);
753 }
754
755 bool StreamProcessor::scheduleStopDryRunning(int64_t t) {
756     uint64_t tx;
757     if (t < 0) {
758         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
759     } else {
760         tx = t;
761     }
762     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
763     uint64_t now = m_handler->getCycleTimerTicks();
764     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
765                           now,
766                           (unsigned int)TICKS_TO_SECS(now),
767                           (unsigned int)TICKS_TO_CYCLES(now),
768                           (unsigned int)TICKS_TO_OFFSET(now));
769     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
770                           tx,
771                           (unsigned int)TICKS_TO_SECS(tx),
772                           (unsigned int)TICKS_TO_CYCLES(tx),
773                           (unsigned int)TICKS_TO_OFFSET(tx));
774     return scheduleStateTransition(ePS_Stopped, tx);
775 }
776
777 bool StreamProcessor::scheduleStopRunning(int64_t t) {
778     uint64_t tx;
779     if (t < 0) {
780         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
781     } else {
782         tx = t;
783     }
784     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
785     uint64_t now = m_handler->getCycleTimerTicks();
786     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
787                           now,
788                           (unsigned int)TICKS_TO_SECS(now),
789                           (unsigned int)TICKS_TO_CYCLES(now),
790                           (unsigned int)TICKS_TO_OFFSET(now));
791     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
792                           tx,
793                           (unsigned int)TICKS_TO_SECS(tx),
794                           (unsigned int)TICKS_TO_CYCLES(tx),
795                           (unsigned int)TICKS_TO_OFFSET(tx));
796     return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
797 }
798
799 bool StreamProcessor::startDryRunning(int64_t t) {
800     if(!scheduleStartDryRunning(t)) {
801         debugError("Could not schedule transition\n");
802         return false;
803     }
804     if(!waitForState(ePS_DryRunning, 2000)) {
805         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
806         return false;
807     }
808     return true;
809 }
810
811 bool StreamProcessor::startRunning(int64_t t) {
812     if(!scheduleStartRunning(t)) {
813         debugError("Could not schedule transition\n");
814         return false;
815     }
816     if(!waitForState(ePS_Running, 2000)) {
817         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Running));
818         return false;
819     }
820     return true;
821 }
822
823 bool StreamProcessor::stopDryRunning(int64_t t) {
824     if(!scheduleStopDryRunning(t)) {
825         debugError("Could not schedule transition\n");
826         return false;
827     }
828     if(!waitForState(ePS_Stopped, 2000)) {
829         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Stopped));
830         return false;
831     }
832     return true;
833 }
834
835 bool StreamProcessor::stopRunning(int64_t t) {
836     if(!scheduleStopRunning(t)) {
837         debugError("Could not schedule transition\n");
838         return false;
839     }
840     if(!waitForState(ePS_DryRunning, 2000)) {
841         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
842         return false;
843     }
844     return true;
845 }
846
847
848 // internal state API
849
850 /**
851  * @brief Enter the ePS_Stopped state
852  * @return true if successful, false if not
853  *
854  * @pre none
855  *
856  * @post the buffer and the isostream are ready for use.
857  * @post all dynamic structures have been allocated successfully
858  * @post the buffer is transparent and empty, and all parameters are set
859  *       to the correct initial/nominal values.
860  *
861  */
862 bool
863 StreamProcessor::doStop()
864 {
865     float ticks_per_frame;
866     unsigned int ringbuffer_size_frames = m_manager->getNbBuffers() * m_manager->getPeriodSize();
867
868     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
869     bool result = true;
870
871     switch(m_state) {
872         case ePS_Created:
873             assert(m_data_buffer);
874             // object just created
875             result = m_data_buffer->init();
876
877             // prepare the framerate estimate
878             ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate());
879             m_ticks_per_frame = ticks_per_frame;
880             debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n", ticks_per_frame);
881
882             // initialize internal buffer
883             result &= m_data_buffer->setBufferSize(ringbuffer_size_frames);
884
885             result &= m_data_buffer->setEventSize( getEventSize() );
886             result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() );
887             if(getType() == ePT_Receive) {
888                 result &= m_data_buffer->setUpdatePeriod( getNominalFramesPerPacket() );
889             } else {
890                 result &= m_data_buffer->setUpdatePeriod( m_manager->getPeriodSize() );
891             }
892             result &= m_data_buffer->setNominalRate(ticks_per_frame);
893             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
894             result &= m_data_buffer->prepare(); // FIXME: the name
895
896             // set the parameters of ports we can:
897             // we want the audio ports to be period buffered,
898             // and the midi ports to be packet buffered
899             for ( PortVectorIterator it = m_Ports.begin();
900                 it != m_Ports.end();
901                 ++it )
902             {
903                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
904                 if(!(*it)->setBufferSize(m_manager->getPeriodSize())) {
905                     debugFatal("Could not set buffer size to %d\n",m_manager->getPeriodSize());
906                     return false;
907                 }
908                 switch ((*it)->getPortType()) {
909                     case Port::E_Audio:
910                         if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
911                             debugFatal("Could not set signal type to PeriodSignalling");
912                             return false;
913                         }
914                         // buffertype and datatype are dependant on the API
915                         debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
916                         // buffertype and datatype are dependant on the API
917                         if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
918                             debugFatal("Could not set buffer type");
919                             return false;
920                         }
921                         if(!(*it)->useExternalBuffer(true)) {
922                             debugFatal("Could not set external buffer usage");
923                             return false;
924                         }
925                         if(!(*it)->setDataType(Port::E_Float)) {
926                             debugFatal("Could not set data type");
927                             return false;
928                         }
929                         break;
930                     case Port::E_Midi:
931                         if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
932                             debugFatal("Could not set signal type to PacketSignalling");
933                             return false;
934                         }
935                         // buffertype and datatype are dependant on the API
936                         debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
937                         // buffertype and datatype are dependant on the API
938                         if(!(*it)->setBufferType(Port::E_RingBuffer)) {
939                             debugFatal("Could not set buffer type");
940                             return false;
941                         }
942                         if(!(*it)->setDataType(Port::E_MidiEvent)) {
943                             debugFatal("Could not set data type");
944                             return false;
945                         }
946                         break;
947                     default:
948                         debugWarning("Unsupported port type specified\n");
949                         break;
950                 }
951             }
952             // the API specific settings of the ports should already be set,
953             // as this is called from the processorManager->prepare()
954             // so we can init the ports
955             result &= PortManager::initPorts();
956
957             break;
958         case ePS_DryRunning:
959             // what to do here?
960             break;
961         default:
962             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
963             return false;
964     }
965
966     result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
967     // make the buffer transparent
968     m_data_buffer->setTransparent(true);
969
970     // reset all ports
971     result &= PortManager::preparePorts();
972
973     m_state = ePS_Stopped;
974     #ifdef DEBUG
975     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
976         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
977         dumpInfo();
978     }
979     #endif
980     return result;
981 }
982
983 /**
984  * @brief Enter the ePS_WaitingForStream state
985  * @return true if successful, false if not
986  *
987  * @pre all dynamic data structures are allocated successfully
988  *
989  * @post
990  *
991  */
992 bool
993 StreamProcessor::doWaitForRunningStream()
994 {
995     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
996     switch(m_state) {
997         case ePS_Stopped:
998             // we have to start waiting for an incoming stream
999             // this basically means nothing, the state change will
1000             // be picked up by the packet iterator
1001             break;
1002         default:
1003             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1004             return false;
1005     }
1006     m_state = ePS_WaitingForStream;
1007     #ifdef DEBUG
1008     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1009         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1010         dumpInfo();
1011     }
1012     #endif
1013     return true;
1014 }
1015
1016 /**
1017  * @brief Enter the ePS_DryRunning state
1018  * @return true if successful, false if not
1019  *
1020  * @pre
1021  *
1022  * @post
1023  *
1024  */
1025 bool
1026 StreamProcessor::doDryRunning()
1027 {
1028     bool result = true;
1029     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1030     switch(m_state) {
1031         case ePS_WaitingForStream:
1032             // a running stream has been detected
1033             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started dry-running at cycle %d\n", this, m_last_cycle);
1034             if (getType() == ePT_Receive) {
1035                 // this to ensure that there is no discontinuity when starting to
1036                 // update the DLL based upon the received packets
1037                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
1038             } else {
1039                 // FIXME: PC=master mode will have to do something here I guess...
1040             }
1041             break;
1042         case ePS_WaitingForStreamDisable:
1043             result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
1044             m_data_buffer->setTransparent(true);
1045             break;
1046         default:
1047             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1048             return false;
1049     }
1050     m_state = ePS_DryRunning;
1051     #ifdef DEBUG
1052     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1053         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1054         dumpInfo();
1055     }
1056     #endif
1057     return result;
1058 }
1059
1060 /**
1061  * @brief Enter the ePS_WaitingForStreamEnable state
1062  * @return true if successful, false if not
1063  *
1064  * @pre
1065  *
1066  * @post
1067  *
1068  */
1069 bool
1070 StreamProcessor::doWaitForStreamEnable()
1071 {
1072     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1073     unsigned int ringbuffer_size_frames;
1074     switch(m_state) {
1075         case ePS_DryRunning:
1076             // we have to start waiting for an incoming stream
1077             // this basically means nothing, the state change will
1078             // be picked up by the packet iterator
1079
1080             if(!m_data_buffer->clearBuffer()) { // FIXME: don't like the reset() name
1081                 debugError("Could not reset data buffer\n");
1082                 return false;
1083             }
1084             if (getType() == ePT_Transmit) {
1085                 ringbuffer_size_frames = m_manager->getNbBuffers() * m_manager->getPeriodSize();
1086                 debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames\n", this, ringbuffer_size_frames);
1087                 // prefill the buffer
1088                 if(!transferSilence(ringbuffer_size_frames)) {
1089                     debugFatal("Could not prefill transmit stream\n");
1090                     return false;
1091                 }
1092             }
1093
1094             break;
1095         default:
1096             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1097             return false;
1098     }
1099     m_state = ePS_WaitingForStreamEnable;
1100     #ifdef DEBUG
1101     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1102         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1103         dumpInfo();
1104     }
1105     #endif
1106     return true;
1107 }
1108
1109 /**
1110  * @brief Enter the ePS_Running state
1111  * @return true if successful, false if not
1112  *
1113  * @pre
1114  *
1115  * @post
1116  *
1117  */
1118 bool
1119 StreamProcessor::doRunning()
1120 {
1121     bool result = true;
1122     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1123     switch(m_state) {
1124         case ePS_WaitingForStreamEnable:
1125             // a running stream has been detected
1126             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started running at cycle %d\n",
1127                                              this, m_last_cycle);
1128             m_in_xrun = false;
1129             m_data_buffer->setTransparent(false);
1130             break;
1131         default:
1132             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1133             return false;
1134     }
1135     m_state = ePS_Running;
1136     #ifdef DEBUG
1137     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1138         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1139         dumpInfo();
1140     }
1141     #endif
1142     return result;
1143 }
1144
1145 /**
1146  * @brief Enter the ePS_WaitingForStreamDisable state
1147  * @return true if successful, false if not
1148  *
1149  * @pre
1150  *
1151  * @post
1152  *
1153  */
1154 bool
1155 StreamProcessor::doWaitForStreamDisable()
1156 {
1157     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1158     switch(m_state) {
1159         case ePS_Running:
1160             // the thread will do the transition
1161             break;
1162         default:
1163             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1164             return false;
1165     }
1166     m_state = ePS_WaitingForStreamDisable;
1167     #ifdef DEBUG
1168     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1169         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1170         dumpInfo();
1171     }
1172     #endif
1173     return true;
1174 }
1175
1176 /**
1177  * @brief Updates the state machine and calls the necessary transition functions
1178  * @return true if successful, false if not
1179  */
1180 bool StreamProcessor::updateState() {
1181     bool result = false;
1182     // copy the current state locally since it could change value,
1183     // and that's something we don't want to happen inbetween tests
1184     // if m_next_state changes during this routine, we know for sure
1185     // that the previous state change was at least attempted correctly.
1186     enum eProcessorState next_state = m_next_state;
1187
1188     debugOutput(DEBUG_LEVEL_VERBOSE, "Do state transition: %s => %s\n",
1189         ePSToString(m_state), ePSToString(next_state));
1190
1191     if (m_state == next_state) {
1192         debugWarning("ignoring identity state update from/to %s\n", ePSToString(m_state) );
1193         return true;
1194     }
1195
1196     // after creation, only initialization is allowed
1197     if (m_state == ePS_Created) {
1198         if(next_state != ePS_Stopped) {
1199             goto updateState_exit_with_error;
1200         }
1201         // do init here
1202         result = doStop();
1203         if (result) return true;
1204         else goto updateState_exit_change_failed;
1205     }
1206
1207     // after initialization, only WaitingForRunningStream is allowed
1208     if (m_state == ePS_Stopped) {
1209         if(next_state != ePS_WaitingForStream) {
1210             goto updateState_exit_with_error;
1211         }
1212         result = doWaitForRunningStream();
1213         if (result) return true;
1214         else goto updateState_exit_change_failed;
1215     }
1216
1217     // after WaitingForStream, only ePS_DryRunning is allowed
1218     // this means that the stream started running
1219     if (m_state == ePS_WaitingForStream) {
1220         if(next_state != ePS_DryRunning) {
1221             goto updateState_exit_with_error;
1222         }
1223         result = doDryRunning();
1224         if (result) return true;
1225         else goto updateState_exit_change_failed;
1226     }
1227
1228     // from ePS_DryRunning we can go to:
1229     //   - ePS_Stopped if something went wrong during DryRunning
1230     //   - ePS_WaitingForStreamEnable if there is a requested to enable
1231     if (m_state == ePS_DryRunning) {
1232         if((next_state != ePS_Stopped) &&
1233            (next_state != ePS_WaitingForStreamEnable)) {
1234             goto updateState_exit_with_error;
1235         }
1236         if (next_state == ePS_Stopped) {
1237             result = doStop();
1238         } else {
1239             result = doWaitForStreamEnable();
1240         }
1241         if (result) return true;
1242         else goto updateState_exit_change_failed;
1243     }
1244
1245     // from ePS_WaitingForStreamEnable we can go to:
1246     //   - ePS_DryRunning if something went wrong while waiting
1247     //   - ePS_Running if the stream enabled correctly
1248     if (m_state == ePS_WaitingForStreamEnable) {
1249         if((next_state != ePS_DryRunning) &&
1250            (next_state != ePS_Running)) {
1251             goto updateState_exit_with_error;
1252         }
1253         if (next_state == ePS_Stopped) {
1254             result = doDryRunning();
1255         } else {
1256             result = doRunning();
1257         }
1258         if (result) return true;
1259         else goto updateState_exit_change_failed;
1260     }
1261
1262     // from ePS_Running we can only start waiting for a disabled stream
1263     if (m_state == ePS_Running) {
1264         if(next_state != ePS_WaitingForStreamDisable) {
1265             goto updateState_exit_with_error;
1266         }
1267         result = doWaitForStreamDisable();
1268         if (result) return true;
1269         else goto updateState_exit_change_failed;
1270     }
1271
1272     // from ePS_WaitingForStreamDisable we can go to DryRunning
1273     if (m_state == ePS_WaitingForStreamDisable) {
1274         if(next_state != ePS_DryRunning) {
1275             goto updateState_exit_with_error;
1276         }
1277         result = doDryRunning();
1278         if (result) return true;
1279         else goto updateState_exit_change_failed;
1280     }
1281
1282     // if we arrive here there is an error
1283 updateState_exit_with_error:
1284     debugError("Invalid state transition: %s => %s\n",
1285         ePSToString(m_state), ePSToString(next_state));
1286     return false;
1287 updateState_exit_change_failed:
1288     debugError("State transition failed: %s => %s\n",
1289         ePSToString(m_state), ePSToString(next_state));
1290     return false;
1291 }
1292
1293 /***********************************************
1294  * Helper routines                             *
1295  ***********************************************/
1296 bool
1297 StreamProcessor::transferSilence(unsigned int nframes)
1298 {
1299     bool retval;
1300     signed int fc;
1301     ffado_timestamp_t ts_tail_tmp;
1302
1303     // prepare a buffer of silence
1304     char *dummybuffer = (char *)calloc(sizeof(quadlet_t), nframes * getEventsPerFrame());
1305     transmitSilenceBlock(dummybuffer, nframes, 0);
1306
1307     m_data_buffer->getBufferTailTimestamp(&ts_tail_tmp, &fc);
1308     if (fc != 0) {
1309         debugWarning("Prefilling a buffer that already contains %d frames\n", fc);
1310     }
1311
1312     // add the silence data to the ringbuffer
1313     if(m_data_buffer->preloadFrames(nframes, dummybuffer, true)) {
1314         retval = true;
1315     } else {
1316         debugWarning("Could not write to event buffer\n");
1317         retval = false;
1318     }
1319     free(dummybuffer);
1320     return retval;
1321 }
1322
1323 /**
1324  * @brief convert a eProcessorState to a string
1325  * @param s the state
1326  * @return a char * describing the state
1327  */
1328 const char *
1329 StreamProcessor::ePSToString(enum eProcessorState s) {
1330     switch (s) {
1331         case ePS_Invalid: return "ePS_Invalid";
1332         case ePS_Created: return "ePS_Created";
1333         case ePS_Stopped: return "ePS_Stopped";
1334         case ePS_WaitingForStream: return "ePS_WaitingForStream";
1335         case ePS_DryRunning: return "ePS_DryRunning";
1336         case ePS_WaitingForStreamEnable: return "ePS_WaitingForStreamEnable";
1337         case ePS_Running: return "ePS_Running";
1338         case ePS_WaitingForStreamDisable: return "ePS_WaitingForStreamDisable";
1339         default: return "error: unknown state";
1340     }
1341 }
1342
1343 /**
1344  * @brief convert a eProcessorType to a string
1345  * @param t the type
1346  * @return a char * describing the state
1347  */
1348 const char *
1349 StreamProcessor::ePTToString(enum eProcessorType t) {
1350     switch (t) {
1351         case ePT_Receive: return "Receive";
1352         case ePT_Transmit: return "Transmit";
1353         default: return "error: unknown type";
1354     }
1355 }
1356
1357 /***********************************************
1358  * Debug                                       *
1359  ***********************************************/
1360 void
1361 StreamProcessor::dumpInfo()
1362 {
1363     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor information\n");
1364     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Iso stream info:\n");
1365
1366     IsoStream::dumpInfo();
1367     debugOutputShort( DEBUG_LEVEL_NORMAL, "  StreamProcessor info:\n");
1368     if (m_handler) {
1369         uint64_t now = m_handler->getCycleTimerTicks();
1370         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011llu (%03us %04uc %04ut)\n",
1371                           now,
1372                           (unsigned int)TICKS_TO_SECS(now),
1373                           (unsigned int)TICKS_TO_CYCLES(now),
1374                           (unsigned int)TICKS_TO_OFFSET(now));
1375     }
1376     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xruns                 : %s\n", (m_in_xrun ? "True":"False"));
1377     debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s\n", ePSToString(m_state));
1378     debugOutputShort( DEBUG_LEVEL_NORMAL, "   Next state           : %s\n", ePSToString(m_next_state));
1379     debugOutputShort( DEBUG_LEVEL_NORMAL, "    transition at       : %u\n", m_cycle_to_switch_state);
1380     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer                : %p\n", m_data_buffer);
1381     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Nominal framerate     : %u\n", m_manager->getNominalRate());
1382     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate      : Sync: %f, Buffer %f\n",
1383         24576000.0/m_manager->getSyncSource().m_data_buffer->getRate(),
1384         24576000.0/m_data_buffer->getRate()
1385         );
1386
1387     m_data_buffer->dumpInfo();
1388 }
1389
1390 void
1391 StreamProcessor::setVerboseLevel(int l) {
1392     setDebugLevel(l);
1393     IsoStream::setVerboseLevel(l);
1394     PortManager::setVerboseLevel(l);
1395     m_data_buffer->setVerboseLevel(l);
1396 }
1397
1398 } // end of namespace
Note: See TracBrowser for help on using the browser.