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

Revision 1721, 65.0 kB (checked in by ppalmers, 14 years ago)

fix all format string warnings

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=%ld ts.sec=%ld ts.nsec=%ld\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=%ld ts.sec=%ld ts.nsec=%ld\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: %ld, 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: %ld, 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: %ld, 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=%011lu (%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 (%011lu ticks)...\n",
590         time_for_startup_frames, time_for_startup_ticks);
591
592     debugOutput( DEBUG_LEVEL_VERBOSE, "  => first sample at TS=%011lu (%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=%011lu (%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=%011lu (%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 %010ld => head TS %010lu, 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(%11lu) 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(%11lu) 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(%11lu) 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 %010ld, 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 %010ld, 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 %010ld, 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 %ld 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 %ld 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: %ld, 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: %ld, 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: %ld, 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=%011lu => TS=%011lu (%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 %lu 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 %011lu 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=%011lu (%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, %11lu) 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,%lu) 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=%011lu (%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, %11lu) 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,%lu) 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 (%lu)\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 (%lu)\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.