root/branches/libffado-2.0/src/libstreaming/StreamProcessorManager.cpp

Revision 1544, 65.0 kB (checked in by ppalmers, 12 years ago)

round the transmit safety buffer size to one packet size (in frames) to avoid messing up the MIDI time muxed stream position

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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 #include "config.h"
24
25 #include "StreamProcessorManager.h"
26 #include "generic/StreamProcessor.h"
27 #include "generic/Port.h"
28 #include "libieee1394/cycletimer.h"
29
30 #include "devicemanager.h"
31
32 #include "libutil/Time.h"
33
34 #include <errno.h>
35 #include <assert.h>
36 #include <math.h>
37
38 namespace Streaming {
39
40 IMPL_DEBUG_MODULE( StreamProcessorManager, StreamProcessorManager, DEBUG_LEVEL_VERBOSE );
41
42 StreamProcessorManager::StreamProcessorManager(DeviceManager &p)
43     : m_time_of_transfer ( 0 )
44     #ifdef DEBUG
45     , m_time_of_transfer2 ( 0 )
46     #endif
47     , m_is_slave( false )
48     , m_SyncSource(NULL)
49     , m_parent( p )
50     , m_xrun_happened( false )
51     , m_activity_wait_timeout_nsec( 0 ) // dynamically set
52     , m_nb_buffers( 0 )
53     , m_period( 0 )
54     , m_sync_delay( 0 )
55     , m_audio_datatype( eADT_Float )
56     , m_nominal_framerate ( 0 )
57     , m_xruns(0)
58     , m_shutdown_needed(false)
59     , m_nbperiods(0)
60     , m_WaitLock( new Util::PosixMutex("SPMWAIT") )
61 {
62     addOption(Util::OptionContainer::Option("slaveMode",false));
63     sem_init(&m_activity_semaphore, 0, 0);
64 }
65
66 StreamProcessorManager::StreamProcessorManager(DeviceManager &p, unsigned int period,
67                                                unsigned int framerate, unsigned int nb_buffers)
68     : m_time_of_transfer ( 0 )
69     #ifdef DEBUG
70     , m_time_of_transfer2 ( 0 )
71     #endif
72     , m_is_slave( false )
73     , m_SyncSource(NULL)
74     , m_parent( p )
75     , m_xrun_happened( false )
76     , m_activity_wait_timeout_nsec( 0 ) // dynamically set
77     , m_nb_buffers(nb_buffers)
78     , m_period(period)
79     , m_sync_delay( 0 )
80     , m_audio_datatype( eADT_Float )
81     , m_nominal_framerate ( framerate )
82     , m_xruns(0)
83     , m_shutdown_needed(false)
84     , m_nbperiods(0)
85     , m_WaitLock( new Util::PosixMutex("SPMWAIT") )
86 {
87     addOption(Util::OptionContainer::Option("slaveMode",false));
88     sem_init(&m_activity_semaphore, 0, 0);
89 }
90
91 StreamProcessorManager::~StreamProcessorManager() {
92     sem_post(&m_activity_semaphore);
93     sem_destroy(&m_activity_semaphore);
94     delete m_WaitLock;
95 }
96
97 // void
98 // StreamProcessorManager::handleBusReset(Ieee1394Service &s)
99 // {
100 // //     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) Handle bus reset on service %p...\n", this, &s);
101 // //
102 // //     bool handled_at_least_one = false;
103 // //     // note that all receive streams are gone once a device is unplugged
104 // //
105 // //     // synchronize with the wait lock
106 // //     Util::MutexLockHelper lock(*m_WaitLock);
107 // //
108 // //     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) got wait lock...\n", this);
109 // //     // cause all SP's to bail out
110 // //     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
111 // //           it != m_ReceiveProcessors.end();
112 // //           ++it )
113 // //     {
114 // //         if(&s == &((*it)->getParent().get1394Service())) {
115 // //             debugOutput(DEBUG_LEVEL_NORMAL,
116 // //                         "issue busreset on receive SPM on channel %d\n",
117 // //                         (*it)->getChannel());
118 // //             (*it)->handleBusReset();
119 // //             handled_at_least_one = true;
120 // //         } else {
121 // //             debugOutput(DEBUG_LEVEL_NORMAL,
122 // //                         "skipping receive SPM on channel %d since not on service %p\n",
123 // //                         (*it)->getChannel(), &s);
124 // //         }
125 // //     }
126 // //     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
127 // //           it != m_TransmitProcessors.end();
128 // //           ++it )
129 // //     {
130 // //         if(&s == &((*it)->getParent().get1394Service())) {
131 // //             debugOutput(DEBUG_LEVEL_NORMAL,
132 // //                         "issue busreset on transmit SPM on channel %d\n",
133 // //                         (*it)->getChannel());
134 // //             (*it)->handleBusReset();
135 // //             handled_at_least_one = true;
136 // //         } else {
137 // //             debugOutput(DEBUG_LEVEL_NORMAL,
138 // //                         "skipping transmit SPM on channel %d since not on service %p\n",
139 // //                         (*it)->getChannel(), &s);
140 // //         }
141 // //     }
142 // //
143 // //     // FIXME: we request shutdown for now.
144 // //     m_shutdown_needed = handled_at_least_one;
145 // }
146
147 void
148 StreamProcessorManager::signalActivity()
149 {
150     sem_post(&m_activity_semaphore);
151     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,"%p activity\n", this);
152 }
153
154 enum StreamProcessorManager::eActivityResult
155 StreamProcessorManager::waitForActivity()
156 {
157     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,"%p waiting for activity\n", this);
158     struct timespec ts;
159     int result;
160
161     if (m_activity_wait_timeout_nsec >= 0) {
162
163         if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
164             debugError("clock_gettime failed\n");
165             return eAR_Error;
166         }
167         ts.tv_nsec += m_activity_wait_timeout_nsec;
168         while(ts.tv_nsec >= 1000000000LL) {
169             ts.tv_sec += 1;
170             ts.tv_nsec -= 1000000000LL;
171         }
172     }
173
174     if (m_activity_wait_timeout_nsec >= 0) {
175         result = sem_timedwait(&m_activity_semaphore, &ts);
176     } else {
177         result = sem_wait(&m_activity_semaphore);
178     }
179
180     if(result != 0) {
181         if (errno == ETIMEDOUT) {
182             debugOutput(DEBUG_LEVEL_VERBOSE,
183                         "(%p) sem_timedwait() timed out (result=%d)\n",
184                         this, result);
185             return eAR_Timeout;
186         } else if (errno == EINTR) {
187             debugOutput(DEBUG_LEVEL_VERBOSE,
188                         "(%p) sem_[timed]wait() interrupted by signal (result=%d)\n",
189                         this, result);
190             return eAR_Interrupted;
191         } else if (errno == EINVAL) {
192             debugError("(%p) sem_[timed]wait error (result=%d errno=EINVAL)\n",
193                         this, result);
194             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
195                        this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec);
196             return eAR_Error;
197         } else {
198             debugError("(%p) sem_[timed]wait error (result=%d errno=%d)\n",
199                         this, result, errno);
200             debugError("(%p) timeout_nsec=%lld ts.sec=%d ts.nsec=%lld\n",
201                        this, m_activity_wait_timeout_nsec, ts.tv_sec, ts.tv_nsec);
202             return eAR_Error;
203         }
204     }
205
206     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,"%p got activity\n", this);
207     return eAR_Activity;
208 }
209
210 /**
211  * Registers \ref processor with this manager.
212  *
213  * also registers it with the isohandlermanager
214  *
215  * be sure to call isohandlermanager->init() first!
216  * and be sure that the processors are also ->init()'ed
217  *
218  * @param processor
219  * @return true if successfull
220  */
221 bool StreamProcessorManager::registerProcessor(StreamProcessor *processor)
222 {
223     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering processor (%p)\n",processor);
224     assert(processor);
225     if (processor->getType() == StreamProcessor::ePT_Receive) {
226         processor->setVerboseLevel(getDebugLevel()); // inherit debug level
227         m_ReceiveProcessors.push_back(processor);
228         Util::Functor* f = new Util::MemberFunctor0< StreamProcessorManager*, void (StreamProcessorManager::*)() >
229                     ( this, &StreamProcessorManager::updateShadowLists, false );
230         processor->addPortManagerUpdateHandler(f);
231         updateShadowLists();
232         return true;
233     }
234     if (processor->getType() == StreamProcessor::ePT_Transmit) {
235         processor->setVerboseLevel(getDebugLevel()); // inherit debug level
236         m_TransmitProcessors.push_back(processor);
237         Util::Functor* f = new Util::MemberFunctor0< StreamProcessorManager*, void (StreamProcessorManager::*)() >
238                     ( this, &StreamProcessorManager::updateShadowLists, false );
239         processor->addPortManagerUpdateHandler(f);
240         updateShadowLists();
241         return true;
242     }
243
244     debugFatal("Unsupported processor type!\n");
245     return false;
246 }
247
248 bool StreamProcessorManager::unregisterProcessor(StreamProcessor *processor)
249 {
250     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering processor (%p)\n",processor);
251     assert(processor);
252
253     if (processor->getType()==StreamProcessor::ePT_Receive) {
254
255         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
256               it != m_ReceiveProcessors.end();
257               ++it )
258         {
259             if ( *it == processor ) {
260                 if (*it == m_SyncSource) {
261                     debugOutput(DEBUG_LEVEL_VERBOSE, "unregistering sync source\n");
262                     m_SyncSource = NULL;
263                 }
264                 m_ReceiveProcessors.erase(it);
265                 // remove the functor
266                 Util::Functor * f = processor->getUpdateHandlerForPtr(this);
267                 if(f) {
268                     processor->remPortManagerUpdateHandler(f);
269                     delete f;
270                 }
271                 updateShadowLists();
272                 return true;
273             }
274         }
275     }
276
277     if (processor->getType()==StreamProcessor::ePT_Transmit) {
278         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
279               it != m_TransmitProcessors.end();
280               ++it )
281         {
282             if ( *it == processor ) {
283                 if (*it == m_SyncSource) {
284                     debugOutput(DEBUG_LEVEL_VERBOSE, "unregistering sync source\n");
285                     m_SyncSource = NULL;
286                 }
287                 m_TransmitProcessors.erase(it);
288                 // remove the functor
289                 Util::Functor * f = processor->getUpdateHandlerForPtr(this);
290                 if(f) {
291                     processor->remPortManagerUpdateHandler(f);
292                     delete f;
293                 }
294                 updateShadowLists();
295                 return true;
296             }
297         }
298     }
299
300     debugFatal("Processor (%p) not found!\n",processor);
301     return false; //not found
302 }
303
304 bool StreamProcessorManager::setSyncSource(StreamProcessor *s) {
305     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting sync source to (%p)\n", s);
306     m_SyncSource = s;
307     return true;
308 }
309
310 bool StreamProcessorManager::prepare() {
311
312     debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
313     m_is_slave=false;
314     if(!getOption("slaveMode", m_is_slave)) {
315         debugWarning("Could not retrieve slaveMode parameter, defaulting to false\n");
316     }
317
318     m_shutdown_needed=false;
319
320     // if no sync source is set, select one here
321     if(m_SyncSource == NULL) {
322        debugWarning("Sync Source is not set. Defaulting to first StreamProcessor.\n");
323     }
324
325     // FIXME: put into separate method
326     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
327           it != m_ReceiveProcessors.end();
328           ++it )
329     {
330         if(m_SyncSource == NULL) {
331             debugWarning(" => Sync Source is %p.\n", *it);
332             m_SyncSource = *it;
333         }
334     }
335     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
336           it != m_TransmitProcessors.end();
337           ++it )
338     {
339         if(m_SyncSource == NULL) {
340             debugWarning(" => Sync Source is %p.\n", *it);
341             m_SyncSource = *it;
342         }
343     }
344
345     // now do the actual preparation of the SP's
346     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Receive processors...\n");
347     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
348         it != m_ReceiveProcessors.end();
349         ++it ) {
350
351         if(!(*it)->setOption("slaveMode", m_is_slave)) {
352             debugOutput(DEBUG_LEVEL_VERBOSE, " note: could not set slaveMode option for (%p)...\n",(*it));
353         }
354
355         if(!(*it)->prepare()) {
356             debugFatal(  " could not prepare (%p)...\n",(*it));
357             return false;
358         }
359     }
360     debugOutput( DEBUG_LEVEL_VERBOSE, "Prepare Transmit processors...\n");
361     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
362         it != m_TransmitProcessors.end();
363         ++it ) {
364         if(!(*it)->setOption("slaveMode", m_is_slave)) {
365             debugOutput(DEBUG_LEVEL_VERBOSE, " note: could not set slaveMode option for (%p)...\n",(*it));
366         }
367         if(!(*it)->prepare()) {
368             debugFatal( " could not prepare (%p)...\n",(*it));
369             return false;
370         }
371     }
372
373     // if there are no stream processors registered,
374     // fail
375     if (m_ReceiveProcessors.size() + m_TransmitProcessors.size() == 0) {
376         debugFatal("No stream processors registered, can't do anything usefull\n");
377         return false;
378     }
379
380     // set the activity timeout value to two periods worth of usecs.
381     // since we can expect activity once every period, but we might have some
382     // offset, the safe value is two periods.
383     int timeout_usec = 2*1000LL * 1000LL * m_period / m_nominal_framerate;
384     debugOutput(DEBUG_LEVEL_VERBOSE, "setting activity timeout to %d\n", timeout_usec);
385     setActivityWaitTimeoutUsec(timeout_usec);
386
387     updateShadowLists();
388
389     return true;
390 }
391
392 bool
393 StreamProcessorManager::startDryRunning()
394 {
395     debugOutput( DEBUG_LEVEL_VERBOSE, "Putting StreamProcessor streams into dry-running state...\n");
396     debugOutput( DEBUG_LEVEL_VERBOSE, " Schedule start dry-running...\n");
397     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
398             it != m_TransmitProcessors.end();
399             ++it ) {
400         if ((*it)->inError()) {
401             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %p in error state\n", *it);
402             return false;
403         }
404         if (!(*it)->isDryRunning()) {
405             if(!(*it)->scheduleStartDryRunning(-1)) {
406                 debugError("Could not put SP %p into the dry-running state\n", *it);
407                 return false;
408             }
409         } else {
410             debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it);
411         }
412     }
413     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
414             it != m_ReceiveProcessors.end();
415             ++it ) {
416         if ((*it)->inError()) {
417             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %p in error state\n", *it);
418             return false;
419         }
420         if (!(*it)->isDryRunning()) {
421             if(!(*it)->scheduleStartDryRunning(-1)) {
422                 debugError("Could not put SP %p into the dry-running state\n", *it);
423                 return false;
424             }
425         } else {
426             debugOutput( DEBUG_LEVEL_VERBOSE, " SP %p already dry-running...\n", *it);
427         }
428     }
429     debugOutput( DEBUG_LEVEL_VERBOSE, " Waiting for all SP's to be dry-running...\n");
430     // wait for the syncsource to start running.
431     // that will block the waitForPeriod call until everyone has started (theoretically)
432     int cnt = STREAMPROCESSORMANAGER_CYCLES_FOR_DRYRUN; // by then it should have started
433     bool all_dry_running = false;
434     while (!all_dry_running && cnt) {
435         all_dry_running = true;
436         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
437                 it != m_ReceiveProcessors.end();
438                 ++it ) {
439             all_dry_running &= (*it)->isDryRunning();
440         }
441         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
442                 it != m_TransmitProcessors.end();
443                 ++it ) {
444             all_dry_running &= (*it)->isDryRunning();
445         }
446
447         SleepRelativeUsec(125);
448         cnt--;
449     }
450     if(cnt==0) {
451         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SP's to start dry-running\n");
452         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
453                 it != m_ReceiveProcessors.end();
454                 ++it ) {
455             debugOutput( DEBUG_LEVEL_VERBOSE, " %s SP %p has state %s\n",
456                 (*it)->getTypeString(), *it, (*it)->getStateString());
457         }
458         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
459                 it != m_TransmitProcessors.end();
460                 ++it ) {
461             debugOutput( DEBUG_LEVEL_VERBOSE, " %s SP %p has state %s\n",
462                 (*it)->getTypeString(), *it, (*it)->getStateString());
463         }
464         return false;
465     }
466     debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams dry-running...\n");
467     return true;
468 }
469
470 bool StreamProcessorManager::syncStartAll() {
471     if(m_SyncSource == NULL) return false;
472
473     // get the options
474     int signal_delay_ticks = STREAMPROCESSORMANAGER_SIGNAL_DELAY_TICKS;
475     int xmit_prebuffer_frames = STREAMPROCESSORMANAGER_XMIT_PREBUFFER_FRAMES;
476     int sync_wait_time_msec = STREAMPROCESSORMANAGER_SYNC_WAIT_TIME_MSEC;
477     int cycles_for_startup = STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP;
478     int prestart_cycles_for_xmit = STREAMPROCESSORMANAGER_PRESTART_CYCLES_FOR_XMIT;
479     int prestart_cycles_for_recv = STREAMPROCESSORMANAGER_PRESTART_CYCLES_FOR_RECV;
480     Util::Configuration &config = m_parent.getConfiguration();
481     config.getValueForSetting("streaming.spm.signal_delay_ticks", signal_delay_ticks);
482     config.getValueForSetting("streaming.spm.xmit_prebuffer_frames", xmit_prebuffer_frames);
483     config.getValueForSetting("streaming.spm.sync_wait_time_msec", sync_wait_time_msec);
484     config.getValueForSetting("streaming.spm.cycles_for_startup", cycles_for_startup);
485     config.getValueForSetting("streaming.spm.prestart_cycles_for_xmit", prestart_cycles_for_xmit);
486     config.getValueForSetting("streaming.spm.prestart_cycles_for_recv", prestart_cycles_for_recv);
487
488     // figure out when to get the SP's running.
489     // the xmit SP's should also know the base timestamp
490     // streams should be aligned here
491
492     // now find out how long we have to delay the wait operation such that
493     // the received frames will all be presented to the SP
494     debugOutput( DEBUG_LEVEL_VERBOSE, "Finding minimal sync delay...\n");
495     int max_of_min_delay = 0;
496     int min_delay = 0;
497     int packet_size_frames = 0;
498     int max_packet_size_frames = 0;
499
500     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
501             it != m_ReceiveProcessors.end();
502             ++it ) {
503         min_delay = (*it)->getMaxFrameLatency();
504         if(min_delay > max_of_min_delay) max_of_min_delay = min_delay;
505         packet_size_frames = (*it)->getNominalFramesPerPacket();
506         if(packet_size_frames > max_packet_size_frames) max_packet_size_frames = packet_size_frames;
507     }
508     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
509             it != m_TransmitProcessors.end();
510             ++it ) {
511         packet_size_frames = (*it)->getNominalFramesPerPacket();
512         if(packet_size_frames > max_packet_size_frames) max_packet_size_frames = packet_size_frames;
513     }
514     debugOutput( DEBUG_LEVEL_VERBOSE, " max_of_min_delay = %d, max_packet_size_frames = %d...\n", max_of_min_delay, max_packet_size_frames);
515
516     // add some processing margin. This only shifts the time
517     // at which the buffer is transfer()'ed. This makes things somewhat
518     // more robust.
519     m_sync_delay = max_of_min_delay + signal_delay_ticks;
520
521     //STEP X: when we implement such a function, we can wait for a signal from the devices that they
522     //        have aquired lock
523     //debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for device(s) to indicate clock sync lock...\n");
524     //sleep(2); // FIXME: be smarter here
525
526     // make sure that we are dry-running long enough for the
527     // DLL to have a decent sync (FIXME: does the DLL get updated when dry-running)?
528     debugOutput( DEBUG_LEVEL_VERBOSE, "Waiting for sync...\n");
529
530     unsigned int nb_sync_runs = (sync_wait_time_msec * getNominalRate());
531     nb_sync_runs /= 1000;
532     nb_sync_runs /= getPeriodSize();
533
534     while(nb_sync_runs--) { // or while not sync-ed?
535         // check if we were woken up too soon
536         uint64_t ticks_at_period = m_SyncSource->getTimeAtPeriod();
537         uint64_t ticks_at_period_margin = ticks_at_period + m_sync_delay;
538         uint64_t pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(ticks_at_period_margin);
539    
540         #ifdef DEBUG
541         int64_t now = Util::SystemTimeSource::getCurrentTime();
542         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "CTR  pred: %lld, syncdelay: %lld, diff: %lld\n", ticks_at_period, ticks_at_period_margin, ticks_at_period_margin-ticks_at_period );
543         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "PREWAIT  pred: %lld, now: %lld, wait: %lld\n", pred_system_time_at_xfer, now, pred_system_time_at_xfer-now );
544         #endif
545    
546         // wait until it's time to transfer
547         Util::SystemTimeSource::SleepUsecAbsolute(pred_system_time_at_xfer);
548    
549         #ifdef DEBUG
550         now = Util::SystemTimeSource::getCurrentTime();
551         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "POSTWAIT pred: %lld, now: %lld, excess: %lld\n", pred_system_time_at_xfer, now, now-pred_system_time_at_xfer );
552         #endif
553     }
554
555     debugOutput( DEBUG_LEVEL_VERBOSE, "Propagate sync info...\n");
556     // FIXME: in the SPM it would be nice to have system time instead of
557     //        1394 time
558
559     float syncrate = 0.0;
560     float tpf = m_SyncSource->getTicksPerFrame();
561     if (tpf > 0.0) {
562         syncrate = 24576000.0/tpf;
563     } else {
564         debugWarning("tpf <= 0? %f\n", tpf);
565     }
566     debugOutput( DEBUG_LEVEL_VERBOSE, " sync source frame rate: %f fps (%f tpf)\n", syncrate, tpf);
567
568     // we now should have decent sync info on the sync source
569     // determine a point in time where the system should start
570     // figure out where we are now
571     uint64_t time_of_first_sample = m_SyncSource->getTimeAtPeriod();
572     debugOutput( DEBUG_LEVEL_VERBOSE, " sync at TS=%011llu (%03us %04uc %04ut)...\n",
573         time_of_first_sample,
574         (unsigned int)TICKS_TO_SECS(time_of_first_sample),
575         (unsigned int)TICKS_TO_CYCLES(time_of_first_sample),
576         (unsigned int)TICKS_TO_OFFSET(time_of_first_sample));
577
578     // start wet-running in STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP cycles
579     // this is the time window we have to setup all SP's such that they
580     // can start wet-running correctly.
581     // we have to round this time to an integer number of audio packets
582     double time_for_startup_abs = (double)(cycles_for_startup * TICKS_PER_CYCLE);
583     int time_for_startup_frames = (int)(time_for_startup_abs / tpf);
584     time_for_startup_frames = ((time_for_startup_frames / max_packet_size_frames) + 1) * max_packet_size_frames;
585     uint64_t time_for_startup_ticks = (uint64_t)((float)time_for_startup_frames * tpf);
586
587     time_of_first_sample = addTicks(time_of_first_sample,
588                                     time_for_startup_ticks);
589     debugOutput( DEBUG_LEVEL_VERBOSE, "  add %d frames (%011llu ticks)...\n",
590         time_for_startup_frames, time_for_startup_ticks);
591
592     debugOutput( DEBUG_LEVEL_VERBOSE, "  => first sample at TS=%011llu (%03us %04uc %04ut)...\n",
593         time_of_first_sample,
594         (unsigned int)TICKS_TO_SECS(time_of_first_sample),
595         (unsigned int)TICKS_TO_CYCLES(time_of_first_sample),
596         (unsigned int)TICKS_TO_OFFSET(time_of_first_sample));
597
598     // we should start wet-running the transmit SP's some cycles in advance
599     // such that we know it is wet-running when it should output its first sample
600     uint64_t time_to_start_xmit = substractTicks(time_of_first_sample,
601                                                  prestart_cycles_for_xmit * TICKS_PER_CYCLE);
602
603     uint64_t time_to_start_recv = substractTicks(time_of_first_sample,
604                                                  prestart_cycles_for_recv * TICKS_PER_CYCLE);
605     debugOutput( DEBUG_LEVEL_VERBOSE, "  => xmit starts at  TS=%011llu (%03us %04uc %04ut)...\n",
606         time_to_start_xmit,
607         (unsigned int)TICKS_TO_SECS(time_to_start_xmit),
608         (unsigned int)TICKS_TO_CYCLES(time_to_start_xmit),
609         (unsigned int)TICKS_TO_OFFSET(time_to_start_xmit));
610     debugOutput( DEBUG_LEVEL_VERBOSE, "  => recv starts at  TS=%011llu (%03us %04uc %04ut)...\n",
611         time_to_start_recv,
612         (unsigned int)TICKS_TO_SECS(time_to_start_recv),
613         (unsigned int)TICKS_TO_CYCLES(time_to_start_recv),
614         (unsigned int)TICKS_TO_OFFSET(time_to_start_recv));
615
616     // print the sync delay
617     int sync_delay_frames = (int)((float)m_sync_delay / m_SyncSource->getTicksPerFrame());
618     debugOutput( DEBUG_LEVEL_VERBOSE, " sync delay: %d = %d + %d ticks (%03us %04uc %04ut) [%d frames]...\n",
619         m_sync_delay, max_of_min_delay, signal_delay_ticks,
620         (unsigned int)TICKS_TO_SECS(m_sync_delay),
621         (unsigned int)TICKS_TO_CYCLES(m_sync_delay),
622         (unsigned int)TICKS_TO_OFFSET(m_sync_delay),
623         sync_delay_frames);
624
625     // the amount of prebuffer frames should be a multiple of the common block size
626     // as otherwise the position of MIDI is messed up
627     if(xmit_prebuffer_frames % max_packet_size_frames) {
628         int tmp = 0;
629         while(tmp < xmit_prebuffer_frames) {
630             tmp += max_packet_size_frames;
631         }
632         debugOutput(DEBUG_LEVEL_VERBOSE,
633                     "The number of prebuffer frames (%d) is not a multiple of the common block size (%d), increased to %d...\n",
634                     xmit_prebuffer_frames, max_packet_size_frames, tmp);
635         xmit_prebuffer_frames = tmp;
636     }
637
638     // check if this can even work.
639     // the worst case point where we can receive a period is at 1 period + sync delay
640     // this means that the number of frames in the xmit buffer has to be at least
641     // 1 period + sync delay
642     if(xmit_prebuffer_frames + m_period * m_nb_buffers < m_period + sync_delay_frames) {
643         debugWarning("The amount of transmit buffer frames (%d) is too small (< %d). "
644                      "This will most likely cause xruns.\n",
645                      xmit_prebuffer_frames + m_period * m_nb_buffers,
646                      m_period + sync_delay_frames);
647     }
648
649     // at this point the buffer head timestamp of the transmit buffers can be set
650     // this is the presentation time of the first sample in the buffer
651     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
652           it != m_TransmitProcessors.end();
653           ++it ) {
654         // set the number of prebuffer frames
655         (*it)->setExtraBufferFrames(xmit_prebuffer_frames);
656
657         // set the TSP of the first sample in the buffer
658         (*it)->setBufferHeadTimestamp(time_of_first_sample);
659         ffado_timestamp_t ts;
660         signed int fc;
661         (*it)->getBufferHeadTimestamp ( &ts, &fc );
662         debugOutput( DEBUG_LEVEL_VERBOSE, " transmit buffer tail %010lld => head TS %010lld, fc=%d...\n",
663                     time_of_first_sample, (uint64_t)ts, fc);
664     }
665
666     // the receive processors can be delayed by sync_delay ticks
667     // this means that in the worst case we have to be able to accomodate
668     // an extra sync_delay ticks worth of frames in the receive SP buffer
669     // the sync delay should be rounded to an integer amount of max_packet_size
670     int tmp = sync_delay_frames / max_packet_size_frames;
671     tmp = tmp + 1;
672     sync_delay_frames = tmp * max_packet_size_frames;
673     if (sync_delay_frames < 1024) sync_delay_frames = 1024; //HACK
674
675     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
676           it != m_ReceiveProcessors.end();
677           ++it ) {
678         // set the number of extra buffer frames
679         (*it)->setExtraBufferFrames(sync_delay_frames);
680     }
681
682     // switch syncsource to running state
683     uint64_t time_to_start_sync;
684     // FIXME: this is most likely not going to work for transmit sync sources
685     // but those are unsupported in this version
686     if(m_SyncSource->getType() == StreamProcessor::ePT_Receive ) {
687         time_to_start_sync = time_to_start_recv;
688     } else {
689         time_to_start_sync = time_to_start_xmit;
690     }
691     if(!m_SyncSource->scheduleStartRunning(time_to_start_sync)) {
692         debugError("m_SyncSource->scheduleStartRunning(%11llu) failed\n", time_to_start_sync);
693         return false;
694     }
695
696     // STEP X: switch all non-syncsource SP's over to the running state
697     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
698           it != m_ReceiveProcessors.end();
699           ++it ) {
700         if(*it != m_SyncSource) {
701             if(!(*it)->scheduleStartRunning(time_to_start_recv)) {
702                 debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_recv);
703                 return false;
704             }
705         }
706     }
707     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
708           it != m_TransmitProcessors.end();
709           ++it ) {
710         if(*it != m_SyncSource) {
711             if(!(*it)->scheduleStartRunning(time_to_start_xmit)) {
712                 debugError("%p->scheduleStartRunning(%11llu) failed\n", *it, time_to_start_xmit);
713                 return false;
714             }
715         }
716     }
717     // wait for the syncsource to start running.
718     // that will block the waitForPeriod call until everyone has started (theoretically)
719     // note: the SP's are scheduled to start in STREAMPROCESSORMANAGER_CYCLES_FOR_STARTUP cycles,
720     // so a 20 times this value should be a good timeout
721     //int cnt = cycles_for_startup * 20; // by then it should have started
722     // or maybe we just have to use 1 second, as this wraps the cycle counter
723     int cnt = 8000;
724     while (!m_SyncSource->isRunning() && cnt) {
725         SleepRelativeUsec(125);
726         cnt--;
727     }
728     if(cnt==0) {
729         debugOutput(DEBUG_LEVEL_VERBOSE, " Timeout waiting for the SyncSource to get started\n");
730         return false;
731     }
732
733     // the sync source is running, we can now read a decent received timestamp from it
734     m_time_of_transfer = m_SyncSource->getTimeAtPeriod();
735
736     // and a (rough) approximation of the rate
737     float rate = m_SyncSource->getTicksPerFrame();
738
739     #ifdef DEBUG
740     // the time at which the previous period would have passed
741     m_time_of_transfer2 = m_time_of_transfer;
742     m_time_of_transfer2 = substractTicks(m_time_of_transfer2, (uint64_t)(m_period * rate));
743     #endif
744
745     debugOutput( DEBUG_LEVEL_VERBOSE, "  initial time of transfer %010lld, rate %f...\n",
746                 m_time_of_transfer, rate);
747
748     // FIXME: ideally we'd want the SP itself to account for the xmit_prebuffer_frames
749     // but that would also require to use a different approach to setting the initial TSP's
750     int64_t delay_in_ticks = (int64_t)(((float)((m_nb_buffers-1) * m_period + xmit_prebuffer_frames)) * rate);
751
752     // then use this information to initialize the xmit handlers
753
754     //  we now set the buffer tail timestamp of the transmit buffer
755     //  to the period transfer time instant plus what's nb_buffers - 1
756     //  in ticks. This due to the fact that we (should) have received one period
757     //  worth of ticks at t = m_time_of_transfer
758     //  hence one period of frames should also have been transmitted, which means
759     //  that there should be (nb_buffers - 1) * periodsize of frames in the xmit buffer
760     //  there are also xmit_prebuffer_frames frames extra present in the buffer
761     //  that allows us to calculate the tail timestamp for the buffer.
762
763     int64_t transmit_tail_timestamp = addTicks(m_time_of_transfer, delay_in_ticks);
764     debugOutput( DEBUG_LEVEL_VERBOSE, "  preset transmit tail TS %010lld, rate %f...\n",
765                 transmit_tail_timestamp, rate);
766
767     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
768         it != m_TransmitProcessors.end();
769         ++it ) {
770         (*it)->setTicksPerFrame(rate);
771         (*it)->setBufferTailTimestamp(transmit_tail_timestamp);
772         ffado_timestamp_t ts;
773         signed int fc;
774         (*it)->getBufferHeadTimestamp ( &ts, &fc );
775         debugOutput( DEBUG_LEVEL_VERBOSE, "   => transmit head TS %010lld, fc=%d...\n",
776                     (uint64_t)ts, fc);
777     }
778
779     // align the received streams to be phase aligned
780     if(!alignReceivedStreams()) {
781         debugError("Could not align streams...\n");
782         return false;
783     }
784
785     debugOutput( DEBUG_LEVEL_VERBOSE, " StreamProcessor streams running...\n");
786     return true;
787 }
788
789 bool
790 StreamProcessorManager::alignReceivedStreams()
791 {
792     debugOutput( DEBUG_LEVEL_VERBOSE, "Aligning received streams...\n");
793     unsigned int nb_sync_runs;
794     unsigned int nb_rcv_sp = m_ReceiveProcessors.size();
795     int64_t diff_between_streams[nb_rcv_sp];
796     int64_t diff;
797
798     unsigned int i;
799
800     int cnt = STREAMPROCESSORMANAGER_NB_ALIGN_TRIES;
801     int align_average_time_msec = STREAMPROCESSORMANAGER_ALIGN_AVERAGE_TIME_MSEC;
802     Util::Configuration &config = m_parent.getConfiguration();
803     config.getValueForSetting("streaming.spm.align_tries", cnt);
804     config.getValueForSetting("streaming.spm.align_average_time_msec", align_average_time_msec);
805
806     unsigned int periods_per_align_try = (align_average_time_msec * getNominalRate());
807     periods_per_align_try /= 1000;
808     periods_per_align_try /= getPeriodSize();
809     debugOutput( DEBUG_LEVEL_VERBOSE, " averaging over %u periods...\n", periods_per_align_try);
810
811     bool aligned = false;
812     while (!aligned && cnt--) {
813         nb_sync_runs = periods_per_align_try;
814         while(nb_sync_runs) {
815             debugOutput( DEBUG_LEVEL_VERY_VERBOSE, " check (%d)...\n", nb_sync_runs);
816             if(!waitForPeriod()) {
817                 debugWarning("xrun while aligning streams...\n");
818                 return false;
819             }
820
821             // before we do anything else, transfer
822             if(!transferSilence()) {
823                 debugError("Could not transfer silence\n");
824                 return false;
825             }
826
827             // now calculate the stream offset
828             i = 0;
829             for ( i = 0; i < nb_rcv_sp; i++) {
830                 StreamProcessor *s = m_ReceiveProcessors.at(i);
831                 diff = diffTicks(m_SyncSource->getTimeAtPeriod(), s->getTimeAtPeriod());
832                 debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "  offset between SyncSP %p and SP %p is %lld ticks...\n",
833                     m_SyncSource, s, diff);
834                 if ( nb_sync_runs == periods_per_align_try ) {
835                     diff_between_streams[i] = diff;
836                 } else {
837                     diff_between_streams[i] += diff;
838                 }
839             }
840
841             nb_sync_runs--;
842         }
843         // calculate the average offsets
844         debugOutput( DEBUG_LEVEL_VERBOSE, " Average offsets:\n");
845         int diff_between_streams_frames[nb_rcv_sp];
846         aligned = true;
847         for ( i = 0; i < nb_rcv_sp; i++) {
848             StreamProcessor *s = m_ReceiveProcessors.at(i);
849
850             diff_between_streams[i] /= periods_per_align_try;
851             diff_between_streams_frames[i] = (int)roundf(diff_between_streams[i] / s->getTicksPerFrame());
852             debugOutput( DEBUG_LEVEL_VERBOSE, "   avg offset between SyncSP %p and SP %p is %lld ticks, %d frames...\n",
853                 m_SyncSource, s, diff_between_streams[i], diff_between_streams_frames[i]);
854
855             aligned &= (diff_between_streams_frames[i] == 0);
856
857             // reposition the stream
858             if(!s->shiftStream(diff_between_streams_frames[i])) {
859                 debugError("Could not shift SP %p %d frames\n", s, diff_between_streams_frames[i]);
860                 return false;
861             }
862         }
863         if (!aligned) {
864             debugOutput(DEBUG_LEVEL_VERBOSE, "Streams not aligned, doing new round...\n");
865         }
866     }
867     if (cnt == 0) {
868         debugError("Align failed\n");
869         return false;
870     }
871     return true;
872 }
873
874 bool StreamProcessorManager::start() {
875     debugOutput( DEBUG_LEVEL_VERBOSE, "Starting Processors...\n");
876
877     // start all SP's synchonized
878     bool start_result = false;
879     for (int ntries=0; ntries < STREAMPROCESSORMANAGER_SYNCSTART_TRIES; ntries++) {
880         // put all SP's into dry-running state
881         if (!startDryRunning()) {
882             debugOutput(DEBUG_LEVEL_VERBOSE, "Could not put SP's in dry-running state (try %d)\n", ntries);
883             start_result = false;
884             continue;
885         }
886
887         start_result = syncStartAll();
888         if(start_result) {
889             break;
890         } else {
891             debugOutput(DEBUG_LEVEL_VERBOSE, "Sync start try %d failed...\n", ntries);
892             if(m_shutdown_needed) {
893                 debugOutput(DEBUG_LEVEL_VERBOSE, "Some fatal error occurred, stop trying.\n");
894                 return false;
895             }
896         }
897     }
898     if (!start_result) {
899         debugFatal("Could not syncStartAll...\n");
900         return false;
901     }
902     debugOutput( DEBUG_LEVEL_VERBOSE, " Started...\n");
903     return true;
904 }
905
906 bool StreamProcessorManager::stop() {
907     debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping...\n");
908
909     debugOutput( DEBUG_LEVEL_VERBOSE, " scheduling stop for all SP's...\n");
910     // switch SP's over to the dry-running state
911     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
912           it != m_ReceiveProcessors.end();
913           ++it ) {
914         if((*it)->isRunning()) {
915             if(!(*it)->scheduleStopRunning(-1)) {
916                 debugError("%p->scheduleStopRunning(-1) failed\n", *it);
917                 return false;
918             }
919         }
920     }
921     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
922           it != m_TransmitProcessors.end();
923           ++it ) {
924         if((*it)->isRunning()) {
925             if(!(*it)->scheduleStopRunning(-1)) {
926                 debugError("%p->scheduleStopRunning(-1) failed\n", *it);
927                 return false;
928             }
929         }
930     }
931     // wait for the SP's to get into the dry-running/stopped state
932     int cnt = 8000;
933     bool ready = false;
934     while (!ready && cnt) {
935         ready = true;
936         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
937             it != m_ReceiveProcessors.end();
938             ++it ) {
939             ready &= ((*it)->isDryRunning() || (*it)->isStopped() || (*it)->isWaitingForStream() || (*it)->inError());
940         }
941         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
942             it != m_TransmitProcessors.end();
943             ++it ) {
944             ready &= ((*it)->isDryRunning() || (*it)->isStopped() || (*it)->isWaitingForStream() || (*it)->inError());
945         }
946         SleepRelativeUsec(125);
947         cnt--;
948     }
949     if(cnt==0) {
950         debugWarning(" Timeout waiting for the SP's to start dry-running\n");
951         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
952             it != m_ReceiveProcessors.end();
953             ++it ) {
954             (*it)->dumpInfo();
955         }
956         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
957             it != m_TransmitProcessors.end();
958             ++it ) {
959             (*it)->dumpInfo();
960         }
961         return false;
962     }
963
964     // switch SP's over to the stopped state
965     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
966           it != m_ReceiveProcessors.end();
967           ++it ) {
968         if ((*it)->inError()) {
969             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %p in error state\n", *it);
970         } else if(!(*it)->scheduleStopDryRunning(-1)) {
971             debugError("%p->scheduleStopDryRunning(-1) failed\n", *it);
972             return false;
973         }
974     }
975     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
976           it != m_TransmitProcessors.end();
977           ++it ) {
978         if ((*it)->inError()) {
979             debugOutput(DEBUG_LEVEL_VERBOSE, "SP %p in error state\n", *it);
980         } else if(!(*it)->scheduleStopDryRunning(-1)) {
981             debugError("%p->scheduleStopDryRunning(-1) failed\n", *it);
982             return false;
983         }
984     }
985     // wait for the SP's to get into the stopped state
986     cnt = 8000;
987     ready = false;
988     while (!ready && cnt) {
989         ready = true;
990         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
991             it != m_ReceiveProcessors.end();
992             ++it ) {
993             ready &= ((*it)->isStopped() || (*it)->inError());
994         }
995         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
996             it != m_TransmitProcessors.end();
997             ++it ) {
998             ready &= ((*it)->isStopped() || (*it)->inError());
999         }
1000         SleepRelativeUsec(125);
1001         cnt--;
1002     }
1003     if(cnt==0) {
1004         debugWarning(" Timeout waiting for the SP's to stop\n");
1005         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1006             it != m_ReceiveProcessors.end();
1007             ++it ) {
1008             (*it)->dumpInfo();
1009         }
1010         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1011             it != m_TransmitProcessors.end();
1012             ++it ) {
1013             (*it)->dumpInfo();
1014         }
1015         return false;
1016     }
1017     debugOutput( DEBUG_LEVEL_VERBOSE, " Stopped...\n");
1018     return true;
1019 }
1020
1021 /**
1022  * Called upon Xrun events. This brings all StreamProcessors back
1023  * into their starting state, and then carries on streaming. This should
1024  * have the same effect as restarting the whole thing.
1025  *
1026  * @return true if successful, false otherwise
1027  */
1028 bool StreamProcessorManager::handleXrun() {
1029
1030     debugOutput( DEBUG_LEVEL_VERBOSE, "Handling Xrun ...\n");
1031
1032     dumpInfo();
1033
1034     /*
1035      * Reset means:
1036      * 1) Disabling the SP's, so that they don't process any packets
1037      *    note: the isomanager does keep on delivering/requesting them
1038      * 2) Bringing all buffers & streamprocessors into a know state
1039      *    - Clear all capture buffers
1040      *    - Put nb_periods*period_size of null frames into the playback buffers
1041      * 3) Re-enable the SP's
1042      */
1043
1044     debugOutput( DEBUG_LEVEL_VERBOSE, "Restarting StreamProcessors...\n");
1045     // start all SP's synchonized
1046     bool start_result = false;
1047     for (int ntries=0; ntries < STREAMPROCESSORMANAGER_SYNCSTART_TRIES; ntries++) {
1048         if(m_shutdown_needed) {
1049             debugOutput(DEBUG_LEVEL_VERBOSE, "Shutdown requested...\n");
1050             return true;
1051         }
1052         // put all SP's into dry-running state
1053         if (!startDryRunning()) {
1054             debugShowBackLog();
1055             debugOutput(DEBUG_LEVEL_VERBOSE, "Could not put SP's in dry-running state (try %d)\n", ntries);
1056             start_result = false;
1057             continue;
1058         }
1059
1060         start_result = syncStartAll();
1061         if(start_result) {
1062             break;
1063         } else {
1064             debugOutput(DEBUG_LEVEL_VERBOSE, "Sync start try %d failed...\n", ntries);
1065         }
1066     }
1067     if (!start_result) {
1068         debugFatal("Could not syncStartAll...\n");
1069         return false;
1070     }
1071     debugOutput( DEBUG_LEVEL_VERBOSE, "Xrun handled...\n");
1072
1073     return true;
1074 }
1075
1076 /**
1077  * @brief Waits until the next period of samples is ready
1078  *
1079  * This function does not return until a full period of samples is (or should be)
1080  * ready to be transferred.
1081  *
1082  * @return true if the period is ready, false if not
1083  */
1084 bool StreamProcessorManager::waitForPeriod() {
1085     if(m_SyncSource == NULL) return false;
1086     if(m_shutdown_needed) return false;
1087     bool xrun_occurred = false;
1088     bool in_error = false;
1089
1090     // grab the wait lock
1091     // this ensures that bus reset handling doesn't interfere
1092     Util::MutexLockHelper lock(*m_WaitLock);
1093     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
1094                         "waiting for period (%d frames in buffer)...\n",
1095                         m_SyncSource->getBufferFill());
1096     uint64_t ticks_at_period = m_SyncSource->getTimeAtPeriod();
1097     uint64_t ticks_at_period_margin = ticks_at_period + m_sync_delay;
1098     uint64_t pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(ticks_at_period_margin);
1099
1100     #ifdef DEBUG
1101     int64_t now = Util::SystemTimeSource::getCurrentTime();
1102     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "CTR  pred: %lld, syncdelay: %lld, diff: %lld\n", ticks_at_period, ticks_at_period_margin, ticks_at_period_margin-ticks_at_period );
1103     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "PREWAIT  pred: %lld, now: %lld, wait: %lld\n", pred_system_time_at_xfer, now, pred_system_time_at_xfer-now );
1104     #endif
1105
1106     // wait until it's time to transfer
1107     Util::SystemTimeSource::SleepUsecAbsolute(pred_system_time_at_xfer);
1108
1109     #ifdef DEBUG
1110     now = Util::SystemTimeSource::getCurrentTime();
1111     debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "POSTWAIT pred: %lld, now: %lld, excess: %lld\n", pred_system_time_at_xfer, now, now-pred_system_time_at_xfer );
1112     #endif
1113
1114     // the period should be ready now
1115     #ifdef DEBUG
1116     int rcv_fills[10];
1117     int xmt_fills[10];
1118     int i;
1119     i=0;
1120     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1121         it != m_ReceiveProcessors.end();
1122         ++it ) {
1123         rcv_fills[i] = (*it)->getBufferFill();
1124         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "RECV SP %p bufferfill: %05d\n", *it, rcv_fills[i]);
1125         i++;
1126     }
1127     i=0;
1128     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1129         it != m_TransmitProcessors.end();
1130         ++it ) {
1131         xmt_fills[i] = (*it)->getBufferFill();
1132         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "XMIT SP %p bufferfill: %05d\n", *it, xmt_fills[i]);
1133         i++;
1134     }
1135     for(i=0;i<1;i++) {
1136         debugOutputExtreme(DEBUG_LEVEL_VERBOSE, "SP %02d RECV: %05d [%05d] XMIT: %05d [%05d] DIFF: %05d\n", i,
1137                     rcv_fills[i], rcv_fills[i] - m_period,
1138                     xmt_fills[i], xmt_fills[i] - m_period,
1139                     rcv_fills[i] - xmt_fills[i]);
1140     }
1141     #endif
1142
1143     #if STREAMPROCESSORMANAGER_ALLOW_DELAYED_PERIOD_SIGNAL
1144     // HACK: we force wait until every SP is ready. this is needed
1145     // since the raw1394 interface provides no control over interrupts
1146     // resulting in very bad predictability on when the data is present.
1147     bool period_not_ready = true;
1148     while(period_not_ready) {
1149         period_not_ready = false;
1150         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1151             it != m_ReceiveProcessors.end();
1152             ++it ) {
1153             bool this_sp_period_ready = (*it)->canConsumePeriod();
1154             if (!this_sp_period_ready) {
1155                 period_not_ready = true;
1156             }
1157         }
1158         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1159             it != m_TransmitProcessors.end();
1160             ++it ) {
1161             bool this_sp_period_ready = (*it)->canProducePeriod();
1162             if (!this_sp_period_ready) {
1163                 period_not_ready = true;
1164             }
1165         }
1166
1167         if (period_not_ready) {
1168             debugOutput(DEBUG_LEVEL_VERBOSE, " wait extended since period not ready...\n");
1169             Util::SystemTimeSource::SleepUsecRelative(125); // one cycle
1170         }
1171
1172         // check for underruns/errors on the ISO side,
1173         // those should make us bail out of the wait loop
1174         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1175             it != m_ReceiveProcessors.end();
1176             ++it ) {
1177             // a xrun has occurred on the Iso side
1178             xrun_occurred |= (*it)->xrunOccurred();
1179             in_error |= (*it)->inError();
1180         }
1181         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1182             it != m_TransmitProcessors.end();
1183             ++it ) {
1184             // a xrun has occurred on the Iso side
1185             xrun_occurred |= (*it)->xrunOccurred();
1186             in_error |= (*it)->inError();
1187         }
1188         if(xrun_occurred | in_error | m_shutdown_needed) break;
1189     }
1190     #else
1191     // check for underruns/errors on the ISO side,
1192     // those should make us bail out of the wait loop
1193     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1194         it != m_ReceiveProcessors.end();
1195         ++it ) {
1196         // xrun on data buffer side
1197         if (!(*it)->canConsumePeriod()) {
1198             xrun_occurred = true;
1199         }
1200         // a xrun has occurred on the Iso side
1201         xrun_occurred |= (*it)->xrunOccurred();
1202         in_error |= (*it)->inError();
1203     }
1204     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1205         it != m_TransmitProcessors.end();
1206         ++it ) {
1207         // xrun on data buffer side
1208         if (!(*it)->canProducePeriod()) {
1209             xrun_occurred = true;
1210         }
1211         // a xrun has occurred on the Iso side
1212         xrun_occurred |= (*it)->xrunOccurred();
1213         in_error |= (*it)->inError();
1214     }
1215     #endif
1216
1217     if(xrun_occurred) {
1218         debugOutput( DEBUG_LEVEL_VERBOSE, "exit due to xrun...\n");
1219     }
1220     if(in_error) {
1221         debugOutput( DEBUG_LEVEL_VERBOSE, "exit due to error...\n");
1222         m_shutdown_needed = true;
1223     }
1224
1225     // we save the 'ideal' time of the transfer at this point,
1226     // because we can have interleaved read - process - write
1227     // cycles making that we modify a receiving stream's buffer
1228     // before we get to writing.
1229     // NOTE: before waitForPeriod() is called again, both the transmit
1230     //       and the receive processors should have done their transfer.
1231     m_time_of_transfer = m_SyncSource->getTimeAtPeriod();
1232    
1233     #ifdef DEBUG
1234     int ticks_per_period = (int)(m_SyncSource->getTicksPerFrame() * m_period);
1235    
1236     int diff = diffTicks(m_time_of_transfer, m_time_of_transfer2);
1237     // display message if the difference between two successive tick
1238     // values is more than 50 ticks. 1 sample at 48k is 512 ticks
1239     // so 50 ticks = 10%, which is a rather large jitter value.
1240     if(diff-ticks_per_period > 50 || diff-ticks_per_period < -50) {
1241         debugOutput(DEBUG_LEVEL_VERBOSE, "rather large TSP difference TS=%011llu => TS=%011llu (%d, nom %d)\n",
1242                                             m_time_of_transfer2, m_time_of_transfer, diff, ticks_per_period);
1243     }
1244     m_time_of_transfer2 = m_time_of_transfer;
1245     #endif
1246
1247     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
1248                         "transfer period %d at %llu ticks...\n",
1249                         m_nbperiods, m_time_of_transfer);
1250
1251     #ifdef DEBUG
1252     int rcv_bf=0, xmt_bf=0;
1253     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1254         it != m_ReceiveProcessors.end();
1255         ++it ) {
1256         rcv_bf = (*it)->getBufferFill();
1257     }
1258     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1259         it != m_TransmitProcessors.end();
1260         ++it ) {
1261         xmt_bf = (*it)->getBufferFill();
1262     }
1263     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE,
1264                         "XF at %011llu ticks, RBF=%d, XBF=%d, SUM=%d...\n",
1265                         m_time_of_transfer, rcv_bf, xmt_bf, rcv_bf+xmt_bf);
1266
1267     // check if xruns occurred on the Iso side.
1268     // also check if xruns will occur should we transfer() now
1269     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1270           it != m_ReceiveProcessors.end();
1271           ++it ) {
1272
1273         if ((*it)->xrunOccurred()) {
1274             debugOutput(DEBUG_LEVEL_NORMAL,
1275                         "Xrun on RECV SP %p due to ISO side xrun\n", *it);
1276             (*it)->dumpInfo();
1277         }
1278         if (!((*it)->canClientTransferFrames(m_period))) {
1279             debugOutput(DEBUG_LEVEL_NORMAL,
1280                         "Xrun on RECV SP %p due to buffer side xrun\n", *it);
1281             (*it)->dumpInfo();
1282         }
1283     }
1284     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1285           it != m_TransmitProcessors.end();
1286           ++it ) {
1287         if ((*it)->xrunOccurred()) {
1288             debugOutput(DEBUG_LEVEL_NORMAL,
1289                         "Xrun on XMIT SP %p due to ISO side xrun\n", *it);
1290         }
1291         if (!((*it)->canClientTransferFrames(m_period))) {
1292             debugOutput(DEBUG_LEVEL_NORMAL,
1293                         "Xrun on XMIT SP %p due to buffer side xrun\n", *it);
1294         }
1295     }
1296     #endif
1297     m_nbperiods++;
1298
1299     // this is to notify the client of the delay that we introduced by waiting
1300     pred_system_time_at_xfer = m_SyncSource->getParent().get1394Service().getSystemTimeForCycleTimerTicks(m_time_of_transfer);
1301
1302     m_delayed_usecs = Util::SystemTimeSource::getCurrentTime() - pred_system_time_at_xfer;
1303     debugOutputExtreme(DEBUG_LEVEL_VERBOSE,
1304                         "delayed for %d usecs...\n",
1305                         m_delayed_usecs);
1306
1307     // now we can signal the client that we are (should be) ready
1308     return !xrun_occurred;
1309 }
1310
1311 /**
1312  * @brief Transfer one period of frames for both receive and transmit StreamProcessors
1313  *
1314  * Transfers one period of frames from the client side to the Iso side and vice versa.
1315  *
1316  * @return true if successful, false otherwise (indicates xrun).
1317  */
1318 bool StreamProcessorManager::transfer() {
1319     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
1320     bool retval=true;
1321     retval &= transfer(StreamProcessor::ePT_Receive);
1322     retval &= transfer(StreamProcessor::ePT_Transmit);
1323     return retval;
1324 }
1325
1326 /**
1327  * @brief Transfer one period of frames for either the receive or transmit StreamProcessors
1328  *
1329  * Transfers one period of frames from the client side to the Iso side or vice versa.
1330  *
1331  * @param t The processor type to tranfer for (receive or transmit)
1332  * @return true if successful, false otherwise (indicates xrun).
1333  */
1334 bool StreamProcessorManager::transfer(enum StreamProcessor::eProcessorType t) {
1335     if(m_SyncSource == NULL) return false;
1336     debugOutputExtreme( DEBUG_LEVEL_VERY_VERBOSE,
1337         "transfer(%d) at TS=%011llu (%03us %04uc %04ut)...\n",
1338         t, m_time_of_transfer,
1339         (unsigned int)TICKS_TO_SECS(m_time_of_transfer),
1340         (unsigned int)TICKS_TO_CYCLES(m_time_of_transfer),
1341         (unsigned int)TICKS_TO_OFFSET(m_time_of_transfer));
1342
1343     bool retval = true;
1344     // a static cast could make sure that there is no performance
1345     // penalty for the virtual functions (to be checked)
1346     if (t==StreamProcessor::ePT_Receive) {
1347         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1348                 it != m_ReceiveProcessors.end();
1349                 ++it ) {
1350             if(!(*it)->getFrames(m_period, m_time_of_transfer)) {
1351                     debugWarning("could not getFrames(%u, %11llu) from stream processor (%p)\n",
1352                             m_period, m_time_of_transfer,*it);
1353                 retval &= false; // buffer underrun
1354             }
1355         }
1356     } else {
1357         // FIXME: in the SPM it would be nice to have system time instead of
1358         //        1394 time
1359         float rate = m_SyncSource->getTicksPerFrame();
1360
1361         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1362                 it != m_TransmitProcessors.end();
1363                 ++it ) {
1364             // this is the delay in frames between the point where a frame is received and
1365             // when it is transmitted again
1366             unsigned int one_ringbuffer_in_frames = m_nb_buffers * m_period + (*it)->getExtraBufferFrames();
1367             int64_t one_ringbuffer_in_ticks = (int64_t)(((float)one_ringbuffer_in_frames) * rate);
1368    
1369             // the data we are putting into the buffer is intended to be transmitted
1370             // one ringbuffer size after it has been received
1371             int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks);
1372
1373             if(!(*it)->putFrames(m_period, transmit_timestamp)) {
1374                 debugWarning("could not putFrames(%u,%llu) to stream processor (%p)\n",
1375                         m_period, transmit_timestamp, *it);
1376                 retval &= false; // buffer underrun
1377             }
1378         }
1379     }
1380     return retval;
1381 }
1382
1383 /**
1384  * @brief Transfer one period of silence for both receive and transmit StreamProcessors
1385  *
1386  * Transfers one period of silence to the Iso side for transmit SP's
1387  * or dump one period of frames for receive SP's
1388  *
1389  * @return true if successful, false otherwise (indicates xrun).
1390  */
1391 bool StreamProcessorManager::transferSilence() {
1392     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Transferring silent period...\n");
1393     bool retval=true;
1394     // NOTE: the order here is opposite from the order in
1395     // normal operation (transmit is before receive), because
1396     // we can do that here (data=silence=available) and
1397     // it increases reliability (esp. on startup)
1398     retval &= transferSilence(StreamProcessor::ePT_Transmit);
1399     retval &= transferSilence(StreamProcessor::ePT_Receive);
1400     return retval;
1401 }
1402
1403 /**
1404  * @brief Transfer one period of silence for either the receive or transmit StreamProcessors
1405  *
1406  * Transfers one period of silence to the Iso side for transmit SP's
1407  * or dump one period of frames for receive SP's
1408  *
1409  * @param t The processor type to tranfer for (receive or transmit)
1410  * @return true if successful, false otherwise (indicates xrun).
1411  */
1412 bool StreamProcessorManager::transferSilence(enum StreamProcessor::eProcessorType t) {
1413     if(m_SyncSource == NULL) return false;
1414     debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
1415         "transferSilence(%d) at TS=%011llu (%03us %04uc %04ut)...\n",
1416         t, m_time_of_transfer,
1417         (unsigned int)TICKS_TO_SECS(m_time_of_transfer),
1418         (unsigned int)TICKS_TO_CYCLES(m_time_of_transfer),
1419         (unsigned int)TICKS_TO_OFFSET(m_time_of_transfer));
1420
1421     bool retval = true;
1422     // a static cast could make sure that there is no performance
1423     // penalty for the virtual functions (to be checked)
1424     if (t==StreamProcessor::ePT_Receive) {
1425         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1426                 it != m_ReceiveProcessors.end();
1427                 ++it ) {
1428             if(!(*it)->dropFrames(m_period, m_time_of_transfer)) {
1429                     debugWarning("could not dropFrames(%u, %11llu) from stream processor (%p)\n",
1430                             m_period, m_time_of_transfer,*it);
1431                 retval &= false; // buffer underrun
1432             }
1433         }
1434     } else {
1435         // FIXME: in the SPM it would be nice to have system time instead of
1436         //        1394 time
1437         float rate = m_SyncSource->getTicksPerFrame();
1438
1439         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1440                 it != m_TransmitProcessors.end();
1441                 ++it ) {
1442             // this is the delay in frames between the point where a frame is received and
1443             // when it is transmitted again
1444             unsigned int one_ringbuffer_in_frames = m_nb_buffers * m_period + (*it)->getExtraBufferFrames();
1445             int64_t one_ringbuffer_in_ticks = (int64_t)(((float)one_ringbuffer_in_frames) * rate);
1446    
1447             // the data we are putting into the buffer is intended to be transmitted
1448             // one ringbuffer size after it has been received
1449             int64_t transmit_timestamp = addTicks(m_time_of_transfer, one_ringbuffer_in_ticks);
1450
1451             if(!(*it)->putSilenceFrames(m_period, transmit_timestamp)) {
1452                 debugWarning("could not putSilenceFrames(%u,%llu) to stream processor (%p)\n",
1453                         m_period, transmit_timestamp, *it);
1454                 retval &= false; // buffer underrun
1455             }
1456         }
1457     }
1458     return retval;
1459 }
1460
1461 void StreamProcessorManager::dumpInfo() {
1462     debugOutputShort( DEBUG_LEVEL_NORMAL, "----------------------------------------------------\n");
1463     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping StreamProcessorManager information...\n");
1464     debugOutputShort( DEBUG_LEVEL_NORMAL, "Period count: %6d\n", m_nbperiods);
1465     debugOutputShort( DEBUG_LEVEL_NORMAL, "Data type: %s\n", (m_audio_datatype==eADT_Float?"float":"int24"));
1466
1467     debugOutputShort( DEBUG_LEVEL_NORMAL, " Receive processors...\n");
1468     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1469         it != m_ReceiveProcessors.end();
1470         ++it ) {
1471         (*it)->dumpInfo();
1472     }
1473
1474     debugOutputShort( DEBUG_LEVEL_NORMAL, " Transmit processors...\n");
1475     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1476         it != m_TransmitProcessors.end();
1477         ++it ) {
1478         (*it)->dumpInfo();
1479     }
1480
1481     debugOutputShort( DEBUG_LEVEL_NORMAL, "----------------------------------------------------\n");
1482
1483     // list port info in verbose mode
1484     debugOutputShort( DEBUG_LEVEL_VERBOSE, "Port Information\n");
1485     int nb_ports;
1486    
1487     debugOutputShort( DEBUG_LEVEL_VERBOSE, " Playback\n");
1488     nb_ports = getPortCount(Port::E_Playback);
1489     for(int i=0; i < nb_ports; i++) {
1490         Port *p = getPortByIndex(i, Port::E_Playback);
1491         debugOutputShort( DEBUG_LEVEL_VERBOSE, "  %3d (%p): ", i, p);
1492         if (p) {
1493             bool disabled = p->isDisabled();
1494             debugOutputShort( DEBUG_LEVEL_VERBOSE, "[%p] [%3s] ", &p->getManager(), (disabled?"off":"on"));
1495             debugOutputShort( DEBUG_LEVEL_VERBOSE, "[%7s] ", p->getPortTypeName().c_str());
1496             debugOutputShort( DEBUG_LEVEL_VERBOSE, "%3s ", p->getName().c_str());
1497         } else {
1498             debugOutputShort( DEBUG_LEVEL_VERBOSE, "invalid ");
1499         }
1500         debugOutputShort( DEBUG_LEVEL_VERBOSE, "\n");
1501     }
1502     debugOutputShort( DEBUG_LEVEL_VERBOSE, " Capture\n");
1503     nb_ports = getPortCount(Port::E_Capture);
1504     for(int i=0; i < nb_ports; i++) {
1505         Port *p = getPortByIndex(i, Port::E_Capture);
1506         debugOutputShort( DEBUG_LEVEL_VERBOSE, "  %3d (%p): ", i, p);
1507         if (p) {
1508             bool disabled = p->isDisabled();
1509             debugOutputShort( DEBUG_LEVEL_VERBOSE, "[%p] [%3s] ", &p->getManager(), (disabled?"off":"on"));
1510             debugOutputShort( DEBUG_LEVEL_VERBOSE, "[%7s] ", p->getPortTypeName().c_str());
1511             debugOutputShort( DEBUG_LEVEL_VERBOSE, " %3s ", p->getName().c_str());
1512         } else {
1513             debugOutputShort( DEBUG_LEVEL_VERBOSE, " invalid ");
1514         }
1515         debugOutputShort( DEBUG_LEVEL_VERBOSE, "\n");
1516     }
1517
1518     debugOutputShort( DEBUG_LEVEL_VERBOSE, "----------------------------------------------------\n");
1519
1520 }
1521
1522 void StreamProcessorManager::setVerboseLevel(int l) {
1523     if(m_WaitLock) m_WaitLock->setVerboseLevel(l);
1524
1525     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1526         it != m_ReceiveProcessors.end();
1527         ++it ) {
1528         (*it)->setVerboseLevel(l);
1529     }
1530     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1531         it != m_TransmitProcessors.end();
1532         ++it ) {
1533         (*it)->setVerboseLevel(l);
1534     }
1535     setDebugLevel(l);
1536     debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
1537 }
1538
1539 int StreamProcessorManager::getPortCount(enum Port::E_PortType type, enum Port::E_Direction direction) {
1540     int count=0;
1541
1542     if (direction == Port::E_Capture) {
1543         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1544             it != m_ReceiveProcessors.end();
1545             ++it ) {
1546             count += (*it)->getPortCount(type);
1547         }
1548     } else {
1549         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1550             it != m_TransmitProcessors.end();
1551             ++it ) {
1552             count += (*it)->getPortCount(type);
1553         }
1554     }
1555     return count;
1556 }
1557
1558 int StreamProcessorManager::getPortCount(enum Port::E_Direction direction) {
1559     int count=0;
1560
1561     if (direction == Port::E_Capture) {
1562         for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1563             it != m_ReceiveProcessors.end();
1564             ++it ) {
1565             count += (*it)->getPortCount();
1566         }
1567     } else {
1568         for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1569             it != m_TransmitProcessors.end();
1570             ++it ) {
1571             count += (*it)->getPortCount();
1572         }
1573     }
1574     return count;
1575 }
1576
1577 void
1578 StreamProcessorManager::updateShadowLists()
1579 {
1580     debugOutput( DEBUG_LEVEL_VERBOSE, "Updating port shadow lists...\n");
1581     m_CapturePorts_shadow.clear();
1582     m_PlaybackPorts_shadow.clear();
1583
1584     for ( StreamProcessorVectorIterator it = m_ReceiveProcessors.begin();
1585         it != m_ReceiveProcessors.end();
1586         ++it ) {
1587         PortManager *pm = *it;
1588         for (int i=0; i < pm->getPortCount(); i++) {
1589             Port *p = pm->getPortAtIdx(i);
1590             if (!p) {
1591                 debugError("getPortAtIdx(%d) returned NULL\n", i);
1592                 continue;
1593             }
1594             if(p->getDirection() != Port::E_Capture) {
1595                 debugError("port at idx %d for receive SP is not a capture port!\n", i);
1596                 continue;
1597             }
1598             m_CapturePorts_shadow.push_back(p);
1599         }
1600     }
1601     for ( StreamProcessorVectorIterator it = m_TransmitProcessors.begin();
1602         it != m_TransmitProcessors.end();
1603         ++it ) {
1604         PortManager *pm = *it;
1605         for (int i=0; i < pm->getPortCount(); i++) {
1606             Port *p = pm->getPortAtIdx(i);
1607             if (!p) {
1608                 debugError("getPortAtIdx(%d) returned NULL\n", i);
1609                 continue;
1610             }
1611             if(p->getDirection() != Port::E_Playback) {
1612                 debugError("port at idx %d for transmit SP is not a playback port!\n", i);
1613                 continue;
1614             }
1615             m_PlaybackPorts_shadow.push_back(p);
1616         }
1617     }
1618 }
1619
1620 Port* StreamProcessorManager::getPortByIndex(int idx, enum Port::E_Direction direction) {
1621     debugOutputExtreme( DEBUG_LEVEL_ULTRA_VERBOSE, "getPortByIndex(%d, %d)...\n", idx, direction);
1622     if (direction == Port::E_Capture) {
1623         #ifdef DEBUG
1624         if(idx >= (int)m_CapturePorts_shadow.size()) {
1625             debugError("Capture port %d out of range (%d)\n", idx, m_CapturePorts_shadow.size());
1626             return NULL;
1627         }
1628         #endif
1629         return m_CapturePorts_shadow.at(idx);
1630     } else {
1631         #ifdef DEBUG
1632         if(idx >= (int)m_PlaybackPorts_shadow.size()) {
1633             debugError("Playback port %d out of range (%d)\n", idx, m_PlaybackPorts_shadow.size());
1634             return NULL;
1635         }
1636         #endif
1637         return m_PlaybackPorts_shadow.at(idx);
1638     }
1639     return NULL;
1640 }
1641
1642 bool StreamProcessorManager::setThreadParameters(bool rt, int priority) {
1643     m_thread_realtime=rt;
1644     m_thread_priority=priority;
1645     return true;
1646 }
1647
1648
1649 } // end of namespace
Note: See TracBrowser for help on using the browser.