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

Revision 720, 47.2 kB (checked in by ppalmers, 13 years ago)

first working version of the reworked streaming code

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