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

Revision 719, 35.2 kB (checked in by ppalmers, 15 years ago)

backup commit

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 // Frame Transfer API
330 bool StreamProcessor::getFrames(unsigned int nbframes, int64_t ts) {
331     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "%p.getFrames(%d, %11llu)", nbframes, ts);
332     assert( getType() == ePT_Receive );
333     if(isDryRunning()) return getFramesDry(nbframes, ts);
334     else return getFramesWet(nbframes, ts);
335 }
336
337 bool StreamProcessor::getFramesWet(unsigned int nbframes, int64_t ts) {
338 // FIXME: this should be done somewhere else
339 #ifdef DEBUG
340     uint64_t ts_head;
341     signed int fc;
342     int32_t lag_ticks;
343     float lag_frames;
344
345     // in order to sync up multiple received streams, we should
346     // use the ts parameter. It specifies the time of the block's
347     // first sample.
348    
349     ffado_timestamp_t ts_head_tmp;
350     m_data_buffer->getBufferHeadTimestamp(&ts_head_tmp, &fc);
351     ts_head=(uint64_t)ts_head_tmp;
352     lag_ticks=diffTicks(ts, ts_head);
353     float rate=m_data_buffer->getRate();
354    
355     assert(rate!=0.0);
356    
357     lag_frames=(((float)lag_ticks)/rate);
358    
359     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): drifts %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
360                  this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
361
362     if (lag_frames>=1.0) {
363         // the stream lags
364         debugWarning( "stream (%p): lags  with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
365                       this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
366     } else if (lag_frames<=-1.0) {
367         // the stream leads
368         debugWarning( "stream (%p): leads with %6d ticks = %10.5f frames (rate=%10.5f), %lld, %llu, %d\n",
369                       this, lag_ticks, lag_frames,rate, ts, ts_head, fc);
370     }
371 #endif
372     // ask the buffer to process nbframes of frames
373     // using it's registered client's processReadBlock(),
374     // which should be ours
375     m_data_buffer->blockProcessReadFrames(nbframes);
376     return true;
377 }
378
379 bool StreamProcessor::getFramesDry(unsigned int nbframes, int64_t ts) {
380     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stream (%p): dry run %d frames (@ ts=%lld)\n",
381                  this, nbframes, ts);
382
383     // dry run on this side means that we put silence in all enabled ports
384     // since there is do data put into the ringbuffer in the dry-running state
385     return provideSilenceBlock(nbframes, 0);
386 }
387
388
389 /***********************************************
390  * State related API                           *
391  ***********************************************/
392 bool StreamProcessor::init()
393 {
394     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "init...\n");
395
396     // initialization can be done without requesting it
397     // from the packet loop
398     m_next_state = ePS_Created;
399     return true;
400 }
401
402 bool StreamProcessor::prepare()
403 {
404     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "prepare...\n");
405     if(!m_manager) {
406         debugFatal("Not attached to a manager!\n");
407         return false;
408     }
409
410     if (!prepareChild()) {
411         debugFatal("Could not prepare child\n");
412         return false;
413     }
414
415     // initialization can be done without requesting it
416     // from the packet loop
417     m_next_state = ePS_Stopped;
418     return updateState();
419 }
420
421 bool StreamProcessor::stop()
422 {
423     uint64_t time_to_stop_at = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
424     int cnt;
425     debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "stop...\n");
426     switch (m_state) {
427         case ePS_Stopped: return true;
428         case ePS_DryRunning:
429             return stopDryRunning(-1);
430         case ePS_Running:
431             return stopRunning(-1) &&
432                    stopDryRunning(-1);
433         default:
434             debugError("Bad state: %s\n", ePSToString(m_state));
435             return false;
436     }
437 }
438
439 bool StreamProcessor::scheduleStateTransition(enum eProcessorState state, uint64_t time_instant)
440 {
441     // first set the time, since in the packet loop we first check m_state == m_next_state before
442     // using the time
443     m_cycle_to_switch_state = TICKS_TO_CYCLES(time_instant);
444     m_next_state = state;
445     return true;
446 }
447
448 bool StreamProcessor::scheduleAndWaitForStateTransition(enum eProcessorState state,
449                                                         uint64_t time_instant,
450                                                         enum eProcessorState wait_state)
451 {
452     int cnt=200; // 2 seconds, i.e. 2 cycles
453     if(!scheduleStateTransition(state, time_instant)) {
454         debugError("Could not schedule state transistion to %s\n", ePSToString(state));
455         return false;
456     }
457     while (m_state != wait_state && cnt) {
458         usleep(10000);
459         cnt++;
460     }
461     if(cnt==0) {
462         debugError("Timeout entering Stopped state\n");
463         return false;
464     }
465     debugOutput(DEBUG_LEVEL_VERBOSE, " entered state %s\n", ePSToString(wait_state));
466     return true;
467 }
468
469 bool StreamProcessor::startDryRunning(int64_t t) {
470     uint64_t tx;
471     if (t < 0) {
472         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
473     } else {
474         tx = t;
475     }
476     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::startDryRunning for (%p)\n",this);
477     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011lu\n", m_handler->getCycleTimerTicks());
478     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%u)\n", tx, TICKS_TO_CYCLES(tx));
479     if (m_state == ePS_Stopped) {
480         return scheduleAndWaitForStateTransition(ePS_WaitingForStream, tx, ePS_DryRunning);
481     } else if (m_state == ePS_Running) {
482         return scheduleAndWaitForStateTransition(ePS_WaitingForStreamDisable, tx, ePS_DryRunning);
483     } else {
484         debugError("Cannot switch to ePS_DryRunning from %s\n", ePSToString(m_state));
485         return false;
486     }
487 }
488
489 bool StreamProcessor::startRunning(int64_t t) {
490     uint64_t tx;
491     if (t < 0) {
492         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
493     } else {
494         tx = t;
495     }
496     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::startRunning for (%p)\n",this);
497     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011lu\n", m_handler->getCycleTimerTicks());
498     debugOutput(DEBUG_LEVEL_VERBOSE,"  Start at              : %011llu (%u)\n", tx, TICKS_TO_CYCLES(tx));
499     return scheduleAndWaitForStateTransition(ePS_WaitingForStreamEnable, tx, ePS_Running);
500 }
501
502 bool StreamProcessor::stopDryRunning(int64_t t) {
503     uint64_t tx;
504     if (t < 0) {
505         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
506     } else {
507         tx = t;
508     }
509     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::stopDryRunning for (%p)\n",this);
510     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011lu\n", m_handler->getCycleTimerTicks());
511     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%u)\n", tx, TICKS_TO_CYCLES(tx));
512     return scheduleAndWaitForStateTransition(ePS_Stopped, tx, ePS_Stopped);
513 }
514
515 bool StreamProcessor::stopRunning(int64_t t) {
516     uint64_t tx;
517     if (t < 0) {
518         tx = addTicks(m_handler->getCycleTimerTicks(), 200 * TICKS_PER_CYCLE);
519     } else {
520         tx = t;
521     }
522     debugOutput(DEBUG_LEVEL_VERBOSE," StreamProcessor::stopRunning for (%p)\n",this);
523     debugOutput(DEBUG_LEVEL_VERBOSE,"  Now                   : %011lu\n", m_handler->getCycleTimerTicks());
524     debugOutput(DEBUG_LEVEL_VERBOSE,"  Stop at               : %011llu (%u)\n", tx, TICKS_TO_CYCLES(tx));
525     return scheduleAndWaitForStateTransition(ePS_WaitingForStreamDisable, tx, ePS_DryRunning);
526 }
527
528 // internal state API
529
530 /**
531  * @brief Enter the ePS_Stopped state
532  * @return true if successful, false if not
533  *
534  * @pre none
535  *
536  * @post the buffer and the isostream are ready for use.
537  * @post all dynamic structures have been allocated successfully
538  * @post the buffer is transparent and empty, and all parameters are set
539  *       to the correct initial/nominal values.
540  *
541  */
542 bool
543 StreamProcessor::doStop()
544 {
545     float ticks_per_frame;
546     unsigned int ringbuffer_size_frames;
547
548     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
549     bool result = true;
550
551     switch(m_state) {
552         case ePS_Created:
553             assert(m_data_buffer);
554             // object just created
555             result = m_data_buffer->init();
556            
557             // prepare the framerate estimate
558             ticks_per_frame = (TICKS_PER_SECOND*1.0) / ((float)m_manager->getNominalRate());
559             m_ticks_per_frame = ticks_per_frame;
560             debugOutput(DEBUG_LEVEL_VERBOSE,"Initializing remote ticks/frame to %f\n", ticks_per_frame);
561        
562             // initialize internal buffer
563             ringbuffer_size_frames = m_manager->getNbBuffers() * m_manager->getPeriodSize();
564             result &= m_data_buffer->setBufferSize(ringbuffer_size_frames * 2);
565
566             result &= m_data_buffer->setEventSize( getEventSize() );
567             result &= m_data_buffer->setEventsPerFrame( getEventsPerFrame() );
568             result &= m_data_buffer->setUpdatePeriod( getUpdatePeriod() );
569
570             result &= m_data_buffer->setNominalRate(ticks_per_frame);
571             result &= m_data_buffer->setWrapValue(128L*TICKS_PER_SECOND);
572             result &= m_data_buffer->prepare(); // FIXME: the name
573
574             // set the parameters of ports we can:
575             // we want the audio ports to be period buffered,
576             // and the midi ports to be packet buffered
577             for ( PortVectorIterator it = m_Ports.begin();
578                 it != m_Ports.end();
579                 ++it )
580             {
581                 debugOutput(DEBUG_LEVEL_VERBOSE, "Setting up port %s\n",(*it)->getName().c_str());
582                 if(!(*it)->setBufferSize(m_manager->getPeriodSize())) {
583                     debugFatal("Could not set buffer size to %d\n",m_manager->getPeriodSize());
584                     return false;
585                 }
586                 switch ((*it)->getPortType()) {
587                     case Port::E_Audio:
588                         if(!(*it)->setSignalType(Port::E_PeriodSignalled)) {
589                             debugFatal("Could not set signal type to PeriodSignalling");
590                             return false;
591                         }
592                         // buffertype and datatype are dependant on the API
593                         debugWarning("---------------- ! Doing hardcoded dummy setup ! --------------\n");
594                         // buffertype and datatype are dependant on the API
595                         if(!(*it)->setBufferType(Port::E_PointerBuffer)) {
596                             debugFatal("Could not set buffer type");
597                             return false;
598                         }
599                         if(!(*it)->useExternalBuffer(true)) {
600                             debugFatal("Could not set external buffer usage");
601                             return false;
602                         }
603                         if(!(*it)->setDataType(Port::E_Float)) {
604                             debugFatal("Could not set data type");
605                             return false;
606                         }
607                         break;
608                     case Port::E_Midi:
609                         if(!(*it)->setSignalType(Port::E_PacketSignalled)) {
610                             debugFatal("Could not set signal type to PacketSignalling");
611                             return false;
612                         }
613                         // buffertype and datatype are dependant on the API
614                         // buffertype and datatype are dependant on the API
615                         debugWarning("---------------- ! Doing hardcoded test setup ! --------------\n");
616                         // buffertype and datatype are dependant on the API
617                         if(!(*it)->setBufferType(Port::E_RingBuffer)) {
618                             debugFatal("Could not set buffer type");
619                             return false;
620                         }
621                         if(!(*it)->setDataType(Port::E_MidiEvent)) {
622                             debugFatal("Could not set data type");
623                             return false;
624                         }
625                         break;
626                     default:
627                         debugWarning("Unsupported port type specified\n");
628                         break;
629                 }
630             }
631             // the API specific settings of the ports should already be set,
632             // as this is called from the processorManager->prepare()
633             // so we can init the ports
634             result &= PortManager::initPorts();
635
636             break;
637         case ePS_DryRunning:
638             // what to do here?
639             break;
640         default:
641             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
642             return false;
643     }
644
645     result &= m_data_buffer->reset(); // FIXME: don't like the reset() name
646
647     // make the buffer transparent
648     m_data_buffer->setTransparent(true);
649
650     // reset all ports
651     result &= PortManager::preparePorts();
652
653     m_state = ePS_Stopped;
654     return result;
655 }
656
657 /**
658  * @brief Enter the ePS_WaitingForStream state
659  * @return true if successful, false if not
660  *
661  * @pre all dynamic data structures are allocated successfully
662  *
663  * @post
664  *
665  */
666 bool
667 StreamProcessor::doWaitForRunningStream()
668 {
669     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
670     switch(m_state) {
671         case ePS_Stopped:
672             // we have to start waiting for an incoming stream
673             // this basically means nothing, the state change will
674             // be picked up by the packet iterator
675             break;
676         default:
677             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
678             return false;
679     }
680     m_state = ePS_WaitingForStream;
681     return true;
682 }
683
684 /**
685  * @brief Enter the ePS_DryRunning state
686  * @return true if successful, false if not
687  *
688  * @pre
689  *
690  * @post
691  *
692  */
693 bool
694 StreamProcessor::doDryRunning()
695 {
696     bool result = true;
697     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
698     switch(m_state) {
699         case ePS_WaitingForStream:
700             // a running stream has been detected
701             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started dry-running at cycle %d\n", this, m_last_cycle);
702             if (getType() == ePT_Receive) {
703                 m_data_buffer->setBufferTailTimestamp(m_last_timestamp);
704             } else {
705                 // FIXME
706                 debugError("Implement\n");
707             }
708             break;
709         case ePS_WaitingForStreamDisable:
710             result &= m_data_buffer->reset(); // FIXME: don't like the reset() name
711             m_data_buffer->setTransparent(true);
712             break;
713         default:
714             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
715             return false;
716     }
717     m_state = ePS_DryRunning;
718     return result;
719 }
720
721 /**
722  * @brief Enter the ePS_WaitingForStreamEnable state
723  * @return true if successful, false if not
724  *
725  * @pre
726  *
727  * @post
728  *
729  */
730 bool
731 StreamProcessor::doWaitForStreamEnable()
732 {
733     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
734     switch(m_state) {
735         case ePS_DryRunning:
736             // we have to start waiting for an incoming stream
737             // this basically means nothing, the state change will
738             // be picked up by the packet iterator
739             break;
740         default:
741             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
742             return false;
743     }
744     m_state = ePS_WaitingForStreamEnable;
745     return true;
746 }
747
748 /**
749  * @brief Enter the ePS_Running state
750  * @return true if successful, false if not
751  *
752  * @pre
753  *
754  * @post
755  *
756  */
757 bool
758 StreamProcessor::doRunning()
759 {
760     bool result = true;
761     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
762     switch(m_state) {
763         case ePS_WaitingForStreamEnable:
764             // a running stream has been detected
765             debugOutput(DEBUG_LEVEL_VERBOSE, "StreamProcessor %p started running at cycle %d\n",
766                                              this, m_last_cycle);
767             if (getType() == ePT_Receive) {
768                 m_data_buffer->setTransparent(false);
769             } else {
770                 // FIXME
771                 debugError("Implement\n");
772             }
773             break;
774         default:
775             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
776             return false;
777     }
778     m_state = ePS_Running;
779     return result;
780 }
781
782 /**
783  * @brief Enter the ePS_WaitingForStreamDisable state
784  * @return true if successful, false if not
785  *
786  * @pre
787  *
788  * @post
789  *
790  */
791 bool
792 StreamProcessor::doWaitForStreamDisable()
793 {
794     debugOutput(DEBUG_LEVEL_VERBOSE, "Enter from state: %s\n", ePSToString(m_state));
795     switch(m_state) {
796         case ePS_Running:
797             // the thread will do the transition
798             break;
799         default:
800             debugError("Entry from invalid state: %s\n", ePSToString(m_state));
801             return false;
802     }
803     m_state = ePS_WaitingForStreamDisable;
804     return true;
805 }
806
807 /**
808  * @brief Updates the state machine and calls the necessary transition functions
809  * @return true if successful, false if not
810  */
811 bool StreamProcessor::updateState() {
812     bool result = false;
813     // copy the current state locally since it could change value,
814     // and that's something we don't want to happen inbetween tests
815     // if m_next_state changes during this routine, we know for sure
816     // that the previous state change was at least attempted correctly.
817     enum eProcessorState next_state = m_next_state;
818
819     debugOutput(DEBUG_LEVEL_VERBOSE, "Do state transition: %s => %s\n",
820         ePSToString(m_state), ePSToString(next_state));
821
822     if (m_state == next_state) {
823         debugWarning("ignoring identity state update from/to %s\n", ePSToString(m_state) );
824         return true;
825     }
826
827     // after creation, only initialization is allowed
828     if (m_state == ePS_Created) {
829         if(next_state != ePS_Stopped) {
830             goto updateState_exit_with_error;
831         }
832         // do init here
833         result = doStop();
834         if (result) return true;
835         else goto updateState_exit_change_failed;
836     }
837
838     // after initialization, only WaitingForRunningStream is allowed
839     if (m_state == ePS_Stopped) {
840         if(next_state != ePS_WaitingForStream) {
841             goto updateState_exit_with_error;
842         }
843         result = doWaitForRunningStream();
844         if (result) return true;
845         else goto updateState_exit_change_failed;
846     }
847
848     // after WaitingForStream, only ePS_DryRunning is allowed
849     // this means that the stream started running
850     if (m_state == ePS_WaitingForStream) {
851         if(next_state != ePS_DryRunning) {
852             goto updateState_exit_with_error;
853         }
854         result = doDryRunning();
855         if (result) return true;
856         else goto updateState_exit_change_failed;
857     }
858
859     // from ePS_DryRunning we can go to:
860     //   - ePS_Stopped if something went wrong during DryRunning
861     //   - ePS_WaitingForStreamEnable if there is a requested to enable
862     if (m_state == ePS_DryRunning) {
863         if((next_state != ePS_Stopped) &&
864            (next_state != ePS_WaitingForStreamEnable)) {
865             goto updateState_exit_with_error;
866         }
867         if (next_state == ePS_Stopped) {
868             result = doStop();
869         } else {
870             result = doWaitForStreamEnable();
871         }
872         if (result) return true;
873         else goto updateState_exit_change_failed;
874     }
875
876     // from ePS_WaitingForStreamEnable we can go to:
877     //   - ePS_DryRunning if something went wrong while waiting
878     //   - ePS_Running if the stream enabled correctly
879     if (m_state == ePS_WaitingForStreamEnable) {
880         if((next_state != ePS_DryRunning) &&
881            (next_state != ePS_Running)) {
882             goto updateState_exit_with_error;
883         }
884         if (next_state == ePS_Stopped) {
885             result = doDryRunning();
886         } else {
887             result = doRunning();
888         }
889         if (result) return true;
890         else goto updateState_exit_change_failed;
891     }
892
893     // from ePS_Running we can only start waiting for a disabled stream
894     if (m_state == ePS_Running) {
895         if(next_state != ePS_WaitingForStreamDisable) {
896             goto updateState_exit_with_error;
897         }
898         result = doWaitForStreamDisable();
899         if (result) return true;
900         else goto updateState_exit_change_failed;
901     }
902
903     // from ePS_WaitingForStreamDisable we can go to DryRunning
904     if (m_state == ePS_WaitingForStreamDisable) {
905         if(next_state != ePS_DryRunning) {
906             goto updateState_exit_with_error;
907         }
908         result = doDryRunning();
909         if (result) return true;
910         else goto updateState_exit_change_failed;
911     }
912
913     // if we arrive here there is an error
914 updateState_exit_with_error:
915     debugError("Invalid state transition: %s => %s\n",
916         ePSToString(m_state), ePSToString(next_state));
917     return false;
918 updateState_exit_change_failed:
919     debugError("State transition failed: %s => %s\n",
920         ePSToString(m_state), ePSToString(next_state));
921     return false;
922 }
923
924
925 /**
926  * @brief convert a eProcessorState to a string
927  * @param s the state
928  * @return a char * describing the state
929  */
930 const char *
931 StreamProcessor::ePSToString(enum eProcessorState s) {
932     switch (s) {
933         case ePS_Invalid: return "ePS_Invalid";
934         case ePS_Created: return "ePS_Created";
935         case ePS_Stopped: return "ePS_Stopped";
936         case ePS_WaitingForStream: return "ePS_WaitingForStream";
937         case ePS_DryRunning: return "ePS_DryRunning";
938         case ePS_WaitingForStreamEnable: return "ePS_WaitingForStreamEnable";
939         case ePS_Running: return "ePS_Running";
940         case ePS_WaitingForStreamDisable: return "ePS_WaitingForStreamDisable";
941         default: return "error: unknown state";
942     }
943 }
944
945 /**
946  * @brief convert a eProcessorType to a string
947  * @param t the type
948  * @return a char * describing the state
949  */
950 const char *
951 StreamProcessor::ePTToString(enum eProcessorType t) {
952     switch (t) {
953         case ePT_Receive: return "Receive";
954         case ePT_Transmit: return "Transmit";
955         default: return "error: unknown type";
956     }
957 }
958
959 /***********************************************
960  * Debug                                       *
961  ***********************************************/
962 void
963 StreamProcessor::dumpInfo()
964 {
965     debugOutputShort( DEBUG_LEVEL_NORMAL, " StreamProcessor information\n");
966     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Iso stream info:\n");
967
968     IsoStream::dumpInfo();
969     debugOutputShort( DEBUG_LEVEL_NORMAL, "  StreamProcessor info:\n");
970     if (m_handler)
971         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Now                   : %011u\n",m_handler->getCycleTimerTicks());
972     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Xruns                 : %d\n", m_xruns);
973     debugOutputShort( DEBUG_LEVEL_NORMAL, "  State                 : %s\n", ePSToString(m_state));
974     debugOutputShort( DEBUG_LEVEL_NORMAL, "   Next state           : %s\n", ePSToString(m_next_state));
975     debugOutputShort( DEBUG_LEVEL_NORMAL, "    transition at       : %u\n", m_cycle_to_switch_state);
976    
977
978     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Nominal framerate     : %u\n", m_manager->getNominalRate());
979     debugOutputShort( DEBUG_LEVEL_NORMAL, "  Device framerate      : Sync: %f, Buffer %f\n",
980         24576000.0/m_manager->getSyncSource().m_data_buffer->getRate(),
981         24576000.0/m_data_buffer->getRate()
982         );
983
984     m_data_buffer->dumpInfo();
985
986     m_PeriodStat.dumpInfo();
987     m_PacketStat.dumpInfo();
988 //     m_WakeupStat.dumpInfo();
989 }
990
991 void
992 StreamProcessor::setVerboseLevel(int l) {
993     setDebugLevel(l);
994     IsoStream::setVerboseLevel(l);
995     PortManager::setVerboseLevel(l);
996     m_data_buffer->setVerboseLevel(l);
997 }
998
999 } // end of namespace
Note: See TracBrowser for help on using the browser.