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

Revision 938, 25.4 kB (checked in by ppalmers, 13 years ago)

implement static iso handler scheduling

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