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

Revision 721, 48.5 kB (checked in by ppalmers, 13 years ago)

another update

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         } else { // pick up the possible xruns
467            
468         }
469     }
470     // we are not running, so send an empty packet
471     // we should generate a valid packet any time
472 send_empty_packet:
473     // note that only the wait state changes are synchronized with the cycles
474     if(m_state != m_next_state) {
475         debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
476                                         ePSToString(m_state), ePSToString(m_next_state));
477         // execute the requested change
478         if (!updateState()) { // we are allowed to change the state directly
479             debugError("Could not update state!\n");
480             return RAW1394_ISO_ERROR;
481         }
482     }
483
484     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT EMPTY: CY=%04u\n", cycle);
485     generateSilentPacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
486     generateSilentPacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
487     return RAW1394_ISO_DEFER;
488 }
489
490
491 // Frame Transfer API
492 /**
493  * Transfer a block of frames from the event buffer to the port buffers
494  * @param nbframes number of frames to transfer
495  * @param ts the timestamp that the LAST frame in the block should have
496  * @return
497  */
498 bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
499     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.getFrames(%d, %11llu)", nbframes, ts);
500     assert( getType() == ePT_Receive );
501     if(isDryRunning()) return getFramesDry(nbframes, ts);
502     else return getFramesWet(nbframes, ts);
503 }
504
505 bool StreamProcessor::getFramesWet(unsigned int nbframes, int64_t ts) {
506 // FIXME: this should be done somewhere else
507 #ifdef DEBUG
508     uint64_t ts_expected;
509     signed int fc;
510     int32_t lag_ticks;
511     float lag_frames;
512
513     // in order to sync up multiple received streams, we should
514     // use the ts parameter. It specifies the time of the block's
515     // last sample.
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     lag_frames = (((float)lag_ticks) / srate);
526     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
527                  this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
528     if (lag_frames >= 1.0) {
529         // the stream lags
530         debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
531                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
532     } else if (lag_frames <= -1.0) {
533         // the stream leads
534         debugWarning( "stream (%p): leads 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     }
537 #endif
538     // ask the buffer to process nbframes of frames
539     // using it's registered client's processReadBlock(),
540     // which should be ours
541     m_data_buffer->blockProcessReadFrames(nbframes);
542     return true;
543 }
544
545 bool StreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) {
546     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n",
547                  this, nbframes, ts);
548
549     // dry run on this side means that we put silence in all enabled ports
550     // since there is do data put into the ringbuffer in the dry-running state
551     return provideSilenceBlock(nbframes, 0);
552 }
553
554 bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts) {
555     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.putFrames(%d, %11llu)", nbframes, ts);
556     assert( getType() == ePT_Transmit );
557     if(isDryRunning()) return putFramesDry(nbframes, ts);
558     else return putFramesWet(nbframes, ts);
559 }
560
561 bool
562 StreamProcessor::putFramesWet(unsigned int nbframes, int64_t ts) {
563     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesWet(%d, %llu)\n", nbframes, ts);
564     // transfer the data
565     m_data_buffer->blockProcessWriteFrames(nbframes, ts);
566     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts);
567     return true; // FIXME: what about failure?
568 }
569
570 bool
571 StreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts) {
572     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesDry(%d, %llu)\n", nbframes, ts);
573     // do nothing
574     return true;
575 }
576
577 /***********************************************
578  * State related API                           *
579  ***********************************************/
580 bool StreamProcessor::init()
581 {
582     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "init...\n");
583
584     // initialization can be done without requesting it
585     // from the packet loop
586     m_next_state = ePS_Created;
587     return true;
588 }
589
590 bool StreamProcessor::prepare()
591 {
592     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "prepare...\n");
593     if(!m_manager) {
594         debugFatal("Not attached to a manager!\n");
595         return false;
596     }
597
598     if (!prepareChild()) {
599         debugFatal("Could not prepare child\n");
600         return false;
601     }
602
603     // initialization can be done without requesting it
604     // from the packet loop
605     m_next_state = ePS_Stopped;
606     return updateState();
607 }
608
609 bool
610 StreamProcessor::scheduleStateTransition(enum eProcessorState state, uint64_t time_instant)
611 {
612     // first set the time, since in the packet loop we first check m_state == m_next_state before
613     // using the time
614     m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant);
615     m_next_state = state;
616     return true;
617 }
618
619 bool
620 StreamProcessor::waitForState(enum eProcessorState state, unsigned int timeout_ms)
621 {
622     debugOutput(DEBUG_LEVEL_VERBOSE, "Waiting for state %s\n", ePSToString(state));
623     int cnt = timeout_ms;
624     while (m_state != state && cnt) {
625         usleep(1000);
626         cnt--;
627     }
628     if(cnt==0) {
629         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout\n");
630         return false;
631     }
632     return true;
633 }
634
635 bool StreamProcessor::scheduleStartDryRunning(int64_t t) {
636     uint64_t tx;
637     if (t < 0) {
638         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
639     } else {
640         tx = t;
641     }
642     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
643     uint64_t now = m_handler->getCycleTimerTicks();
644     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
645                           now,
646                           (unsigned int)TICKS_TO_SECS(now),
647                           (unsigned int)TICKS_TO_CYCLES(now),
648                           (unsigned int)TICKS_TO_OFFSET(now));
649     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
650                           tx,
651                           (unsigned int)TICKS_TO_SECS(tx),
652                           (unsigned int)TICKS_TO_CYCLES(tx),
653                           (unsigned int)TICKS_TO_OFFSET(tx));
654     if (m_state == ePS_Stopped) {
655         return scheduleStateTransition(ePS_WaitingForStream, tx);
656     } else if (m_state == ePS_Running) {
657         return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
658     } else {
659         debugError("Cannot switch to ePS_DryRunning from %s\n", ePSToString(m_state));
660         return false;
661     }
662 }
663
664 bool StreamProcessor::scheduleStartRunning(int64_t t) {
665     uint64_t tx;
666     if (t < 0) {
667         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
668     } else {
669         tx = t;
670     }
671     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
672     uint64_t now = m_handler->getCycleTimerTicks();
673     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
674                           now,
675                           (unsigned int)TICKS_TO_SECS(now),
676                           (unsigned int)TICKS_TO_CYCLES(now),
677                           (unsigned int)TICKS_TO_OFFSET(now));
678     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
679                           tx,
680                           (unsigned int)TICKS_TO_SECS(tx),
681                           (unsigned int)TICKS_TO_CYCLES(tx),
682                           (unsigned int)TICKS_TO_OFFSET(tx));
683     return scheduleStateTransition(ePS_WaitingForStreamEnable, tx);
684 }
685
686 bool StreamProcessor::scheduleStopDryRunning(int64_t t) {
687     uint64_t tx;
688     if (t < 0) {
689         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
690     } else {
691         tx = t;
692     }
693     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
694     uint64_t now = m_handler->getCycleTimerTicks();
695     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
696                           now,
697                           (unsigned int)TICKS_TO_SECS(now),
698                           (unsigned int)TICKS_TO_CYCLES(now),
699                           (unsigned int)TICKS_TO_OFFSET(now));
700     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
701                           tx,
702                           (unsigned int)TICKS_TO_SECS(tx),
703                           (unsigned int)TICKS_TO_CYCLES(tx),
704                           (unsigned int)TICKS_TO_OFFSET(tx));
705     return scheduleStateTransition(ePS_Stopped, tx);
706 }
707
708 bool StreamProcessor::scheduleStopRunning(int64_t t) {
709     uint64_t tx;
710     if (t < 0) {
711         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
712     } else {
713         tx = t;
714     }
715     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
716     uint64_t now = m_handler->getCycleTimerTicks();
717     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
718                           now,
719                           (unsigned int)TICKS_TO_SECS(now),
720                           (unsigned int)TICKS_TO_CYCLES(now),
721                           (unsigned int)TICKS_TO_OFFSET(now));
722     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
723                           tx,
724                           (unsigned int)TICKS_TO_SECS(tx),
725                           (unsigned int)TICKS_TO_CYCLES(tx),
726                           (unsigned int)TICKS_TO_OFFSET(tx));
727     return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
728 }
729
730 bool StreamProcessor::startDryRunning(int64_t t) {
731     if(!scheduleStartDryRunning(t)) {
732         debugError("Could not schedule transition\n");
733         return false;
734     }
735     if(!waitForState(ePS_DryRunning, 2000)) {
736         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
737         return false;
738     }
739     return true;
740 }
741
742 bool StreamProcessor::startRunning(int64_t t) {
743     if(!scheduleStartRunning(t)) {
744         debugError("Could not schedule transition\n");
745         return false;
746     }
747     if(!waitForState(ePS_Running, 2000)) {
748         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Running));
749         return false;
750     }
751     return true;
752 }
753
754 bool StreamProcessor::stopDryRunning(int64_t t) {
755     if(!scheduleStopDryRunning(t)) {
756         debugError("Could not schedule transition\n");
757         return false;
758     }
759     if(!waitForState(ePS_Stopped, 2000)) {
760         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Stopped));
761         return false;
762     }
763     return true;
764 }
765
766 bool StreamProcessor::stopRunning(int64_t t) {
767     if(!scheduleStopRunning(t)) {
768         debugError("Could not schedule transition\n");
769         return false;
770     }
771     if(!waitForState(ePS_DryRunning, 2000)) {
772         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
773         return false;
774     }
775     return true;
776 }
777
778
779 // internal state API
780
781 /**
782  * @brief Enter the ePS_Stopped state
783  * @return true if successful, false if not
784  *
785  * @pre none
786  *
787  * @post the buffer and the isostream are ready for use.
788  * @post all dynamic structures have been allocated successfully
789  * @post the buffer is transparent and empty, and all parameters are set
790  *       to the correct initial/nominal values.
791  *
792  */
793 bool
794 StreamProcessor::doStop()
795 {
796     float ticks_per_frame;
797     unsigned int ringbuffer_size_frames = m_manager->getNbBuffers() * m_manager->getPeriodSize();
798
799     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
800     bool result = true;
801
802     switch(m_state) {
803         case ePS_Created:
804             assert(m_data_buffer);
805             // object just created
806             result = m_data_buffer->init();
807
808             // prepare the framerate estimate
809             ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate());
810             m_ticks_per_frame = ticks_per_frame;
811             debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n", ticks_per_frame);
812
813             // initialize internal buffer
814             result &= m_data_buffer->setBufferSize(ringbuffer_size_frames);
815
816             result &= m_data_buffer->setEventSize( getEventSize() );
817             result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() );
818             if(getType() == ePT_Receive) {
819                 result &= m_data_buffer->setUpdatePeriod( getNominalFramesPerPacket() );
820             } else {
821                 result &= m_data_buffer->setUpdatePeriod( m_manager->getPeriodSize() );
822             }
823             result &= m_data_buffer->setNominalRate(ticks_per_frame);
824             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
825             result &= m_data_buffer->prepare(); // FIXME: the name
826
827             // set the parameters of ports we can:
828             // we want the audio ports to be period buffered,
829             // and the midi ports to be packet buffered
830             for ( PortVectorIterator it = m_Ports.begin();
831                 it != m_Ports.end();
832                 ++it )
833             {
834                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
835                 if(!(*it)->setBufferSize(m_manager->getPeriodSize())) {
836                     debugFatal("Could not set buffer size to %d\n",m_manager->getPeriodSize());
837                     return false;
838                 }
839                 switch ((*it)->getPortType()) {
840                     case Port::E_Audio:
841                         if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
842                             debugFatal("Could not set signal type to PeriodSignalling");
843                             return false;
844                         }
845                         // buffertype and datatype are dependant on the API
846                         debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
847                         // buffertype and datatype are dependant on the API
848                         if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
849                             debugFatal("Could not set buffer type");
850                             return false;
851                         }
852                         if(!(*it)->useExternalBuffer(true)) {
853                             debugFatal("Could not set external buffer usage");
854                             return false;
855                         }
856                         if(!(*it)->setDataType(Port::E_Float)) {
857                             debugFatal("Could not set data type");
858                             return false;
859                         }
860                         break;
861                     case Port::E_Midi:
862                         if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
863                             debugFatal("Could not set signal type to PacketSignalling");
864                             return false;
865                         }
866                         // buffertype and datatype are dependant on the API
867                         debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
868                         // buffertype and datatype are dependant on the API
869                         if(!(*it)->setBufferType(Port::E_RingBuffer)) {
870                             debugFatal("Could not set buffer type");
871                             return false;
872                         }
873                         if(!(*it)->setDataType(Port::E_MidiEvent)) {
874                             debugFatal("Could not set data type");
875                             return false;
876                         }
877                         break;
878                     default:
879                         debugWarning("Unsupported port type specified\n");
880                         break;
881                 }
882             }
883             // the API specific settings of the ports should already be set,
884             // as this is called from the processorManager->prepare()
885             // so we can init the ports
886             result &= PortManager::initPorts();
887
888             break;
889         case ePS_DryRunning:
890             // what to do here?
891             break;
892         default:
893             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
894             return false;
895     }
896
897     result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
898     // make the buffer transparent
899     m_data_buffer->setTransparent(true);
900
901     // reset all ports
902     result &= PortManager::preparePorts();
903
904     m_state = ePS_Stopped;
905     #ifdef DEBUG
906     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
907         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
908         dumpInfo();
909     }
910     #endif
911     return result;
912 }
913
914 /**
915  * @brief Enter the ePS_WaitingForStream state
916  * @return true if successful, false if not
917  *
918  * @pre all dynamic data structures are allocated successfully
919  *
920  * @post
921  *
922  */
923 bool
924 StreamProcessor::doWaitForRunningStream()
925 {
926     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
927     switch(m_state) {
928         case ePS_Stopped:
929             // we have to start waiting for an incoming stream
930             // this basically means nothing, the state change will
931             // be picked up by the packet iterator
932             break;
933         default:
934             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
935             return false;
936     }
937     m_state = ePS_WaitingForStream;
938     #ifdef DEBUG
939     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
940         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
941         dumpInfo();
942     }
943     #endif
944     return true;
945 }
946
947 /**
948  * @brief Enter the ePS_DryRunning state
949  * @return true if successful, false if not
950  *
951  * @pre
952  *
953  * @post
954  *
955  */
956 bool
957 StreamProcessor::doDryRunning()
958 {
959     bool result = true;
960     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
961     switch(m_state) {
962         case ePS_WaitingForStream:
963             // a running stream has been detected
964             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started dry-running at cycle %d\n", this, m_last_cycle);
965             if (getType() == ePT_Receive) {
966                 // this to ensure that there is no discontinuity when starting to
967                 // update the DLL based upon the received packets
968                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
969             } else {
970                 // FIXME
971                 debugError("Implement\n");
972             }
973             break;
974         case ePS_WaitingForStreamDisable:
975             result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
976             m_data_buffer->setTransparent(true);
977             break;
978         default:
979             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
980             return false;
981     }
982     m_state = ePS_DryRunning;
983     #ifdef DEBUG
984     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
985         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
986         dumpInfo();
987     }
988     #endif
989     return result;
990 }
991
992 /**
993  * @brief Enter the ePS_WaitingForStreamEnable state
994  * @return true if successful, false if not
995  *
996  * @pre
997  *
998  * @post
999  *
1000  */
1001 bool
1002 StreamProcessor::doWaitForStreamEnable()
1003 {
1004     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1005     unsigned int ringbuffer_size_frames;
1006     switch(m_state) {
1007         case ePS_DryRunning:
1008             // we have to start waiting for an incoming stream
1009             // this basically means nothing, the state change will
1010             // be picked up by the packet iterator
1011
1012             if(!m_data_buffer->clearBuffer()) { // FIXME: don't like the reset() name
1013                 debugError("Could not reset data buffer\n");
1014                 return false;
1015             }
1016             if (getType() == ePT_Transmit) {
1017                 ringbuffer_size_frames = m_manager->getNbBuffers() * m_manager->getPeriodSize();
1018                 debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames\n", this, ringbuffer_size_frames);
1019                 // prefill the buffer
1020                 if(!transferSilence(ringbuffer_size_frames)) {
1021                     debugFatal("Could not prefill transmit stream\n");
1022                     return false;
1023                 }
1024             }
1025
1026             break;
1027         default:
1028             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1029             return false;
1030     }
1031     m_state = ePS_WaitingForStreamEnable;
1032     #ifdef DEBUG
1033     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1034         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1035         dumpInfo();
1036     }
1037     #endif
1038     return true;
1039 }
1040
1041 /**
1042  * @brief Enter the ePS_Running state
1043  * @return true if successful, false if not
1044  *
1045  * @pre
1046  *
1047  * @post
1048  *
1049  */
1050 bool
1051 StreamProcessor::doRunning()
1052 {
1053     bool result = true;
1054     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1055     switch(m_state) {
1056         case ePS_WaitingForStreamEnable:
1057             // a running stream has been detected
1058             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started running at cycle %d\n",
1059                                              this, m_last_cycle);
1060             m_xruns = 0;
1061             m_data_buffer->setTransparent(false);
1062             break;
1063         default:
1064             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1065             return false;
1066     }
1067     m_state = ePS_Running;
1068     #ifdef DEBUG
1069     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1070         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1071         dumpInfo();
1072     }
1073     #endif
1074     return result;
1075 }
1076
1077 /**
1078  * @brief Enter the ePS_WaitingForStreamDisable state
1079  * @return true if successful, false if not
1080  *
1081  * @pre
1082  *
1083  * @post
1084  *
1085  */
1086 bool
1087 StreamProcessor::doWaitForStreamDisable()
1088 {
1089     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1090     switch(m_state) {
1091         case ePS_Running:
1092             // the thread will do the transition
1093             break;
1094         default:
1095             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1096             return false;
1097     }
1098     m_state = ePS_WaitingForStreamDisable;
1099     #ifdef DEBUG
1100     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1101         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1102         dumpInfo();
1103     }
1104     #endif
1105     return true;
1106 }
1107
1108 /**
1109  * @brief Updates the state machine and calls the necessary transition functions
1110  * @return true if successful, false if not
1111  */
1112 bool StreamProcessor::updateState() {
1113     bool result = false;
1114     // copy the current state locally since it could change value,
1115     // and that's something we don't want to happen inbetween tests
1116     // if m_next_state changes during this routine, we know for sure
1117     // that the previous state change was at least attempted correctly.
1118     enum eProcessorState next_state = m_next_state;
1119
1120     debugOutput(DEBUG_LEVEL_VERBOSE, "Do state transition: %s => %s\n",
1121         ePSToString(m_state), ePSToString(next_state));
1122
1123     if (m_state == next_state) {
1124         debugWarning("ignoring identity state update from/to %s\n", ePSToString(m_state) );
1125         return true;
1126     }
1127
1128     // after creation, only initialization is allowed
1129     if (m_state == ePS_Created) {
1130         if(next_state != ePS_Stopped) {
1131             goto updateState_exit_with_error;
1132         }
1133         // do init here
1134         result = doStop();
1135         if (result) return true;
1136         else goto updateState_exit_change_failed;
1137     }
1138
1139     // after initialization, only WaitingForRunningStream is allowed
1140     if (m_state == ePS_Stopped) {
1141         if(next_state != ePS_WaitingForStream) {
1142             goto updateState_exit_with_error;
1143         }
1144         result = doWaitForRunningStream();
1145         if (result) return true;
1146         else goto updateState_exit_change_failed;
1147     }
1148
1149     // after WaitingForStream, only ePS_DryRunning is allowed
1150     // this means that the stream started running
1151     if (m_state == ePS_WaitingForStream) {
1152         if(next_state != ePS_DryRunning) {
1153             goto updateState_exit_with_error;
1154         }
1155         result = doDryRunning();
1156         if (result) return true;
1157         else goto updateState_exit_change_failed;
1158     }
1159
1160     // from ePS_DryRunning we can go to:
1161     //   - ePS_Stopped if something went wrong during DryRunning
1162     //   - ePS_WaitingForStreamEnable if there is a requested to enable
1163     if (m_state == ePS_DryRunning) {
1164         if((next_state != ePS_Stopped) &&
1165            (next_state != ePS_WaitingForStreamEnable)) {
1166             goto updateState_exit_with_error;
1167         }
1168         if (next_state == ePS_Stopped) {
1169             result = doStop();
1170         } else {
1171             result = doWaitForStreamEnable();
1172         }
1173         if (result) return true;
1174         else goto updateState_exit_change_failed;
1175     }
1176
1177     // from ePS_WaitingForStreamEnable we can go to:
1178     //   - ePS_DryRunning if something went wrong while waiting
1179     //   - ePS_Running if the stream enabled correctly
1180     if (m_state == ePS_WaitingForStreamEnable) {
1181         if((next_state != ePS_DryRunning) &&
1182            (next_state != ePS_Running)) {
1183             goto updateState_exit_with_error;
1184         }
1185         if (next_state == ePS_Stopped) {
1186             result = doDryRunning();
1187         } else {
1188             result = doRunning();
1189         }
1190         if (result) return true;
1191         else goto updateState_exit_change_failed;
1192     }
1193
1194     // from ePS_Running we can only start waiting for a disabled stream
1195     if (m_state == ePS_Running) {
1196         if(next_state != ePS_WaitingForStreamDisable) {
1197             goto updateState_exit_with_error;
1198         }
1199         result = doWaitForStreamDisable();
1200         if (result) return true;
1201         else goto updateState_exit_change_failed;
1202     }
1203
1204     // from ePS_WaitingForStreamDisable we can go to DryRunning
1205     if (m_state == ePS_WaitingForStreamDisable) {
1206         if(next_state != ePS_DryRunning) {
1207             goto updateState_exit_with_error;
1208         }
1209         result = doDryRunning();
1210         if (result) return true;
1211         else goto updateState_exit_change_failed;
1212     }
1213
1214     // if we arrive here there is an error
1215 updateState_exit_with_error:
1216     debugError("Invalid state transition: %s => %s\n",
1217         ePSToString(m_state), ePSToString(next_state));
1218     return false;
1219 updateState_exit_change_failed:
1220     debugError("State transition failed: %s => %s\n",
1221         ePSToString(m_state), ePSToString(next_state));
1222     return false;
1223 }
1224
1225 /***********************************************
1226  * Helper routines                             *
1227  ***********************************************/
1228 bool
1229 StreamProcessor::transferSilence(unsigned int nframes)
1230 {
1231     bool retval;
1232     signed int fc;
1233     ffado_timestamp_t ts_tail_tmp;
1234
1235     // prepare a buffer of silence
1236     char *dummybuffer = (char *)calloc(sizeof(quadlet_t), nframes * getEventsPerFrame());
1237     transmitSilenceBlock(dummybuffer, nframes, 0);
1238
1239     m_data_buffer->getBufferTailTimestamp(&ts_tail_tmp, &fc);
1240     if (fc != 0) {
1241         debugWarning("Prefilling a buffer that already contains %d frames\n", fc);
1242     }
1243
1244     // add the silence data to the ringbuffer
1245     if(m_data_buffer->preloadFrames(nframes, dummybuffer, true)) {
1246         retval = true;
1247     } else {
1248         debugWarning("Could not write to event buffer\n");
1249         retval = false;
1250     }
1251     free(dummybuffer);
1252     return retval;
1253 }
1254
1255 /**
1256  * @brief convert a eProcessorState to a string
1257  * @param s the state
1258  * @return a char * describing the state
1259  */
1260 const char *
1261 StreamProcessor::ePSToString(enum eProcessorState s) {
1262     switch (s) {
1263         case ePS_Invalid: return "ePS_Invalid";
1264         case ePS_Created: return "ePS_Created";
1265         case ePS_Stopped: return "ePS_Stopped";
1266         case ePS_WaitingForStream: return "ePS_WaitingForStream";
1267         case ePS_DryRunning: return "ePS_DryRunning";
1268         case ePS_WaitingForStreamEnable: return "ePS_WaitingForStreamEnable";
1269         case ePS_Running: return "ePS_Running";
1270         case ePS_WaitingForStreamDisable: return "ePS_WaitingForStreamDisable";
1271         default: return "error: unknown state";
1272     }
1273 }
1274
1275 /**
1276  * @brief convert a eProcessorType to a string
1277  * @param t the type
1278  * @return a char * describing the state
1279  */
1280 const char *
1281 StreamProcessor::ePTToString(enum eProcessorType t) {
1282     switch (t) {
1283         case ePT_Receive: return "Receive";
1284         case ePT_Transmit: return "Transmit";
1285         default: return "error: unknown type";
1286     }
1287 }
1288
1289 /***********************************************
1290  * Debug                                       *
1291  ***********************************************/
1292 void
1293 StreamProcessor::dumpInfo()
1294 {
1295     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor information\n");
1296     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Iso stream info:\n");
1297
1298     IsoStream::dumpInfo();
1299     debugOutputShort( DEBUG_LEVEL_NORMAL, "  StreamProcessor info:\n");
1300     if (m_handler) {
1301         uint64_t now = m_handler->getCycleTimerTicks();
1302         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011llu (%03us %04uc %04ut)\n",
1303                           now,
1304                           (unsigned int)TICKS_TO_SECS(now),
1305                           (unsigned int)TICKS_TO_CYCLES(now),
1306                           (unsigned int)TICKS_TO_OFFSET(now));
1307     }
1308     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xruns                 : %d\n", m_xruns);
1309     debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s\n", ePSToString(m_state));
1310     debugOutputShort( DEBUG_LEVEL_NORMAL, "   Next state           : %s\n", ePSToString(m_next_state));
1311     debugOutputShort( DEBUG_LEVEL_NORMAL, "    transition at       : %u\n", m_cycle_to_switch_state);
1312     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer                : %p\n", m_data_buffer);
1313     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Nominal framerate     : %u\n", m_manager->getNominalRate());
1314     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate      : Sync: %f, Buffer %f\n",
1315         24576000.0/m_manager->getSyncSource().m_data_buffer->getRate(),
1316         24576000.0/m_data_buffer->getRate()
1317         );
1318
1319     m_data_buffer->dumpInfo();
1320 }
1321
1322 void
1323 StreamProcessor::setVerboseLevel(int l) {
1324     setDebugLevel(l);
1325     IsoStream::setVerboseLevel(l);
1326     PortManager::setVerboseLevel(l);
1327     m_data_buffer->setVerboseLevel(l);
1328 }
1329
1330 } // end of namespace
Note: See TracBrowser for help on using the browser.