root/trunk/libffado/src/libstreaming/generic/StreamProcessor.cpp

Revision 807, 69.1 kB (checked in by ppalmers, 14 years ago)

more reliability things

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 program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25
26 #include "StreamProcessor.h"
27 #include "../StreamProcessorManager.h"
28
29 #include "devicemanager.h"
30
31 #include "libieee1394/ieee1394service.h"
32 #include "libieee1394/IsoHandlerManager.h"
33 #include "libieee1394/cycletimer.h"
34
35 #include "libutil/Time.h"
36
37 #include "libutil/Atomic.h"
38
39 #include <assert.h>
40 #include <math.h>
41
42 /*
43 #define POST_SEMAPHORE { \
44     int tmp; \
45     sem_getvalue(&m_signal_semaphore, &tmp); \
46     debugWarning("posting semaphore from value %d\n", tmp); \
47     sem_post(&m_signal_semaphore); \
48 }
49 */
50
51 #define POST_SEMAPHORE { \
52     sem_post(&m_signal_semaphore); \
53 }
54
55 namespace Streaming {
56
57 IMPL_DEBUG_MODULE( StreamProcessor, StreamProcessor, DEBUG_LEVEL_VERBOSE );
58
59 StreamProcessor::StreamProcessor(FFADODevice &parent, enum eProcessorType type)
60     : m_processor_type ( type )
61     , m_state( ePS_Created )
62     , m_next_state( ePS_Invalid )
63     , m_cycle_to_switch_state( 0 )
64     , m_Parent( parent )
65     , m_1394service( parent.get1394Service() ) // local cache
66     , m_IsoHandlerManager( parent.get1394Service().getIsoHandlerManager() ) // local cache
67     , m_StreamProcessorManager( m_Parent.getDeviceManager().getStreamProcessorManager() ) // local cache
68     , m_channel( -1 )
69     , m_dropped(0)
70     , m_last_timestamp(0)
71     , m_last_timestamp2(0)
72     , m_scratch_buffer( NULL )
73     , m_scratch_buffer_size_bytes( 0 )
74     , m_ticks_per_frame( 0 )
75     , m_last_cycle( -1 )
76     , m_sync_delay( 0 )
77     , m_in_xrun( false )
78     , m_signal_period( 0 )
79     , m_signal_offset( 0 )
80 {
81     // create the timestamped buffer and register ourselves as its client
82     m_data_buffer = new Util::TimestampedBuffer(this);
83 }
84
85 StreamProcessor::~StreamProcessor() {
86     m_StreamProcessorManager.unregisterProcessor(this);
87     if(!m_IsoHandlerManager.unregisterStream(this)) {
88         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not unregister stream processor with the Iso manager\n");
89     }
90
91     if (m_data_buffer) delete m_data_buffer;
92     if (m_scratch_buffer) delete[] m_scratch_buffer;
93     sem_destroy(&m_signal_semaphore);
94 }
95
96 uint64_t StreamProcessor::getTimeNow() {
97     return m_1394service.getCycleTimerTicks();
98 }
99
100 int StreamProcessor::getMaxFrameLatency() {
101     if (getType() == ePT_Receive) {
102         return (int)(m_IsoHandlerManager.getPacketLatencyForStream( this ) * TICKS_PER_CYCLE);
103     } else {
104         return (int)(m_IsoHandlerManager.getPacketLatencyForStream( this ) * TICKS_PER_CYCLE);
105     }
106 }
107
108 unsigned int
109 StreamProcessor::getNominalPacketsNeeded(unsigned int nframes)
110 {
111     unsigned int nominal_frames_per_second
112                     = m_StreamProcessorManager.getNominalRate();
113     uint64_t nominal_ticks_per_frame = TICKS_PER_SECOND / nominal_frames_per_second;
114     uint64_t nominal_ticks = nominal_ticks_per_frame * nframes;
115     uint64_t nominal_packets = nominal_ticks / TICKS_PER_CYCLE;
116     return nominal_packets;
117 }
118
119 unsigned int
120 StreamProcessor::getPacketsPerPeriod()
121 {
122     return getNominalPacketsNeeded(m_StreamProcessorManager.getPeriodSize());
123 }
124
125 unsigned int
126 StreamProcessor::getNbPacketsIsoXmitBuffer()
127 {
128 #if ISOHANDLER_PER_HANDLER_THREAD
129     // if we use one thread per packet, we can put every frame directly into the ISO buffer
130     // the waitForClient in IsoHandler will take care of the fact that the frames are
131     // not present in time
132     unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers()));
133     debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer);
134     return packets_to_prebuffer;
135 #else
136     // the target is to have all of the transmit buffer (at period transfer) as ISO packets
137     // when one period is received, there will be approx (NbBuffers - 1) * period_size frames
138     // in the transmit buffer (the others are still to be put into the xmit frame buffer)
139     unsigned int packets_to_prebuffer = (getPacketsPerPeriod() * (m_StreamProcessorManager.getNbBuffers()-1));
140     debugOutput(DEBUG_LEVEL_VERBOSE, "Nominal prebuffer: %u\n", packets_to_prebuffer);
141    
142     // however we have to take into account the fact that there is some sync delay
143     // we assume that the SPM has indicated
144     // HACK: this counts on the fact that the latency for this stream will be the same as the
145     //       latency for the receive sync source
146     unsigned int est_sync_delay = getPacketsPerPeriod() / MINIMUM_INTERRUPTS_PER_PERIOD;
147     est_sync_delay += STREAMPROCESSORMANAGER_SIGNAL_DELAY_TICKS / TICKS_PER_CYCLE;
148     packets_to_prebuffer -= est_sync_delay;
149     debugOutput(DEBUG_LEVEL_VERBOSE, " correct for sync delay (%d): %u\n",
150                                      est_sync_delay,
151                                      packets_to_prebuffer);
152    
153     // only queue a part of the theoretical max in order not to have too much 'not ready' cycles
154     packets_to_prebuffer = (packets_to_prebuffer * MAX_ISO_XMIT_BUFFER_FILL_PCT * 1000) / 100000;
155     debugOutput(DEBUG_LEVEL_VERBOSE, " reduce to %d%%: %u\n",
156                                      MAX_ISO_XMIT_BUFFER_FILL_PCT, packets_to_prebuffer);
157    
158     return packets_to_prebuffer;
159 #endif
160 }
161
162 /***********************************************
163  * Buffer management and manipulation          *
164  ***********************************************/
165 void StreamProcessor::flush() {
166     m_IsoHandlerManager.flushHandlerForStream(this);
167 }
168
169 int StreamProcessor::getBufferFill() {
170     return m_data_buffer->getBufferFill();
171 }
172
173 int64_t
174 StreamProcessor::getTimeUntilNextPeriodSignalUsecs()
175 {
176     uint64_t time_at_period=getTimeAtPeriod();
177
178     // we delay the period signal with the sync delay
179     // this makes that the period signals lag a little compared to reality
180     // ISO buffering causes the packets to be received at max
181     // m_handler->getWakeupInterval() later than the time they were received.
182     // hence their payload is available this amount of time later. However, the
183     // period boundary is predicted based upon earlier samples, and therefore can
184     // pass before these packets are processed. Adding this extra term makes that
185     // the period boundary is signalled later
186     time_at_period = addTicks(time_at_period, m_StreamProcessorManager.getSyncSource().getSyncDelay());
187
188     uint64_t cycle_timer=m_1394service.getCycleTimerTicks();
189
190     // calculate the time until the next period
191     int32_t until_next=diffTicks(time_at_period,cycle_timer);
192
193     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> TAP=%11llu, CTR=%11llu, UTN=%11ld\n",
194         time_at_period, cycle_timer, until_next
195         );
196
197     // now convert to usecs
198     // don't use the mapping function because it only works
199     // for absolute times, not the relative time we are
200     // using here (which can also be negative).
201     return (int64_t)(((float)until_next) / TICKS_PER_USEC);
202 }
203
204 void
205 StreamProcessor::setSyncDelay(int d) {
206     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "Setting SP %p SyncDelay to %d ticks\n", this, d);
207     m_sync_delay = d;
208 }
209
210 uint64_t
211 StreamProcessor::getTimeAtPeriodUsecs()
212 {
213     return (uint64_t)((float)getTimeAtPeriod() * TICKS_PER_USEC);
214 }
215
216 uint64_t
217 StreamProcessor::getTimeAtPeriod()
218 {
219     if (getType() == ePT_Receive) {
220         ffado_timestamp_t next_period_boundary=m_data_buffer->getTimestampFromHead(m_StreamProcessorManager.getPeriodSize());
221    
222         #ifdef DEBUG
223         ffado_timestamp_t ts;
224         signed int fc;
225         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
226    
227         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
228             next_period_boundary, ts, fc, getTicksPerFrame()
229             );
230         #endif
231         return (uint64_t)next_period_boundary;
232     } else {
233         ffado_timestamp_t next_period_boundary=m_data_buffer->getTimestampFromTail((m_StreamProcessorManager.getNbBuffers()-1) * m_StreamProcessorManager.getPeriodSize());
234    
235         #ifdef DEBUG
236         ffado_timestamp_t ts;
237         signed int fc;
238         m_data_buffer->getBufferTailTimestamp(&ts,&fc);
239    
240         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "=> NPD="TIMESTAMP_FORMAT_SPEC", LTS="TIMESTAMP_FORMAT_SPEC", FC=%5u, TPF=%f\n",
241             next_period_boundary, ts, fc, getTicksPerFrame()
242             );
243         #endif
244         return (uint64_t)next_period_boundary;
245     }
246 }
247
248 float
249 StreamProcessor::getTicksPerFrame()
250 {
251     assert(m_data_buffer != NULL);
252     return m_data_buffer->getRate();
253 }
254
255 bool
256 StreamProcessor::canClientTransferFrames(unsigned int nbframes)
257 {
258     bool can_transfer;
259     unsigned int fc = m_data_buffer->getFrameCounter();
260     if (getType() == ePT_Receive) {
261         can_transfer = (fc >= nbframes);
262     } else {
263         // there has to be enough space to put the frames in
264         can_transfer = m_data_buffer->getBufferSize() - fc > nbframes;
265         // or the buffer is transparent
266         can_transfer |= m_data_buffer->isTransparent();
267     }
268    
269     #ifdef DEBUG
270     if (!can_transfer) {
271         debugWarning("(%p, %s) cannot transfer since fc == %u, nbframes == %u\n",
272             this, ePTToString(getType()), fc, nbframes);
273     }
274     #endif
275    
276     return can_transfer;
277 }
278
279 /***********************************************
280  * I/O API                                     *
281  ***********************************************/
282
283 // Packet transfer API
284 enum raw1394_iso_disposition
285 StreamProcessor::putPacket(unsigned char *data, unsigned int length,
286                            unsigned char channel, unsigned char tag, unsigned char sy,
287                            unsigned int cycle, unsigned int dropped) {
288     if(m_last_cycle == -1) {
289         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %u)\n", getTypeString(), this, cycle);
290     }
291
292     int dropped_cycles = 0;
293     if (m_last_cycle != (int)cycle && m_last_cycle != -1) {
294         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
295         if (dropped_cycles < 0) {
296             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
297                          this, dropped_cycles, cycle, m_last_cycle, dropped);
298         }
299         if (dropped_cycles > 0) {
300             debugWarning("(%p) dropped %d packets on cycle %u, 'dropped'=%u, cycle=%d, m_last_cycle=%d\n",
301                 this, dropped_cycles, cycle, dropped, cycle, m_last_cycle);
302             m_dropped += dropped_cycles;
303             m_in_xrun = true;
304             m_last_cycle = cycle;
305             POST_SEMAPHORE;
306             return RAW1394_ISO_DEFER;
307             //flushDebugOutput();
308             //assert(0);
309         }
310     }
311     m_last_cycle = cycle;
312
313     // bypass based upon state
314     if (m_state == ePS_Invalid) {
315         debugError("Should not have state %s\n", ePSToString(m_state) );
316         POST_SEMAPHORE;
317         return RAW1394_ISO_ERROR;
318     }
319     if (m_state == ePS_Created) {
320         return RAW1394_ISO_DEFER;
321     }
322
323     // store the previous timestamp
324     m_last_timestamp2 = m_last_timestamp;
325
326     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
327     //       it happens on the first 'good' cycle for the wait condition
328     //       or on the first received cycle that is received afterwards (might be a problem)
329
330     // check whether we are waiting for a stream to be disabled
331     if(m_state == ePS_WaitingForStreamDisable) {
332         // we then check whether we have to switch on this cycle
333         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
334             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
335             m_next_state = ePS_DryRunning;
336             if (!updateState()) { // we are allowed to change the state directly
337                 debugError("Could not update state!\n");
338                 POST_SEMAPHORE;
339                 return RAW1394_ISO_ERROR;
340             }
341         } else {
342             // not time to disable yet
343         }
344         // the received data can be discarded while waiting for the stream
345         // to be disabled
346         return RAW1394_ISO_OK;
347     }
348
349     // check whether we are waiting for a stream to be enabled
350     else if(m_state == ePS_WaitingForStreamEnable) {
351         // we then check whether we have to switch on this cycle
352         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
353             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
354             m_next_state = ePS_Running;
355             if (!updateState()) { // we are allowed to change the state directly
356                 debugError("Could not update state!\n");
357                 POST_SEMAPHORE;
358                 return RAW1394_ISO_ERROR;
359             }
360         } else {
361             // not time to enable yet
362         }
363         // we are dryRunning hence data should be processed in any case
364     }
365
366     // check the packet header
367     enum eChildReturnValue result = processPacketHeader(data, length, channel, tag, sy, cycle, dropped_cycles);
368     if (result == eCRV_OK) {
369         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "RECV: CY=%04u TS=%011llu\n",
370                 cycle, m_last_timestamp);
371         // update some accounting
372         m_last_good_cycle = cycle;
373         m_last_dropped = dropped_cycles;
374
375         // check whether we are waiting for a stream to startup
376         // this requires that the packet is good
377         if(m_state == ePS_WaitingForStream) {
378             // since we have a packet with an OK header,
379             // we can indicate that the stream started up
380
381             // we then check whether we have to switch on this cycle
382             if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
383                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning due to good packet\n");
384                 // hence go to the dryRunning state
385                 m_next_state = ePS_DryRunning;
386                 if (!updateState()) { // we are allowed to change the state directly
387                     debugError("Could not update state!\n");
388                     POST_SEMAPHORE;
389                     return RAW1394_ISO_ERROR;
390                 }
391             } else {
392                 // not time (yet) to switch state
393             }
394             // in both cases we don't want to process the data
395             return RAW1394_ISO_OK;
396         }
397
398         // check whether a state change has been requested
399         // note that only the wait state changes are synchronized with the cycles
400         else if(m_state != m_next_state) {
401             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
402                                              ePSToString(m_state), ePSToString(m_next_state));
403             // execute the requested change
404             if (!updateState()) { // we are allowed to change the state directly
405                 debugError("Could not update state!\n");
406                 POST_SEMAPHORE;
407                 return RAW1394_ISO_ERROR;
408             }
409         }
410
411         // handle dropped cycles
412         if(dropped_cycles) {
413             // they represent a discontinuity in the timestamps, and hence are
414             // to be dealt with
415             debugWarning("(%p) Correcting timestamp for dropped cycles, discarding packet...\n", this);
416             m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
417             if (m_state == ePS_Running) {
418                 // this is an xrun situation
419                 m_in_xrun = true;
420                 debugWarning("Should update state to WaitingForStreamDisable due to dropped packet xrun\n");
421                 m_cycle_to_switch_state = cycle + 1; // switch in the next cycle
422                 m_next_state = ePS_WaitingForStreamDisable;
423                 // execute the requested change
424                 if (!updateState()) { // we are allowed to change the state directly
425                     debugError("Could not update state!\n");
426                     POST_SEMAPHORE;
427                     return RAW1394_ISO_ERROR;
428                 }
429                 POST_SEMAPHORE;
430                 return RAW1394_ISO_DEFER;
431             }
432         }
433
434         // for all states that reach this we are allowed to
435         // do protocol specific data reception
436         enum eChildReturnValue result2 = processPacketData(data, length, channel, tag, sy, cycle, dropped_cycles);
437
438         // if an xrun occured, switch to the dryRunning state and
439         // allow for the xrun to be picked up
440         if (result2 == eCRV_XRun) {
441             debugWarning("processPacketData xrun\n");
442             m_in_xrun = true;
443             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
444             m_cycle_to_switch_state = cycle+1; // switch in the next cycle
445             m_next_state = ePS_WaitingForStreamDisable;
446             // execute the requested change
447             if (!updateState()) { // we are allowed to change the state directly
448                 debugError("Could not update state!\n");
449                 POST_SEMAPHORE;
450                 return RAW1394_ISO_ERROR;
451             }
452             POST_SEMAPHORE;
453             return RAW1394_ISO_DEFER;
454         } else if(result2 == eCRV_OK) {
455             // no problem here
456             // if we have enough samples, we can post the semaphore and
457             // defer further processing until later. this will allow us to
458             // run the client and process the frames such that we can put them
459             // into the xmit buffers ASAP
460             if (m_state == ePS_Running) {
461                 unsigned int bufferfill = m_data_buffer->getBufferFill();
462                 if(bufferfill >= m_signal_period + m_signal_offset) {
463                     // this to avoid multiple signals for the same period
464                     int semval;
465                     sem_getvalue(&m_signal_semaphore, &semval);
466                     unsigned int signal_period = m_signal_period * (semval + 1) + m_signal_offset;
467                     if(bufferfill >= signal_period) {
468                         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) buffer fill (%d) > signal period (%d), sem_val=%d\n",
469                                     this, m_data_buffer->getBufferFill(), signal_period, semval);
470                         POST_SEMAPHORE;
471                     }
472                     // the process thread should have higher prio such that we are blocked until
473                     // the samples are processed.
474                 }
475             }
476             return RAW1394_ISO_OK;
477         } else {
478             debugError("Invalid response\n");
479             POST_SEMAPHORE;
480             return RAW1394_ISO_ERROR;
481         }
482     } else if(result == eCRV_Invalid) {
483         // apparently we don't have to do anything when the packets are not valid
484         return RAW1394_ISO_OK;
485     } else {
486         debugError("Invalid response\n");
487         POST_SEMAPHORE;
488         return RAW1394_ISO_ERROR;
489     }
490     debugError("reached the unreachable\n");
491     POST_SEMAPHORE;
492     return RAW1394_ISO_ERROR;
493 }
494
495 enum raw1394_iso_disposition
496 StreamProcessor::getPacket(unsigned char *data, unsigned int *length,
497                            unsigned char *tag, unsigned char *sy,
498                            int cycle, unsigned int dropped, unsigned int max_length) {
499     if (cycle<0) {
500         *tag = 0;
501         *sy = 0;
502         *length = 0;
503         return RAW1394_ISO_OK;
504     }
505
506     unsigned int ctr;
507     int now_cycles;
508     int cycle_diff;
509
510     if(m_last_cycle == -1) {
511         debugOutput(DEBUG_LEVEL_VERBOSE, "Handler for %s SP %p is alive (cycle = %d)\n", getTypeString(), this, cycle);
512     }
513
514     int dropped_cycles = 0;
515     if (m_last_cycle != cycle && m_last_cycle != -1) {
516         dropped_cycles = diffCycles(cycle, m_last_cycle) - 1;
517         if (dropped_cycles < 0) {
518             debugWarning("(%p) dropped < 1 (%d), cycle: %d, last_cycle: %d, dropped: %d\n",
519                          this, dropped_cycles, cycle, m_last_cycle, dropped);
520         }
521         if (dropped_cycles > 0) {
522             debugWarning("(%p) dropped %d packets on cycle %u (last_cycle=%u, dropped=%d)\n", this, dropped_cycles, cycle, m_last_cycle, dropped);
523             m_dropped += dropped_cycles;
524             // HACK: this should not be necessary, since the header generation functions should trigger the xrun.
525             //       but apparently there are some issues with the 1394 stack
526             m_in_xrun = true;
527             if(m_state == ePS_Running) {
528                 debugShowBackLogLines(200);
529                 debugWarning("dropped packets xrun\n");
530                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to dropped packets xrun\n");
531                 m_next_state = ePS_WaitingForStreamDisable;
532                 // execute the requested change
533                 if (!updateState()) { // we are allowed to change the state directly
534                     debugError("Could not update state!\n");
535                     return RAW1394_ISO_ERROR;
536                 }
537                 goto send_empty_packet;
538             }
539         }
540     }
541     if (cycle >= 0) {
542         m_last_cycle = cycle;
543     }
544
545     // bypass based upon state
546     if (m_state == ePS_Invalid) {
547         debugError("Should not have state %s\n", ePSToString(m_state) );
548         return RAW1394_ISO_ERROR;
549     }
550     if (m_state == ePS_Created) {
551         *tag = 0;
552         *sy = 0;
553         *length = 0;
554         return RAW1394_ISO_DEFER;
555     }
556
557     // normal processing
558     // note that we can't use getCycleTimer directly here,
559     // because packets are queued in advance. This means that
560     // we the packet we are constructing will be sent out
561     // on 'cycle', not 'now'.
562     ctr = m_1394service.getCycleTimer();
563     now_cycles = (int)CYCLE_TIMER_GET_CYCLES(ctr);
564
565     // the difference between the cycle this
566     // packet is intended for and 'now'
567     cycle_diff = diffCycles(cycle, now_cycles);
568
569     if(cycle_diff < 0 && (m_state == ePS_Running || m_state == ePS_DryRunning)) {
570         debugWarning("Requesting packet for cycle %04d which is in the past (now=%04dcy)\n",
571             cycle, now_cycles);
572         if(m_state == ePS_Running) {
573             debugShowBackLogLines(200);
574 //             flushDebugOutput();
575 //             assert(0);
576             debugWarning("generatePacketData xrun\n");
577             m_in_xrun = true;
578             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
579             m_next_state = ePS_WaitingForStreamDisable;
580             // execute the requested change
581             if (!updateState()) { // we are allowed to change the state directly
582                 debugError("Could not update state!\n");
583                 return RAW1394_ISO_ERROR;
584             }
585             goto send_empty_packet;
586         }
587     }
588
589     // store the previous timestamp
590     m_last_timestamp2 = m_last_timestamp;
591
592     // NOTE: synchronized switching is restricted to a 0.5 sec span (4000 cycles)
593     //       it happens on the first 'good' cycle for the wait condition
594     //       or on the first received cycle that is received afterwards (might be a problem)
595
596     // check whether we are waiting for a stream to be disabled
597     if(m_state == ePS_WaitingForStreamDisable) {
598         // we then check whether we have to switch on this cycle
599         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
600             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to DryRunning\n");
601             m_next_state = ePS_DryRunning;
602             if (!updateState()) { // we are allowed to change the state directly
603                 debugError("Could not update state!\n");
604                 return RAW1394_ISO_ERROR;
605             }
606         } else {
607             // not time to disable yet
608         }
609     }
610     // check whether we are waiting for a stream to be enabled
611     else if(m_state == ePS_WaitingForStreamEnable) {
612         // we then check whether we have to switch on this cycle
613         if (diffCycles(cycle, m_cycle_to_switch_state) >= 0) {
614             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to Running\n");
615             m_next_state = ePS_Running;
616             if (!updateState()) { // we are allowed to change the state directly
617                 debugError("Could not update state!\n");
618                 return RAW1394_ISO_ERROR;
619             }
620         } else {
621             // not time to enable yet
622         }
623         // we are dryRunning hence data should be processed in any case
624     }
625     // check whether we are waiting for a stream to startup
626     else if(m_state == ePS_WaitingForStream) {
627         // as long as the cycle parameter is not in sync with
628         // the current time, the stream is considered not
629         // to be 'running'
630         // we then check whether we have to switch on this cycle
631         if ((cycle_diff >= 0) && (diffCycles(cycle, m_cycle_to_switch_state) >= 0)) {
632             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStream to DryRunning\n");
633             // hence go to the dryRunning state
634             m_next_state = ePS_DryRunning;
635             if (!updateState()) { // we are allowed to change the state directly
636                 debugError("Could not update state!\n");
637                 return RAW1394_ISO_ERROR;
638             }
639         } else {
640             // not time (yet) to switch state
641         }
642     }
643     else if(m_state == ePS_Running) {
644         // check the packet header
645         enum eChildReturnValue result = generatePacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
646         if (result == eCRV_Packet || result == eCRV_Defer) {
647             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT: CY=%04u TS=%011llu\n",
648                     cycle, m_last_timestamp);
649             // update some accounting
650             m_last_good_cycle = cycle;
651             m_last_dropped = dropped_cycles;
652
653             // check whether a state change has been requested
654             // note that only the wait state changes are synchronized with the cycles
655             if(m_state != m_next_state) {
656                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
657                                                 ePSToString(m_state), ePSToString(m_next_state));
658                 // execute the requested change
659                 if (!updateState()) { // we are allowed to change the state directly
660                     debugError("Could not update state!\n");
661                     return RAW1394_ISO_ERROR;
662                 }
663             }
664
665             enum eChildReturnValue result2 = generatePacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
666             // if an xrun occured, switch to the dryRunning state and
667             // allow for the xrun to be picked up
668             if (result2 == eCRV_XRun) {
669                 debugWarning("generatePacketData xrun\n");
670                 m_in_xrun = true;
671                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to data xrun\n");
672                 m_cycle_to_switch_state = cycle+1; // switch in the next cycle
673                 m_next_state = ePS_WaitingForStreamDisable;
674                 // execute the requested change
675                 if (!updateState()) { // we are allowed to change the state directly
676                     debugError("Could not update state!\n");
677                     return RAW1394_ISO_ERROR;
678                 }
679                 goto send_empty_packet;
680             }
681             // skip queueing packets if we detect that there are not enough frames
682             // available
683             if(result2 == eCRV_Defer || result == eCRV_Defer)
684                 return RAW1394_ISO_DEFER;
685             else
686                 return RAW1394_ISO_OK;
687         } else if (result == eCRV_XRun) { // pick up the possible xruns
688             debugWarning("generatePacketHeader xrun\n");
689             m_in_xrun = true;
690             debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state to WaitingForStreamDisable due to header xrun\n");
691             m_next_state = ePS_WaitingForStreamDisable;
692             // execute the requested change
693             if (!updateState()) { // we are allowed to change the state directly
694                 debugError("Could not update state!\n");
695                 return RAW1394_ISO_ERROR;
696             }
697         } else if (result == eCRV_EmptyPacket) {
698             if(m_state != m_next_state) {
699                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
700                                                 ePSToString(m_state), ePSToString(m_next_state));
701                 // execute the requested change
702                 if (!updateState()) { // we are allowed to change the state directly
703                     debugError("Could not update state!\n");
704                     return RAW1394_ISO_ERROR;
705                 }
706             }
707             goto send_empty_packet;
708         } else if (result == eCRV_Again) {
709             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "have to retry cycle %d\n", cycle);
710             if(m_state != m_next_state) {
711                 debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
712                                                 ePSToString(m_state), ePSToString(m_next_state));
713                 // execute the requested change
714                 if (!updateState()) { // we are allowed to change the state directly
715                     debugError("Could not update state!\n");
716                     return RAW1394_ISO_ERROR;
717                 }
718             }
719             usleep(125); // only when using thread-per-handler
720             return RAW1394_ISO_AGAIN;
721 //             generateSilentPacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
722 //             generateSilentPacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
723 //             return RAW1394_ISO_DEFER;
724         } else {
725             debugError("Invalid return value: %d\n", result);
726             return RAW1394_ISO_ERROR;
727         }
728     }
729     // we are not running, so send an empty packet
730     // we should generate a valid packet any time
731 send_empty_packet:
732     // note that only the wait state changes are synchronized with the cycles
733     if(m_state != m_next_state) {
734         debugOutput(DEBUG_LEVEL_VERBOSE, "Should update state from %s to %s\n",
735                                         ePSToString(m_state), ePSToString(m_next_state));
736         // execute the requested change
737         if (!updateState()) { // we are allowed to change the state directly
738             debugError("Could not update state!\n");
739             return RAW1394_ISO_ERROR;
740         }
741     }
742
743     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "XMIT EMPTY: CY=%04u\n", cycle);
744     generateSilentPacketHeader(data, length, tag, sy, cycle, dropped_cycles, max_length);
745     generateSilentPacketData(data, length, tag, sy, cycle, dropped_cycles, max_length);
746     return RAW1394_ISO_OK;
747 }
748
749
750 // Frame Transfer API
751 /**
752  * Transfer a block of frames from the event buffer to the port buffers
753  * @param nbframes number of frames to transfer
754  * @param ts the timestamp that the LAST frame in the block should have
755  * @return
756  */
757 bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
758     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.getFrames(%d, %11llu)", nbframes, ts);
759     assert( getType() == ePT_Receive );
760     if(isDryRunning()) return getFramesDry(nbframes, ts);
761     else return getFramesWet(nbframes, ts);
762 }
763
764 bool StreamProcessor::getFramesWet(unsigned int nbframes, int64_t ts) {
765 // FIXME: this should be done somewhere else
766 #ifdef DEBUG
767     uint64_t ts_expected;
768     signed int fc;
769     int32_t lag_ticks;
770     float lag_frames;
771
772     // in order to sync up multiple received streams, we should
773     // use the ts parameter. It specifies the time of the block's
774     // last sample.
775     float srate = m_StreamProcessorManager.getSyncSource().getTicksPerFrame();
776     assert(srate != 0.0);
777     int64_t this_block_length_in_ticks = (int64_t)(((float)nbframes) * srate);
778
779     ffado_timestamp_t ts_head_tmp;
780     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);
781     ts_expected = addTicks((uint64_t)ts_head_tmp, this_block_length_in_ticks);
782
783     lag_ticks = diffTicks(ts, ts_expected);
784     lag_frames = (((float)lag_ticks) / srate);
785     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
786                  this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
787     if (lag_frames >= 1.0) {
788         // the stream lags
789         debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
790                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
791     } else if (lag_frames <= -1.0) {
792         // the stream leads
793         debugWarning( "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
794                       this, lag_ticks, lag_frames, srate, ts, ts_expected, fc);
795     }
796 #endif
797     // ask the buffer to process nbframes of frames
798     // using it's registered client's processReadBlock(),
799     // which should be ours
800     m_data_buffer->blockProcessReadFrames(nbframes);
801     return true;
802 }
803
804 bool StreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts)
805 {
806     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n",
807                  this, nbframes, ts);
808     // dry run on this side means that we put silence in all enabled ports
809     // since there is do data put into the ringbuffer in the dry-running state
810     return provideSilenceBlock(nbframes, 0);
811 }
812
813 bool
814 StreamProcessor::dropFrames(unsigned int nbframes, int64_t ts)
815 {
816     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "StreamProcessor::dropFrames(%d, %lld)\n", nbframes, ts);
817     return m_data_buffer->dropFrames(nbframes);
818 }
819
820 bool StreamProcessor::putFrames(unsigned int nbframes, int64_t ts)
821 {
822     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.putFrames(%d, %11llu)", nbframes, ts);
823     assert( getType() == ePT_Transmit );
824
825     if(isDryRunning()) return putFramesDry(nbframes, ts);
826     else return putFramesWet(nbframes, ts);
827 }
828
829 bool
830 StreamProcessor::putFramesWet(unsigned int nbframes, int64_t ts)
831 {
832     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesWet(%d, %llu)\n", nbframes, ts);
833     // transfer the data
834     m_data_buffer->blockProcessWriteFrames(nbframes, ts);
835     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, " New timestamp: %llu\n", ts);
836
837     unsigned int bufferfill = m_data_buffer->getBufferFill();
838     if (bufferfill >= m_signal_period + m_signal_offset) {
839         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) sufficient frames in buffer (%d / %d), posting semaphore\n",
840                                          this, bufferfill, m_signal_period + m_signal_offset);
841         POST_SEMAPHORE;
842     } else {
843         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) insufficient frames in buffer (%d / %d), not posting semaphore\n",
844                                          this, bufferfill, m_signal_period + m_signal_offset);
845     }
846     return true; // FIXME: what about failure?
847 }
848
849 bool
850 StreamProcessor::putFramesDry(unsigned int nbframes, int64_t ts)
851 {
852     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putFramesDry(%d, %llu)\n", nbframes, ts);
853     // do nothing
854     return true;
855 }
856
857 bool
858 StreamProcessor::putSilenceFrames(unsigned int nbframes, int64_t ts)
859 {
860     debugOutput(DEBUG_LEVEL_ULTRA_VERBOSE, "StreamProcessor::putSilenceFrames(%d, %llu)\n", nbframes, ts);
861
862     size_t bytes_per_frame = getEventSize() * getEventsPerFrame();
863     unsigned int scratch_buffer_size_frames = m_scratch_buffer_size_bytes / bytes_per_frame;
864
865     if (nbframes > scratch_buffer_size_frames) {
866         debugError("nframes (%u) > scratch_buffer_size_frames (%u)\n",
867                    nbframes, scratch_buffer_size_frames);
868     }
869
870     assert(m_scratch_buffer);
871     if(!transmitSilenceBlock((char *)m_scratch_buffer, nbframes, 0)) {
872         debugError("Could not prepare silent block\n");
873         return false;
874     }
875     if(!m_data_buffer->writeFrames(nbframes, (char *)m_scratch_buffer, ts)) {
876         debugError("Could not write silent block\n");
877         return false;
878     }
879
880     unsigned int bufferfill = m_data_buffer->getBufferFill();
881     if (bufferfill >= m_signal_period + m_signal_offset) {
882         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) sufficient frames in buffer (%d / %d), posting semaphore\n",
883                                          this, bufferfill, m_signal_period + m_signal_offset);
884         POST_SEMAPHORE;
885     } else {
886         debugOutput(DEBUG_LEVEL_VERBOSE, "(%p) insufficient frames in buffer (%d / %d), not posting semaphore\n",
887                                          this, bufferfill, m_signal_period + m_signal_offset);
888     }
889
890     return true;
891 }
892
893 bool
894 StreamProcessor::waitForSignal()
895 {
896     int result;
897     if(m_state == ePS_Running) {
898         result = sem_wait(&m_signal_semaphore);
899 #ifdef DEBUG
900         int tmp;
901         sem_getvalue(&m_signal_semaphore, &tmp);
902         debugOutput(DEBUG_LEVEL_VERBOSE, " sem_wait returns: %d, sem_value: %d\n", result, tmp);
903 #endif
904         return result == 0;
905     } else {
906         // when we're not running, we can always provide frames
907         debugOutput(DEBUG_LEVEL_VERBOSE, "Not running...\n");
908         return true;
909     }
910 }
911
912 bool
913 StreamProcessor::tryWaitForSignal()
914 {
915     if(m_state == ePS_Running) {
916         return sem_trywait(&m_signal_semaphore) == 0;
917     } else {
918         // when we're not running, we can always provide frames
919         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Not running...\n");
920         return true;
921     }
922 }
923
924 bool
925 StreamProcessor::canProcessPackets()
926 {
927     if(m_state != ePS_Running) return true;
928     bool result;
929     int bufferfill;
930     if(getType() == ePT_Receive) {
931         bufferfill = m_data_buffer->getBufferSpace();
932     } else {
933         bufferfill = m_data_buffer->getBufferFill();
934     }
935     result = bufferfill > getNominalFramesPerPacket();
936     debugOutput(DEBUG_LEVEL_VERBOSE, "(%p, %s) for a bufferfill of %d, we return %d\n",
937                 this, ePTToString(getType()), bufferfill, result);
938     return result;
939 }
940
941 bool
942 StreamProcessor::shiftStream(int nbframes)
943 {
944     if(nbframes == 0) return true;
945     if(nbframes > 0) {
946         return m_data_buffer->dropFrames(nbframes);
947     } else {
948         bool result = true;
949         while(nbframes++) {
950             result &= m_data_buffer->writeDummyFrame();
951         }
952         return result;
953     }
954 }
955
956 /**
957  * @brief write silence events to the stream ringbuffers.
958  */
959 bool StreamProcessor::provideSilenceBlock(unsigned int nevents, unsigned int offset)
960 {
961     bool no_problem=true;
962     for ( PortVectorIterator it = m_PeriodPorts.begin();
963           it != m_PeriodPorts.end();
964           ++it ) {
965         if((*it)->isDisabled()) {continue;};
966
967         //FIXME: make this into a static_cast when not DEBUG?
968         Port *port=dynamic_cast<Port *>(*it);
969
970         switch(port->getPortType()) {
971
972         case Port::E_Audio:
973             if(provideSilenceToPort(static_cast<AudioPort *>(*it), offset, nevents)) {
974                 debugWarning("Could not put silence into to port %s",(*it)->getName().c_str());
975                 no_problem=false;
976             }
977             break;
978         // midi is a packet based port, don't process
979         //    case MotuPortInfo::E_Midi:
980         //        break;
981
982         default: // ignore
983             break;
984         }
985     }
986     return no_problem;
987 }
988
989 int
990 StreamProcessor::provideSilenceToPort(
991                        AudioPort *p, unsigned int offset, unsigned int nevents)
992 {
993     unsigned int j=0;
994     switch(p->getDataType()) {
995         default:
996         case Port::E_Int24:
997             {
998                 quadlet_t *buffer=(quadlet_t *)(p->getBufferAddress());
999                 assert(nevents + offset <= p->getBufferSize());
1000                 buffer+=offset;
1001
1002                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
1003                     *(buffer)=0;
1004                     buffer++;
1005                 }
1006             }
1007             break;
1008         case Port::E_Float:
1009             {
1010                 float *buffer=(float *)(p->getBufferAddress());
1011                 assert(nevents + offset <= p->getBufferSize());
1012                 buffer+=offset;
1013
1014                 for(j = 0; j < nevents; j += 1) { // decode max nsamples
1015                     *buffer = 0.0;
1016                     buffer++;
1017                 }
1018             }
1019             break;
1020     }
1021     return 0;
1022 }
1023
1024 /***********************************************
1025  * State related API                           *
1026  ***********************************************/
1027 bool StreamProcessor::init()
1028 {
1029     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "init...\n");
1030
1031     if (sem_init(&m_signal_semaphore, 0, 0) == -1) {
1032         debugError("Could not init signal semaphore");
1033         return false;
1034     }
1035
1036     if(!m_IsoHandlerManager.registerStream(this)) {
1037         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register stream processor with the Iso manager\n");
1038         return false;
1039     }
1040     if(!m_StreamProcessorManager.registerProcessor(this)) {
1041         debugOutput(DEBUG_LEVEL_VERBOSE,"Could not register stream processor with the SP manager\n");
1042         return false;
1043     }
1044
1045     // initialization can be done without requesting it
1046     // from the packet loop
1047     m_next_state = ePS_Created;
1048     return true;
1049 }
1050
1051 bool StreamProcessor::prepare()
1052 {
1053     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare SP (%p)...\n", this);
1054
1055     // make the scratch buffer one period of frames long
1056     m_scratch_buffer_size_bytes = m_StreamProcessorManager.getPeriodSize() * getEventsPerFrame() * getEventSize();
1057     debugOutput( DEBUG_LEVEL_VERBOSE, " Allocate scratch buffer of %d quadlets\n");
1058     if(m_scratch_buffer) delete[] m_scratch_buffer;
1059     m_scratch_buffer = new byte_t[m_scratch_buffer_size_bytes];
1060     if(m_scratch_buffer == NULL) {
1061         debugFatal("Could not allocate scratch buffer\n");
1062         return false;
1063     }
1064
1065     if (!prepareChild()) {
1066         debugFatal("Could not prepare child\n");
1067         return false;
1068     }
1069
1070     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepared for:\n");
1071     debugOutput( DEBUG_LEVEL_VERBOSE, " Samplerate: %d\n",
1072              m_StreamProcessorManager.getNominalRate());
1073     debugOutput( DEBUG_LEVEL_VERBOSE, " PeriodSize: %d, NbBuffers: %d\n",
1074              m_StreamProcessorManager.getPeriodSize(), m_StreamProcessorManager.getNbBuffers());
1075     debugOutput( DEBUG_LEVEL_VERBOSE, " Port: %d, Channel: %d\n",
1076              m_1394service.getPort(), m_channel);
1077
1078     // initialization can be done without requesting it
1079     // from the packet loop
1080     m_next_state = ePS_Stopped;
1081     return updateState();
1082 }
1083
1084 bool
1085 StreamProcessor::scheduleStateTransition(enum eProcessorState state, uint64_t time_instant)
1086 {
1087     // first set the time, since in the packet loop we first check m_state == m_next_state before
1088     // using the time
1089     m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant);
1090     m_next_state = state;
1091     return true;
1092 }
1093
1094 bool
1095 StreamProcessor::waitForState(enum eProcessorState state, unsigned int timeout_ms)
1096 {
1097     debugOutput(DEBUG_LEVEL_VERBOSE, "Waiting for state %s\n", ePSToString(state));
1098     int cnt = timeout_ms;
1099     while (m_state != state && cnt) {
1100         SleepRelativeUsec(1000);
1101         cnt--;
1102     }
1103     if(cnt==0) {
1104         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout\n");
1105         return false;
1106     }
1107     return true;
1108 }
1109
1110 bool StreamProcessor::scheduleStartDryRunning(int64_t t) {
1111     uint64_t tx;
1112     if (t < 0) {
1113         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1114     } else {
1115         tx = t;
1116     }
1117     uint64_t start_handler_ticks = substractTicks(tx, 100 * TICKS_PER_CYCLE);
1118
1119     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1120     uint64_t now = m_1394service.getCycleTimerTicks();
1121     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1122                           now,
1123                           (unsigned int)TICKS_TO_SECS(now),
1124                           (unsigned int)TICKS_TO_CYCLES(now),
1125                           (unsigned int)TICKS_TO_OFFSET(now));
1126     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
1127                           tx,
1128                           (unsigned int)TICKS_TO_SECS(tx),
1129                           (unsigned int)TICKS_TO_CYCLES(tx),
1130                           (unsigned int)TICKS_TO_OFFSET(tx));
1131     if (m_state == ePS_Stopped) {
1132         if(!m_IsoHandlerManager.startHandlerForStream(
1133                                         this, TICKS_TO_CYCLES(start_handler_ticks))) {
1134             debugError("Could not start handler for SP %p\n", this);
1135             return false;
1136         }
1137         return scheduleStateTransition(ePS_WaitingForStream, tx);
1138     } else if (m_state == ePS_Running) {
1139         return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
1140     } else {
1141         debugError("Cannot switch to ePS_DryRunning from %s\n", ePSToString(m_state));
1142         return false;
1143     }
1144 }
1145
1146 bool StreamProcessor::scheduleStartRunning(int64_t t) {
1147     uint64_t tx;
1148     if (t < 0) {
1149         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1150     } else {
1151         tx = t;
1152     }
1153     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1154     uint64_t now = m_1394service.getCycleTimerTicks();
1155     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1156                           now,
1157                           (unsigned int)TICKS_TO_SECS(now),
1158                           (unsigned int)TICKS_TO_CYCLES(now),
1159                           (unsigned int)TICKS_TO_OFFSET(now));
1160     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%03us %04uc %04ut)\n",
1161                           tx,
1162                           (unsigned int)TICKS_TO_SECS(tx),
1163                           (unsigned int)TICKS_TO_CYCLES(tx),
1164                           (unsigned int)TICKS_TO_OFFSET(tx));
1165     return scheduleStateTransition(ePS_WaitingForStreamEnable, tx);
1166 }
1167
1168 bool StreamProcessor::scheduleStopDryRunning(int64_t t) {
1169     uint64_t tx;
1170     if (t < 0) {
1171         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1172     } else {
1173         tx = t;
1174     }
1175     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1176     uint64_t now = m_1394service.getCycleTimerTicks();
1177     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1178                           now,
1179                           (unsigned int)TICKS_TO_SECS(now),
1180                           (unsigned int)TICKS_TO_CYCLES(now),
1181                           (unsigned int)TICKS_TO_OFFSET(now));
1182     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
1183                           tx,
1184                           (unsigned int)TICKS_TO_SECS(tx),
1185                           (unsigned int)TICKS_TO_CYCLES(tx),
1186                           (unsigned int)TICKS_TO_OFFSET(tx));
1187
1188     return scheduleStateTransition(ePS_Stopped, tx);
1189 }
1190
1191 bool StreamProcessor::scheduleStopRunning(int64_t t) {
1192     uint64_t tx;
1193     if (t < 0) {
1194         tx = addTicks(m_1394service.getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
1195     } else {
1196         tx = t;
1197     }
1198     debugOutput(DEBUG_LEVEL_VERBOSE,"for %s SP (%p)\n", ePTToString(getType()), this);
1199     uint64_t now = m_1394service.getCycleTimerTicks();
1200     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011llu (%03us %04uc %04ut)\n",
1201                           now,
1202                           (unsigned int)TICKS_TO_SECS(now),
1203                           (unsigned int)TICKS_TO_CYCLES(now),
1204                           (unsigned int)TICKS_TO_OFFSET(now));
1205     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%03us %04uc %04ut)\n",
1206                           tx,
1207                           (unsigned int)TICKS_TO_SECS(tx),
1208                           (unsigned int)TICKS_TO_CYCLES(tx),
1209                           (unsigned int)TICKS_TO_OFFSET(tx));
1210     return scheduleStateTransition(ePS_WaitingForStreamDisable, tx);
1211 }
1212
1213 bool StreamProcessor::startDryRunning(int64_t t) {
1214     if(!scheduleStartDryRunning(t)) {
1215         debugError("Could not schedule transition\n");
1216         return false;
1217     }
1218     if(!waitForState(ePS_DryRunning, 2000)) {
1219         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
1220         return false;
1221     }
1222     return true;
1223 }
1224
1225 bool StreamProcessor::startRunning(int64_t t) {
1226     if(!scheduleStartRunning(t)) {
1227         debugError("Could not schedule transition\n");
1228         return false;
1229     }
1230     if(!waitForState(ePS_Running, 2000)) {
1231         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Running));
1232         return false;
1233     }
1234     return true;
1235 }
1236
1237 bool StreamProcessor::stopDryRunning(int64_t t) {
1238     if(!scheduleStopDryRunning(t)) {
1239         debugError("Could not schedule transition\n");
1240         return false;
1241     }
1242     if(!waitForState(ePS_Stopped, 2000)) {
1243         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_Stopped));
1244         return false;
1245     }
1246     return true;
1247 }
1248
1249 bool StreamProcessor::stopRunning(int64_t t) {
1250     if(!scheduleStopRunning(t)) {
1251         debugError("Could not schedule transition\n");
1252         return false;
1253     }
1254     if(!waitForState(ePS_DryRunning, 2000)) {
1255         debugError(" Timeout while waiting for %s\n", ePSToString(ePS_DryRunning));
1256         return false;
1257     }
1258     return true;
1259 }
1260
1261
1262 // internal state API
1263
1264 /**
1265  * @brief Enter the ePS_Stopped state
1266  * @return true if successful, false if not
1267  *
1268  * @pre none
1269  *
1270  * @post the buffer and the isostream are ready for use.
1271  * @post all dynamic structures have been allocated successfully
1272  * @post the buffer is transparent and empty, and all parameters are set
1273  *       to the correct initial/nominal values.
1274  *
1275  */
1276 bool
1277 StreamProcessor::doStop()
1278 {
1279     float ticks_per_frame;
1280     unsigned int ringbuffer_size_frames = (m_StreamProcessorManager.getNbBuffers() + 1) * m_StreamProcessorManager.getPeriodSize();
1281
1282     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1283     bool result = true;
1284
1285     switch(m_state) {
1286         case ePS_Created:
1287             assert(m_data_buffer);
1288             // object just created
1289             result = m_data_buffer->init();
1290
1291             // prepare the framerate estimate
1292             ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_StreamProcessorManager.getNominalRate());
1293             m_ticks_per_frame = ticks_per_frame;
1294             debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n", ticks_per_frame);
1295
1296             // initialize internal buffer
1297             result &= m_data_buffer->setBufferSize(ringbuffer_size_frames);
1298
1299             result &= m_data_buffer->setEventSize( getEventSize() );
1300             result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() );
1301             if(getType() == ePT_Receive) {
1302                 result &= m_data_buffer->setUpdatePeriod( getNominalFramesPerPacket() );
1303             } else {
1304                 result &= m_data_buffer->setUpdatePeriod( m_StreamProcessorManager.getPeriodSize() );
1305             }
1306             result &= m_data_buffer->setNominalRate(ticks_per_frame);
1307             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
1308             result &= m_data_buffer->prepare(); // FIXME: the name
1309
1310             // set the parameters of ports we can:
1311             // we want the audio ports to be period buffered,
1312             // and the midi ports to be packet buffered
1313             for ( PortVectorIterator it = m_Ports.begin();
1314                 it != m_Ports.end();
1315                 ++it )
1316             {
1317                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
1318                 if(!(*it)->setBufferSize(m_StreamProcessorManager.getPeriodSize())) {
1319                     debugFatal("Could not set buffer size to %d\n",m_StreamProcessorManager.getPeriodSize());
1320                     return false;
1321                 }
1322                 switch ((*it)->getPortType()) {
1323                     case Port::E_Audio:
1324                         if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
1325                             debugFatal("Could not set signal type to PeriodSignalling");
1326                             return false;
1327                         }
1328                         // buffertype and datatype are dependant on the API
1329                         debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
1330                         // buffertype and datatype are dependant on the API
1331                         if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
1332                             debugFatal("Could not set buffer type");
1333                             return false;
1334                         }
1335                         if(!(*it)->useExternalBuffer(true)) {
1336                             debugFatal("Could not set external buffer usage");
1337                             return false;
1338                         }
1339                         if(!(*it)->setDataType(Port::E_Float)) {
1340                             debugFatal("Could not set data type");
1341                             return false;
1342                         }
1343                         break;
1344                     case Port::E_Midi:
1345                         if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
1346                             debugFatal("Could not set signal type to PacketSignalling");
1347                             return false;
1348                         }
1349                         // buffertype and datatype are dependant on the API
1350                         debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
1351                         // buffertype and datatype are dependant on the API
1352                         if(!(*it)->setBufferType(Port::E_RingBuffer)) {
1353                             debugFatal("Could not set buffer type");
1354                             return false;
1355                         }
1356                         if(!(*it)->setDataType(Port::E_MidiEvent)) {
1357                             debugFatal("Could not set data type");
1358                             return false;
1359                         }
1360                         break;
1361                     default:
1362                         debugWarning("Unsupported port type specified\n");
1363                         break;
1364                 }
1365             }
1366             // the API specific settings of the ports should already be set,
1367             // as this is called from the processorManager->prepare()
1368             // so we can init the ports
1369             result &= PortManager::initPorts();
1370
1371             break;
1372         case ePS_DryRunning:
1373             if(!m_IsoHandlerManager.stopHandlerForStream(this)) {
1374                 debugError("Could not stop handler for SP %p\n", this);
1375                 return false;
1376             }
1377             break;
1378         default:
1379             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1380             return false;
1381     }
1382
1383     result &= m_data_buffer->clearBuffer(); // FIXME: don't like the reset() name
1384     // make the buffer transparent
1385     m_data_buffer->setTransparent(true);
1386
1387     // reset all ports
1388     result &= PortManager::preparePorts();
1389
1390     m_state = ePS_Stopped;
1391     #ifdef DEBUG
1392     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1393         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1394         dumpInfo();
1395     }
1396     #endif
1397     return result;
1398 }
1399
1400 /**
1401  * @brief Enter the ePS_WaitingForStream state
1402  * @return true if successful, false if not
1403  *
1404  * @pre all dynamic data structures are allocated successfully
1405  *
1406  * @post
1407  *
1408  */
1409 bool
1410 StreamProcessor::doWaitForRunningStream()
1411 {
1412     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1413     switch(m_state) {
1414         case ePS_Stopped:
1415             // we have to start waiting for an incoming stream
1416             // this basically means nothing, the state change will
1417             // be picked up by the packet iterator
1418             break;
1419         default:
1420             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1421             return false;
1422     }
1423     m_state = ePS_WaitingForStream;
1424     #ifdef DEBUG
1425     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1426         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1427         dumpInfo();
1428     }
1429     #endif
1430     return true;
1431 }
1432
1433 /**
1434  * @brief Enter the ePS_DryRunning state
1435  * @return true if successful, false if not
1436  *
1437  * @pre
1438  *
1439  * @post
1440  *
1441  */
1442 bool
1443 StreamProcessor::doDryRunning()
1444 {
1445     bool result = true;
1446     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1447     switch(m_state) {
1448         case ePS_WaitingForStream:
1449             // a running stream has been detected
1450             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started dry-running at cycle %d\n", this, m_last_cycle);
1451             if (getType() == ePT_Receive) {
1452                 // this to ensure that there is no discontinuity when starting to
1453                 // update the DLL based upon the received packets
1454                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
1455             } else {
1456                 // FIXME: PC=master mode will have to do something here I guess...
1457             }
1458             break;
1459         case ePS_WaitingForStreamEnable: // when xrunning at startup
1460             result &= m_data_buffer->clearBuffer();
1461             m_data_buffer->setTransparent(true);
1462             break;
1463         case ePS_WaitingForStreamDisable:
1464             result &= m_data_buffer->clearBuffer();
1465             m_data_buffer->setTransparent(true);
1466             break;
1467         default:
1468             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1469             return false;
1470     }
1471     m_state = ePS_DryRunning;
1472     #ifdef DEBUG
1473     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1474         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1475         dumpInfo();
1476     }
1477     #endif
1478     return result;
1479 }
1480
1481 /**
1482  * @brief Enter the ePS_WaitingForStreamEnable state
1483  * @return true if successful, false if not
1484  *
1485  * @pre
1486  *
1487  * @post
1488  *
1489  */
1490 bool
1491 StreamProcessor::doWaitForStreamEnable()
1492 {
1493     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1494     unsigned int ringbuffer_size_frames;
1495     switch(m_state) {
1496         case ePS_DryRunning:
1497             // we have to start waiting for an incoming stream
1498             // this basically means nothing, the state change will
1499             // be picked up by the packet iterator
1500
1501             sem_init(&m_signal_semaphore, 0, 0);
1502             m_signal_period = m_StreamProcessorManager.getPeriodSize();
1503             m_signal_offset = 0; // FIXME: we have to ensure that everyone is ready
1504
1505             if(!m_data_buffer->clearBuffer()) {
1506                 debugError("Could not reset data buffer\n");
1507                 return false;
1508             }
1509             if (getType() == ePT_Transmit) {
1510                 ringbuffer_size_frames = m_StreamProcessorManager.getNbBuffers() * m_StreamProcessorManager.getPeriodSize();
1511                 debugOutput(DEBUG_LEVEL_VERBOSE, "Prefill transmit SP %p with %u frames\n", this, ringbuffer_size_frames);
1512                 // prefill the buffer
1513                 if(!transferSilence(ringbuffer_size_frames)) {
1514                     debugFatal("Could not prefill transmit stream\n");
1515                     return false;
1516                 }
1517                 if (m_data_buffer->getBufferFill() >= m_signal_period + m_signal_offset) {
1518                     POST_SEMAPHORE;
1519                 }
1520             }
1521
1522             break;
1523         default:
1524             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1525             return false;
1526     }
1527     m_state = ePS_WaitingForStreamEnable;
1528     #ifdef DEBUG
1529     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1530         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1531         dumpInfo();
1532     }
1533     #endif
1534     return true;
1535 }
1536
1537 /**
1538  * @brief Enter the ePS_Running state
1539  * @return true if successful, false if not
1540  *
1541  * @pre
1542  *
1543  * @post
1544  *
1545  */
1546 bool
1547 StreamProcessor::doRunning()
1548 {
1549     bool result = true;
1550     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1551     switch(m_state) {
1552         case ePS_WaitingForStreamEnable:
1553             // a running stream has been detected
1554             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started running at cycle %d\n",
1555                                              this, m_last_cycle);
1556             m_in_xrun = false;
1557             m_data_buffer->setTransparent(false);
1558             break;
1559         default:
1560             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1561             return false;
1562     }
1563     m_state = ePS_Running;
1564     #ifdef DEBUG
1565     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1566         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1567         dumpInfo();
1568     }
1569     #endif
1570     return result;
1571 }
1572
1573 /**
1574  * @brief Enter the ePS_WaitingForStreamDisable state
1575  * @return true if successful, false if not
1576  *
1577  * @pre
1578  *
1579  * @post
1580  *
1581  */
1582 bool
1583 StreamProcessor::doWaitForStreamDisable()
1584 {
1585     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
1586     switch(m_state) {
1587         case ePS_Running:
1588             // the thread will do the transition
1589
1590             // we have to wake the iterator if it's asleep
1591             POST_SEMAPHORE;
1592             break;
1593         default:
1594             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
1595             return false;
1596     }
1597     m_state = ePS_WaitingForStreamDisable;
1598     #ifdef DEBUG
1599     if (getDebugLevel() >= DEBUG_LEVEL_VERBOSE) {
1600         debugOutput(DEBUG_LEVEL_VERBOSE, "State switch complete, dumping SP info...\n");
1601         dumpInfo();
1602     }
1603     #endif
1604     return true;
1605 }
1606
1607 /**
1608  * @brief Updates the state machine and calls the necessary transition functions
1609  * @return true if successful, false if not
1610  */
1611 bool StreamProcessor::updateState() {
1612     bool result = false;
1613     // copy the current state locally since it could change value,
1614     // and that's something we don't want to happen inbetween tests
1615     // if m_next_state changes during this routine, we know for sure
1616     // that the previous state change was at least attempted correctly.
1617     enum eProcessorState next_state = m_next_state;
1618
1619     debugOutput(DEBUG_LEVEL_VERBOSE, "Do state transition: %s => %s\n",
1620         ePSToString(m_state), ePSToString(next_state));
1621
1622     if (m_state == next_state) {
1623         debugWarning("ignoring identity state update from/to %s\n", ePSToString(m_state) );
1624         return true;
1625     }
1626
1627     // after creation, only initialization is allowed
1628     if (m_state == ePS_Created) {
1629         if(next_state != ePS_Stopped) {
1630             goto updateState_exit_with_error;
1631         }
1632         // do init here
1633         result = doStop();
1634         if (result) return true;
1635         else goto updateState_exit_change_failed;
1636     }
1637
1638     // after initialization, only WaitingForRunningStream is allowed
1639     if (m_state == ePS_Stopped) {
1640         if(next_state != ePS_WaitingForStream) {
1641             goto updateState_exit_with_error;
1642         }
1643         result = doWaitForRunningStream();
1644         if (result) return true;
1645         else goto updateState_exit_change_failed;
1646     }
1647
1648     // after WaitingForStream, only ePS_DryRunning is allowed
1649     // this means that the stream started running
1650     if (m_state == ePS_WaitingForStream) {
1651         if(next_state != ePS_DryRunning) {
1652             goto updateState_exit_with_error;
1653         }
1654         result = doDryRunning();
1655         if (result) return true;
1656         else goto updateState_exit_change_failed;
1657     }
1658
1659     // from ePS_DryRunning we can go to:
1660     //   - ePS_Stopped if something went wrong during DryRunning
1661     //   - ePS_WaitingForStreamEnable if there is a requested to enable
1662     if (m_state == ePS_DryRunning) {
1663         if((next_state != ePS_Stopped) &&
1664            (next_state != ePS_WaitingForStreamEnable)) {
1665             goto updateState_exit_with_error;
1666         }
1667         if (next_state == ePS_Stopped) {
1668             result = doStop();
1669         } else {
1670             result = doWaitForStreamEnable();
1671         }
1672         if (result) return true;
1673         else goto updateState_exit_change_failed;
1674     }
1675
1676     // from ePS_WaitingForStreamEnable we can go to:
1677     //   - ePS_DryRunning if something went wrong while waiting
1678     //   - ePS_Running if the stream enabled correctly
1679     if (m_state == ePS_WaitingForStreamEnable) {
1680         if((next_state != ePS_DryRunning) &&
1681            (next_state != ePS_Running)) {
1682             goto updateState_exit_with_error;
1683         }
1684         if (next_state == ePS_Stopped) {
1685             result = doDryRunning();
1686         } else {
1687             result = doRunning();
1688         }
1689         if (result) return true;
1690         else goto updateState_exit_change_failed;
1691     }
1692
1693     // from ePS_Running we can only start waiting for a disabled stream
1694     if (m_state == ePS_Running) {
1695         if(next_state != ePS_WaitingForStreamDisable) {
1696             goto updateState_exit_with_error;
1697         }
1698         result = doWaitForStreamDisable();
1699         if (result) return true;
1700         else goto updateState_exit_change_failed;
1701     }
1702
1703     // from ePS_WaitingForStreamDisable we can go to DryRunning
1704     if (m_state == ePS_WaitingForStreamDisable) {
1705         if(next_state != ePS_DryRunning) {
1706             goto updateState_exit_with_error;
1707         }
1708         result = doDryRunning();
1709         if (result) return true;
1710         else goto updateState_exit_change_failed;
1711     }
1712
1713     // if we arrive here there is an error
1714 updateState_exit_with_error:
1715     debugError("Invalid state transition: %s => %s\n",
1716         ePSToString(m_state), ePSToString(next_state));
1717     return false;
1718 updateState_exit_change_failed:
1719     debugError("State transition failed: %s => %s\n",
1720         ePSToString(m_state), ePSToString(next_state));
1721     return false;
1722 }
1723
1724 /***********************************************
1725  * Helper routines                             *
1726  ***********************************************/
1727 bool
1728 StreamProcessor::transferSilence(unsigned int nframes)
1729 {
1730     bool retval;
1731     signed int fc;
1732     ffado_timestamp_t ts_tail_tmp;
1733
1734     // prepare a buffer of silence
1735     char *dummybuffer = (char *)calloc(getEventSize(), nframes * getEventsPerFrame());
1736     transmitSilenceBlock(dummybuffer, nframes, 0);
1737
1738     m_data_buffer->getBufferTailTimestamp(&ts_tail_tmp, &fc);
1739     if (fc != 0) {
1740         debugWarning("Prefilling a buffer that already contains %d frames\n", fc);
1741     }
1742
1743     // add the silence data to the ringbuffer
1744     if(m_data_buffer->preloadFrames(nframes, dummybuffer, true)) {
1745         retval = true;
1746     } else {
1747         debugWarning("Could not write to event buffer\n");
1748         retval = false;
1749     }
1750     free(dummybuffer);
1751     return retval;
1752 }
1753
1754 /**
1755  * @brief convert a eProcessorState to a string
1756  * @param s the state
1757  * @return a char * describing the state
1758  */
1759 const char *
1760 StreamProcessor::ePSToString(enum eProcessorState s) {
1761     switch (s) {
1762         case ePS_Invalid: return "ePS_Invalid";
1763         case ePS_Created: return "ePS_Created";
1764         case ePS_Stopped: return "ePS_Stopped";
1765         case ePS_WaitingForStream: return "ePS_WaitingForStream";
1766         case ePS_DryRunning: return "ePS_DryRunning";
1767         case ePS_WaitingForStreamEnable: return "ePS_WaitingForStreamEnable";
1768         case ePS_Running: return "ePS_Running";
1769         case ePS_WaitingForStreamDisable: return "ePS_WaitingForStreamDisable";
1770         default: return "error: unknown state";
1771     }
1772 }
1773
1774 /**
1775  * @brief convert a eProcessorType to a string
1776  * @param t the type
1777  * @return a char * describing the state
1778  */
1779 const char *
1780 StreamProcessor::ePTToString(enum eProcessorType t) {
1781     switch (t) {
1782         case ePT_Receive: return "Receive";
1783         case ePT_Transmit: return "Transmit";
1784         default: return "error: unknown type";
1785     }
1786 }
1787
1788 /***********************************************
1789  * Debug                                       *
1790  ***********************************************/
1791 void
1792 StreamProcessor::dumpInfo()
1793 {
1794     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor %p, %s:\n", this, ePTToString(m_processor_type));
1795     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %d, %d\n", m_1394service.getPort(), m_channel);
1796     uint64_t now = m_1394service.getCycleTimerTicks();
1797     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011llu (%03us %04uc %04ut)\n",
1798                         now,
1799                         (unsigned int)TICKS_TO_SECS(now),
1800                         (unsigned int)TICKS_TO_CYCLES(now),
1801                         (unsigned int)TICKS_TO_OFFSET(now));
1802     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xrun?                 : %s\n", (m_in_xrun ? "True":"False"));
1803     if (m_state == m_next_state) {
1804         debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s\n",
1805                                             ePSToString(m_state));
1806     } else {
1807         debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s (Next: %s)\n",
1808                                               ePSToString(m_state), ePSToString(m_next_state));
1809         debugOutputShort( DEBUG_LEVEL_NORMAL, "    transition at       : %u\n", m_cycle_to_switch_state);
1810     }
1811     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Buffer                : %p\n", m_data_buffer);
1812     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Framerate             : Nominal: %u, Sync: %f, Buffer %f\n",
1813                                           m_StreamProcessorManager.getNominalRate(),
1814                                           24576000.0/m_StreamProcessorManager.getSyncSource().m_data_buffer->getRate(),
1815                                           24576000.0/m_data_buffer->getRate());
1816     float d = getSyncDelay();
1817     debugOutputShort(DEBUG_LEVEL_NORMAL, "  Sync delay             : %f ticks (%f frames, %f cy)\n",
1818                                          d, d/getTicksPerFrame(),
1819                                          d/((float)TICKS_PER_CYCLE));
1820     m_data_buffer->dumpInfo();
1821 }
1822
1823 void
1824 StreamProcessor::setVerboseLevel(int l) {
1825     setDebugLevel(l);
1826     PortManager::setVerboseLevel(l);
1827     m_data_buffer->setVerboseLevel(l);
1828 }
1829
1830 } // end of namespace
Note: See TracBrowser for help on using the browser.