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

Revision 723, 52.5 kB (checked in by ppalmers, 14 years ago)

fix problem where receiving multiple streams doesn't work

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