root/trunk/libffado/src/libieee1394/IsoHandlerManager.cpp

Revision 911, 26.0 kB (checked in by ppalmers, 13 years ago)

Fix compilation with extreme debugging enabled

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
24 #include "config.h"
25 #include "IsoHandlerManager.h"
26 #include "ieee1394service.h"
27 #include "IsoHandler.h"
28 #include "libstreaming/generic/StreamProcessor.h"
29
30 #include "libutil/Atomic.h"
31
32 #include "libutil/PosixThread.h"
33
34 #include "libutil/SystemTimeSource.h"
35
36 #include <assert.h>
37
38 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
39 IMPL_DEBUG_MODULE( IsoTask, IsoTask, DEBUG_LEVEL_NORMAL );
40
41 using namespace Streaming;
42
43 // --- ISO Thread --- //
44
45 IsoTask::IsoTask(IsoHandlerManager& manager, enum IsoTask::eTaskType t)
46     : m_manager( manager )
47     , m_type( t )
48 {
49 }
50
51 bool
52 IsoTask::Init()
53 {
54     request_update = 0;
55
56     int i;
57     for (i=0; i < ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT; i++) {
58         m_IsoHandler_map_shadow[i] = NULL;
59         m_poll_fds_shadow[i].events = 0;
60     }
61     m_poll_nfds_shadow = 0;
62     return true;
63 }
64
65 bool
66 IsoTask::requestShadowMapUpdate()
67 {
68     debugOutput(DEBUG_LEVEL_VERBOSE, "enter\n");
69     INC_ATOMIC(&request_update);
70     return true;
71 }
72
73 // updates the internal stream map
74 // note that this should be executed with the guarantee that
75 // nobody will modify
76 void
77 IsoTask::updateShadowMapHelper()
78 {
79     debugOutput( DEBUG_LEVEL_VERBOSE, "updating shadow vars...\n");
80     unsigned int i, cnt, max;
81     max = m_manager.m_IsoHandlers.size();
82     for (i = 0, cnt = 0; i < max; i++) {
83         IsoHandler *h = m_manager.m_IsoHandlers.at(i);
84         assert(h);
85
86         // skip handlers of the wrong type
87         if (h->getType() == IsoHandler::eHT_Receive  && m_type == eTT_Transmit) continue;
88         if (h->getType() == IsoHandler::eHT_Transmit && m_type == eTT_Receive) continue;
89
90         if (h->isEnabled()) {
91             m_IsoHandler_map_shadow[cnt] = h;
92             m_poll_fds_shadow[cnt].fd = h->getFileDescriptor();
93             m_poll_fds_shadow[cnt].revents = 0;
94             m_poll_fds_shadow[cnt].events = POLLIN;
95             cnt++;
96             debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p added\n", h->getTypeString(), h);
97         } else {
98             debugOutput( DEBUG_LEVEL_VERBOSE, "%s handler %p skipped (disabled)\n", h->getTypeString(), h);
99         }
100         if(cnt > ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT) {
101             debugWarning("Too much ISO Handlers in thread...\n");
102             break;
103         }
104     }
105     m_poll_nfds_shadow = cnt;
106     debugOutput( DEBUG_LEVEL_VERBOSE, " updated shadow vars...\n");
107 }
108
109 bool
110 IsoTask::Execute()
111 {
112     debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "Execute\n");
113     int err;
114     unsigned int i;
115     unsigned int m_poll_timeout = 10;
116
117     // if some other thread requested a shadow map update, do it
118     if(request_update) {
119         updateShadowMapHelper();
120         DEC_ATOMIC(&request_update); // ack the update
121     }
122
123     // bypass if no handlers are registered
124     if (m_poll_nfds_shadow == 0) {
125         debugOutput(DEBUG_LEVEL_VERY_VERBOSE, "bypass iterate since no handlers to poll\n");
126         usleep(m_poll_timeout * 1000);
127         return true;
128     }
129
130     // setup the poll here
131     if (m_type==eTT_Transmit) {
132         // if we are a transmit thread, we should only poll on
133         // those handlers that have a client that is ready to send
134         // something. poll'ing the others will only cause busy-wait
135         // looping.
136         for (i = 0; i < m_poll_nfds_shadow; i++) {
137             short events = 0;
138             if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) {
139                 events = POLLIN | POLLPRI;
140             }
141             m_poll_fds_shadow[i].events = events;
142         }
143     } else {
144         // for receive handlers, we can do the same. we might not have to though
145         // FIXME: check whether this is necessary
146         for (i = 0; i < m_poll_nfds_shadow; i++) {
147             short events = 0;
148 //             if (m_IsoHandler_map_shadow[i]->tryWaitForClient()) {
149 //                 events = POLLIN | POLLERR | POLLHUP;
150 //             }
151             events = POLLIN | POLLPRI;
152             m_poll_fds_shadow[i].events = events;
153         }
154     }
155
156     // Use a shadow map of the fd's such that the poll call is not in a critical section
157     err = poll (m_poll_fds_shadow, m_poll_nfds_shadow, m_poll_timeout);
158
159     if (err < 0) {
160         if (errno == EINTR) {
161             return true;
162         }
163         debugFatal("poll error: %s\n", strerror (errno));
164         return false;
165     }
166
167     for (i = 0; i < m_poll_nfds_shadow; i++) {
168         #ifdef DEBUG
169         if(m_poll_fds_shadow[i].revents) {
170             debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
171                         "received events: %08X for (%d/%d, %p, %s)\n",
172                         m_poll_fds_shadow[i].revents,
173                         i, m_poll_nfds_shadow,
174                         m_IsoHandler_map_shadow[i],
175                         m_IsoHandler_map_shadow[i]->getTypeString());
176         }
177         #endif
178
179         // if we get here, it means two things:
180         // 1) the kernel can accept or provide packets (poll returned POLLIN)
181         // 2) the client can provide or accept packets (we enabled polling)
182         if(m_poll_fds_shadow[i].revents & (POLLIN)) {
183             m_IsoHandler_map_shadow[i]->iterate();
184         } else {
185             // there might be some error condition
186             if (m_poll_fds_shadow[i].revents & POLLERR) {
187                 debugWarning("error on fd for %d\n",i);
188             }
189             if (m_poll_fds_shadow[i].revents & POLLHUP) {
190                 debugWarning("hangup on fd for %d\n",i);
191             }
192         }
193
194 //         #ifdef DEBUG
195 //         // check if the handler is still alive
196 //         if(m_IsoHandler_map_shadow[i]->isDead()) {
197 //             debugError("Iso handler (%p, %s) is dead!\n",
198 //                        m_IsoHandler_map_shadow[i],
199 //                        m_IsoHandler_map_shadow[i]->getTypeString());
200 //             return false; // shutdown the system
201 //         }
202 //         #endif
203
204     }
205                       nb_rcv, nb_xmit);
206
207     return true;
208
209 }
210
211 void IsoTask::setVerboseLevel(int i) {
212     setDebugLevel(i);
213 }
214
215 // -- the ISO handler manager -- //
216 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
217    : m_State(E_Created)
218    , m_service( service )
219    , m_realtime(false), m_priority(0)
220    , m_ReceiveThread ( NULL )
221    , m_TransmitThread ( NULL )
222    , m_ReceiveTask ( NULL )
223    , m_TransmitTask ( NULL )
224 {}
225
226 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
227    : m_State(E_Created)
228    , m_service( service )
229    , m_realtime(run_rt), m_priority(rt_prio)
230    , m_ReceiveThread ( NULL )
231    , m_TransmitThread ( NULL )
232    , m_ReceiveTask ( NULL )
233    , m_TransmitTask ( NULL )
234 {}
235
236 IsoHandlerManager::~IsoHandlerManager()
237 {
238     stopHandlers();
239     pruneHandlers();
240     if(m_IsoHandlers.size() > 0) {
241         debugError("Still some handlers in use\n");
242     }
243     if (m_ReceiveThread) {
244         m_ReceiveThread->Stop();
245         delete m_ReceiveThread;
246     }
247     if (m_ReceiveTask) {
248         delete m_ReceiveTask;
249     }
250
251     if (m_TransmitThread) {
252         m_TransmitThread->Stop();
253         delete m_TransmitThread;
254     }
255     if (m_TransmitTask) {
256         delete m_TransmitTask;
257     }
258 }
259
260 bool
261 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
262     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
263     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
264     m_realtime = rt;
265     m_priority = priority;
266     bool result = true;
267
268     if (m_ReceiveThread) {
269         if (m_realtime) {
270             m_ReceiveThread->AcquireRealTime(m_priority);
271         } else {
272             m_ReceiveThread->DropRealTime();
273         }
274     }
275     if (m_TransmitThread) {
276         if (m_realtime) {
277             m_TransmitThread->AcquireRealTime(m_priority);
278         } else {
279             m_TransmitThread->DropRealTime();
280         }
281     }
282
283     return result;
284 }
285
286 bool IsoHandlerManager::init()
287 {
288     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
289     // check state
290     if(m_State != E_Created) {
291         debugError("Manager already initialized...\n");
292         return false;
293     }
294
295     // create a thread to iterate our receive handlers
296     debugOutput( DEBUG_LEVEL_VERBOSE, "Create receive thread for %p...\n", this);
297     m_ReceiveTask = new IsoTask( *this, IsoTask::eTT_Receive );
298     if(!m_ReceiveTask) {
299         debugFatal("No task\n");
300         return false;
301     }
302     m_ReceiveThread = new Util::PosixThread(m_ReceiveTask, m_realtime,
303                                             m_priority + ISOHANDLERMANAGER_RECEIVE_PRIO_INCREASE,
304                                             PTHREAD_CANCEL_DEFERRED);
305
306     if(!m_ReceiveThread) {
307         debugFatal("No thread\n");
308         return false;
309     }
310     if (m_ReceiveThread->Start() != 0) {
311         debugFatal("Could not start receive thread\n");
312         return false;
313     }
314
315     // create a thread to iterate our transmit handlers
316     debugOutput( DEBUG_LEVEL_VERBOSE, "Create transmit thread for %p...\n", this);
317     m_TransmitTask = new IsoTask( *this, IsoTask::eTT_Transmit );
318     if(!m_TransmitTask) {
319         debugFatal("No task\n");
320         return false;
321     }
322     m_TransmitThread = new Util::PosixThread(m_TransmitTask, m_realtime,
323                                              m_priority + ISOHANDLERMANAGER_TRANSMIT_PRIO_INCREASE,
324                                              PTHREAD_CANCEL_DEFERRED);
325     if(!m_TransmitThread) {
326         debugFatal("No thread\n");
327         return false;
328     }
329     if (m_TransmitThread->Start() != 0) {
330         debugFatal("Could not start transmit thread\n");
331         return false;
332     }
333
334     m_State=E_Running;
335     return true;
336 }
337
338
339 bool
340 IsoHandlerManager::updateShadowMapFor(IsoHandler *h)
341 {
342     // update the shadow map
343     if(h->getType() == IsoHandler::eHT_Receive) {
344         if(!m_ReceiveTask->requestShadowMapUpdate()) {
345             debugError("failed to update shadow map\n");
346             return false;
347         }
348     } else {
349         if(!m_TransmitTask->requestShadowMapUpdate()) {
350             debugError("failed to update shadow map\n");
351             return false;
352         }
353     }
354     return true;
355 }
356
357 bool
358 IsoHandlerManager::disable(IsoHandler *h) {
359     bool result;
360     int i=0;
361     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
362     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
363         it != m_IsoHandlers.end();
364         ++it )
365     {
366         if ((*it) == h) {
367             result = h->disable();
368             result &= updateShadowMapFor(h);
369             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
370             return result;
371         }
372         i++;
373     }
374     debugError("Handler not found\n");
375     return false;
376 }
377
378 bool
379 IsoHandlerManager::enable(IsoHandler *h) {
380     bool result;
381     int i=0;
382     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
383     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
384         it != m_IsoHandlers.end();
385         ++it )
386     {
387         if ((*it) == h) {
388             result = h->enable();
389             result &= updateShadowMapFor(h);
390             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
391             return result;
392         }
393         i++;
394     }
395     debugError("Handler not found\n");
396     return false;
397 }
398
399 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
400 {
401     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
402     assert(handler);
403     handler->setVerboseLevel(getDebugLevel());
404     m_IsoHandlers.push_back(handler);
405     return updateShadowMapFor(handler);
406 }
407
408 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
409 {
410     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
411     assert(handler);
412
413     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
414       it != m_IsoHandlers.end();
415       ++it )
416     {
417         if ( *it == handler ) {
418             m_IsoHandlers.erase(it);
419             return updateShadowMapFor(handler);
420         }
421     }
422     debugFatal("Could not find handler (%p)\n", handler);
423     return false; //not found
424 }
425
426 /**
427  * Registers an StreamProcessor with the IsoHandlerManager.
428  *
429  * If nescessary, an IsoHandler is created to handle this stream.
430  * Once an StreamProcessor is registered to the handler, it will be included
431  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
432  *
433  * @param stream the stream to register
434  * @return true if registration succeeds
435  *
436  * \todo : currently there is a one-to-one mapping
437  *        between streams and handlers, this is not ok for
438  *        multichannel receive
439  */
440 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
441 {
442     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
443     assert(stream);
444
445     IsoHandler* h = NULL;
446
447     // make sure the stream isn't already attached to a handler
448     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
449       it != m_IsoHandlers.end();
450       ++it )
451     {
452         if((*it)->isStreamRegistered(stream)) {
453             debugError( "stream already registered!\n");
454             return false;
455         }
456     }
457
458     // clean up all handlers that aren't used
459     pruneHandlers();
460
461     // allocate a handler for this stream
462     if (stream->getType()==StreamProcessor::ePT_Receive) {
463         // setup the optimal parameters for the raw1394 ISO buffering
464         unsigned int packets_per_period = stream->getPacketsPerPeriod();
465         unsigned int max_packet_size = stream->getMaxPacketSize();
466         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
467
468         // Ensure we don't request a packet size bigger than the
469         // kernel-enforced maximum which is currently 1 page.
470         if (max_packet_size > page_size) {
471             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
472             return false;
473         }
474
475         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
476         if(irq_interval <= 0) irq_interval=1;
477        
478         // the receive buffer size doesn't matter for the latency,
479         // but it has a minimal value in order for libraw to operate correctly (300)
480         int buffers=400;
481
482         // create the actual handler
483         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
484                            buffers, max_packet_size, irq_interval);
485
486         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
487
488         if(!h) {
489             debugFatal("Could not create IsoRecvHandler\n");
490             return false;
491         }
492
493     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
494         // setup the optimal parameters for the raw1394 ISO buffering
495         unsigned int packets_per_period = stream->getPacketsPerPeriod();
496         unsigned int max_packet_size = stream->getMaxPacketSize();
497 //         unsigned int page_size = getpagesize();
498
499         // Ensure we don't request a packet size bigger than the
500         // kernel-enforced maximum which is currently 1 page.
501 //         if (max_packet_size > page_size) {
502 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
503 //             return false;
504 //         }
505         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
506             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
507                        max_packet_size, MAX_XMIT_PACKET_SIZE);
508             return false;
509         }
510
511         // the SP specifies how many packets to ISO-buffer
512         int buffers = stream->getNbPacketsIsoXmitBuffer();
513         if (buffers > MAX_XMIT_NB_BUFFERS) {
514             debugOutput(DEBUG_LEVEL_VERBOSE,
515                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
516                         buffers, MAX_XMIT_NB_BUFFERS);
517             buffers = MAX_XMIT_NB_BUFFERS;
518         }
519         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
520         if(irq_interval <= 0) irq_interval=1;
521
522         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
523
524         // create the actual handler
525         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
526                            buffers, max_packet_size, irq_interval);
527
528         if(!h) {
529             debugFatal("Could not create IsoXmitHandler\n");
530             return false;
531         }
532
533     } else {
534         debugFatal("Bad stream type\n");
535         return false;
536     }
537
538     h->setVerboseLevel(getDebugLevel());
539
540     // init the handler
541     if(!h->init()) {
542         debugFatal("Could not initialize receive handler\n");
543         return false;
544     }
545
546     // set the handler's thread parameters
547     // receive handlers have lower priority than the client thread
548     // since they have ISO side buffering
549     // xmit handlers have higher priority since we want client side
550     // frames to be put into the ISO buffers ASAP
551     int thread_prio;
552     if (stream->getType()==StreamProcessor::ePT_Receive) {
553         thread_prio = m_priority - 1;
554         if (thread_prio < THREAD_MIN_RTPRIO) thread_prio = THREAD_MIN_RTPRIO;
555     } else {
556         thread_prio = m_priority + 1;
557         if (thread_prio > THREAD_MAX_RTPRIO) thread_prio = THREAD_MAX_RTPRIO;
558     }
559
560     // register the stream with the handler
561     if(!h->registerStream(stream)) {
562         debugFatal("Could not register receive stream with handler\n");
563         return false;
564     }
565
566     // register the handler with the manager
567     if(!registerHandler(h)) {
568         debugFatal("Could not register receive handler with manager\n");
569         return false;
570     }
571     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
572
573     m_StreamProcessors.push_back(stream);
574     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
575                                       m_StreamProcessors.size(), m_IsoHandlers.size());
576     return true;
577 }
578
579 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
580 {
581     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
582     assert(stream);
583
584     // make sure the stream isn't attached to a handler anymore
585     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
586       it != m_IsoHandlers.end();
587       ++it )
588     {
589         if((*it)->isStreamRegistered(stream)) {
590             if(!(*it)->unregisterStream(stream)) {
591                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
592                 return false;
593             }
594             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
595         }
596     }
597
598     // clean up all handlers that aren't used
599     pruneHandlers();
600
601     // remove the stream from the registered streams list
602     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
603       it != m_StreamProcessors.end();
604       ++it )
605     {
606         if ( *it == stream ) {
607             m_StreamProcessors.erase(it);
608             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
609             return true;
610         }
611     }
612     return false; //not found
613 }
614
615 /**
616  * @brief unregister a handler from the manager
617  * @note called without the lock held.
618  */
619 void IsoHandlerManager::pruneHandlers() {
620     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
621     IsoHandlerVector toUnregister;
622
623     // find all handlers that are not in use
624     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
625           it != m_IsoHandlers.end();
626           ++it )
627     {
628         if(!((*it)->inUse())) {
629             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
630             toUnregister.push_back(*it);
631         }
632     }
633     // delete them
634     for ( IsoHandlerVectorIterator it = toUnregister.begin();
635           it != toUnregister.end();
636           ++it )
637     {
638         unregisterHandler(*it);
639
640         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
641
642         // Now the handler's been unregistered it won't be reused
643         // again.  Therefore it really needs to be formally deleted
644         // to free up the raw1394 handle.  Otherwise things fall
645         // apart after several xrun recoveries as the system runs
646         // out of resources to support all the disused but still
647         // allocated raw1394 handles.  At least this is the current
648         // theory as to why we end up with "memory allocation"
649         // failures after several Xrun recoveries.
650         delete *it;
651     }
652 }
653
654 bool
655 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
656     // check state
657     if(m_State != E_Running) {
658         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
659         return false;
660     }
661     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
662       it != m_IsoHandlers.end();
663       ++it )
664     {
665         if((*it)->isStreamRegistered(stream)) {
666             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
667             if(!(*it)->disable()) {
668                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
669                 return false;
670             }
671             if(!updateShadowMapFor(*it)) {
672                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
673                 return false;
674             }
675             return true;
676         }
677     }
678     debugError("Stream %p has no attached handler\n", stream);
679     return false;
680 }
681
682 int
683 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
684     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
685       it != m_IsoHandlers.end();
686       ++it )
687     {
688         if((*it)->isStreamRegistered(stream)) {
689             return (*it)->getPacketLatency();
690         }
691     }
692     debugError("Stream %p has no attached handler\n", stream);
693     return 0;
694 }
695
696 void
697 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
698     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
699       it != m_IsoHandlers.end();
700       ++it )
701     {
702         if((*it)->isStreamRegistered(stream)) {
703             return (*it)->flush();
704         }
705     }
706     debugError("Stream %p has no attached handler\n", stream);
707     return;
708 }
709
710 bool
711 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
712     return startHandlerForStream(stream, -1);
713 }
714
715 bool
716 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
717     // check state
718     if(m_State != E_Running) {
719         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
720         return false;
721     }
722     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
723       it != m_IsoHandlers.end();
724       ++it )
725     {
726         if((*it)->isStreamRegistered(stream)) {
727             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
728             if(!(*it)->enable(cycle)) {
729                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
730                 return false;
731             }
732             if(!updateShadowMapFor(*it)) {
733                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
734                 return false;
735             }
736             return true;
737         }
738     }
739     debugError("Stream %p has no attached handler\n", stream);
740     return false;
741 }
742
743 bool IsoHandlerManager::stopHandlers() {
744     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
745
746     // check state
747     if(m_State != E_Running) {
748         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
749         return false;
750     }
751
752     bool retval=true;
753
754     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
755         it != m_IsoHandlers.end();
756         ++it )
757     {
758         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
759         if(!(*it)->disable()){
760             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
761             retval=false;
762         }
763         if(!updateShadowMapFor(*it)) {
764             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
765             retval=false;
766         }
767     }
768
769     if (retval) {
770         m_State=E_Prepared;
771     } else {
772         m_State=E_Error;
773     }
774     return retval;
775 }
776
777 bool IsoHandlerManager::reset() {
778     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
779     // check state
780     if(m_State == E_Error) {
781         debugFatal("Resetting from error condition not yet supported...\n");
782         return false;
783     }
784     // if not in an error condition, reset means stop the handlers
785     return stopHandlers();
786 }
787
788 void IsoHandlerManager::setVerboseLevel(int i) {
789     setDebugLevel(i);
790     // propagate the debug level
791     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
792           it != m_IsoHandlers.end();
793           ++it )
794     {
795         (*it)->setVerboseLevel(i);
796     }
797     if(m_ReceiveThread) m_ReceiveThread->setVerboseLevel(i);
798     if(m_ReceiveTask) m_ReceiveTask->setVerboseLevel(i);
799     if(m_TransmitThread) m_TransmitThread->setVerboseLevel(i);
800     if(m_TransmitTask) m_TransmitTask->setVerboseLevel(i);
801 }
802
803 void IsoHandlerManager::dumpInfo() {
804     int i=0;
805     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
806     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
807
808     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
809           it != m_IsoHandlers.end();
810           ++it )
811     {
812         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
813         (*it)->dumpInfo();
814     }
815 }
816
817 const char *
818 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
819     switch (s) {
820         default: return "Invalid";
821         case E_Created: return "Created";
822         case E_Prepared: return "Prepared";
823         case E_Running: return "Running";
824         case E_Error: return "Error";
825     }
826 }
Note: See TracBrowser for help on using the browser.