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

Revision 967, 25.8 kB (checked in by ppalmers, 13 years ago)

- first attempt at not causing total havoc when devices are removed from the bus.

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