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

Revision 913, 25.9 kB (checked in by ppalmers, 13 years ago)

remove bogus line

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
206     return true;
207
208 }
209
210 void IsoTask::setVerboseLevel(int i) {
211     setDebugLevel(i);
212 }
213
214 // -- the ISO handler manager -- //
215 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service)
216    : m_State(E_Created)
217    , m_service( service )
218    , m_realtime(false), m_priority(0)
219    , m_ReceiveThread ( NULL )
220    , m_TransmitThread ( NULL )
221    , m_ReceiveTask ( NULL )
222    , m_TransmitTask ( NULL )
223 {}
224
225 IsoHandlerManager::IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio)
226    : m_State(E_Created)
227    , m_service( service )
228    , m_realtime(run_rt), m_priority(rt_prio)
229    , m_ReceiveThread ( NULL )
230    , m_TransmitThread ( NULL )
231    , m_ReceiveTask ( NULL )
232    , m_TransmitTask ( NULL )
233 {}
234
235 IsoHandlerManager::~IsoHandlerManager()
236 {
237     stopHandlers();
238     pruneHandlers();
239     if(m_IsoHandlers.size() > 0) {
240         debugError("Still some handlers in use\n");
241     }
242     if (m_ReceiveThread) {
243         m_ReceiveThread->Stop();
244         delete m_ReceiveThread;
245     }
246     if (m_ReceiveTask) {
247         delete m_ReceiveTask;
248     }
249
250     if (m_TransmitThread) {
251         m_TransmitThread->Stop();
252         delete m_TransmitThread;
253     }
254     if (m_TransmitTask) {
255         delete m_TransmitTask;
256     }
257 }
258
259 bool
260 IsoHandlerManager::setThreadParameters(bool rt, int priority) {
261     debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) switch to: (rt=%d, prio=%d)...\n", this, rt, priority);
262     if (priority > THREAD_MAX_RTPRIO) priority = THREAD_MAX_RTPRIO; // cap the priority
263     m_realtime = rt;
264     m_priority = priority;
265     bool result = true;
266
267     if (m_ReceiveThread) {
268         if (m_realtime) {
269             m_ReceiveThread->AcquireRealTime(m_priority);
270         } else {
271             m_ReceiveThread->DropRealTime();
272         }
273     }
274     if (m_TransmitThread) {
275         if (m_realtime) {
276             m_TransmitThread->AcquireRealTime(m_priority);
277         } else {
278             m_TransmitThread->DropRealTime();
279         }
280     }
281
282     return result;
283 }
284
285 bool IsoHandlerManager::init()
286 {
287     debugOutput( DEBUG_LEVEL_VERBOSE, "Initializing ISO manager %p...\n", this);
288     // check state
289     if(m_State != E_Created) {
290         debugError("Manager already initialized...\n");
291         return false;
292     }
293
294     // create a thread to iterate our receive handlers
295     debugOutput( DEBUG_LEVEL_VERBOSE, "Create receive thread for %p...\n", this);
296     m_ReceiveTask = new IsoTask( *this, IsoTask::eTT_Receive );
297     if(!m_ReceiveTask) {
298         debugFatal("No task\n");
299         return false;
300     }
301     m_ReceiveThread = new Util::PosixThread(m_ReceiveTask, m_realtime,
302                                             m_priority + ISOHANDLERMANAGER_RECEIVE_PRIO_INCREASE,
303                                             PTHREAD_CANCEL_DEFERRED);
304
305     if(!m_ReceiveThread) {
306         debugFatal("No thread\n");
307         return false;
308     }
309     if (m_ReceiveThread->Start() != 0) {
310         debugFatal("Could not start receive thread\n");
311         return false;
312     }
313
314     // create a thread to iterate our transmit handlers
315     debugOutput( DEBUG_LEVEL_VERBOSE, "Create transmit thread for %p...\n", this);
316     m_TransmitTask = new IsoTask( *this, IsoTask::eTT_Transmit );
317     if(!m_TransmitTask) {
318         debugFatal("No task\n");
319         return false;
320     }
321     m_TransmitThread = new Util::PosixThread(m_TransmitTask, m_realtime,
322                                              m_priority + ISOHANDLERMANAGER_TRANSMIT_PRIO_INCREASE,
323                                              PTHREAD_CANCEL_DEFERRED);
324     if(!m_TransmitThread) {
325         debugFatal("No thread\n");
326         return false;
327     }
328     if (m_TransmitThread->Start() != 0) {
329         debugFatal("Could not start transmit thread\n");
330         return false;
331     }
332
333     m_State=E_Running;
334     return true;
335 }
336
337
338 bool
339 IsoHandlerManager::updateShadowMapFor(IsoHandler *h)
340 {
341     // update the shadow map
342     if(h->getType() == IsoHandler::eHT_Receive) {
343         if(!m_ReceiveTask->requestShadowMapUpdate()) {
344             debugError("failed to update shadow map\n");
345             return false;
346         }
347     } else {
348         if(!m_TransmitTask->requestShadowMapUpdate()) {
349             debugError("failed to update shadow map\n");
350             return false;
351         }
352     }
353     return true;
354 }
355
356 bool
357 IsoHandlerManager::disable(IsoHandler *h) {
358     bool result;
359     int i=0;
360     debugOutput(DEBUG_LEVEL_VERBOSE, "Disable on IsoHandler %p\n", h);
361     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
362         it != m_IsoHandlers.end();
363         ++it )
364     {
365         if ((*it) == h) {
366             result = h->disable();
367             result &= updateShadowMapFor(h);
368             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " disabled\n");
369             return result;
370         }
371         i++;
372     }
373     debugError("Handler not found\n");
374     return false;
375 }
376
377 bool
378 IsoHandlerManager::enable(IsoHandler *h) {
379     bool result;
380     int i=0;
381     debugOutput(DEBUG_LEVEL_VERBOSE, "Enable on IsoHandler %p\n", h);
382     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
383         it != m_IsoHandlers.end();
384         ++it )
385     {
386         if ((*it) == h) {
387             result = h->enable();
388             result &= updateShadowMapFor(h);
389             debugOutput(DEBUG_LEVEL_VERY_VERBOSE, " enabled\n");
390             return result;
391         }
392         i++;
393     }
394     debugError("Handler not found\n");
395     return false;
396 }
397
398 bool IsoHandlerManager::registerHandler(IsoHandler *handler)
399 {
400     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
401     assert(handler);
402     handler->setVerboseLevel(getDebugLevel());
403     m_IsoHandlers.push_back(handler);
404     return updateShadowMapFor(handler);
405 }
406
407 bool IsoHandlerManager::unregisterHandler(IsoHandler *handler)
408 {
409     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
410     assert(handler);
411
412     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
413       it != m_IsoHandlers.end();
414       ++it )
415     {
416         if ( *it == handler ) {
417             m_IsoHandlers.erase(it);
418             return updateShadowMapFor(handler);
419         }
420     }
421     debugFatal("Could not find handler (%p)\n", handler);
422     return false; //not found
423 }
424
425 /**
426  * Registers an StreamProcessor with the IsoHandlerManager.
427  *
428  * If nescessary, an IsoHandler is created to handle this stream.
429  * Once an StreamProcessor is registered to the handler, it will be included
430  * in the ISO streaming cycle (i.e. receive/transmit of it will occur).
431  *
432  * @param stream the stream to register
433  * @return true if registration succeeds
434  *
435  * \todo : currently there is a one-to-one mapping
436  *        between streams and handlers, this is not ok for
437  *        multichannel receive
438  */
439 bool IsoHandlerManager::registerStream(StreamProcessor *stream)
440 {
441     debugOutput( DEBUG_LEVEL_VERBOSE, "Registering stream %p\n",stream);
442     assert(stream);
443
444     IsoHandler* h = NULL;
445
446     // make sure the stream isn't already attached to a handler
447     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
448       it != m_IsoHandlers.end();
449       ++it )
450     {
451         if((*it)->isStreamRegistered(stream)) {
452             debugError( "stream already registered!\n");
453             return false;
454         }
455     }
456
457     // clean up all handlers that aren't used
458     pruneHandlers();
459
460     // allocate a handler for this stream
461     if (stream->getType()==StreamProcessor::ePT_Receive) {
462         // setup the optimal parameters for the raw1394 ISO buffering
463         unsigned int packets_per_period = stream->getPacketsPerPeriod();
464         unsigned int max_packet_size = stream->getMaxPacketSize();
465         unsigned int page_size = getpagesize() - 2; // for one reason or another this is necessary
466
467         // Ensure we don't request a packet size bigger than the
468         // kernel-enforced maximum which is currently 1 page.
469         if (max_packet_size > page_size) {
470             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
471             return false;
472         }
473
474         unsigned int irq_interval = packets_per_period / MINIMUM_INTERRUPTS_PER_PERIOD;
475         if(irq_interval <= 0) irq_interval=1;
476        
477         // the receive buffer size doesn't matter for the latency,
478         // but it has a minimal value in order for libraw to operate correctly (300)
479         int buffers=400;
480
481         // create the actual handler
482         h = new IsoHandler(*this, IsoHandler::eHT_Receive,
483                            buffers, max_packet_size, irq_interval);
484
485         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoRecvHandler\n");
486
487         if(!h) {
488             debugFatal("Could not create IsoRecvHandler\n");
489             return false;
490         }
491
492     } else if (stream->getType()==StreamProcessor::ePT_Transmit) {
493         // setup the optimal parameters for the raw1394 ISO buffering
494         unsigned int packets_per_period = stream->getPacketsPerPeriod();
495         unsigned int max_packet_size = stream->getMaxPacketSize();
496 //         unsigned int page_size = getpagesize();
497
498         // Ensure we don't request a packet size bigger than the
499         // kernel-enforced maximum which is currently 1 page.
500 //         if (max_packet_size > page_size) {
501 //             debugError("max packet size (%u) > page size (%u)\n", max_packet_size, page_size);
502 //             return false;
503 //         }
504         if (max_packet_size > MAX_XMIT_PACKET_SIZE) {
505             debugError("max packet size (%u) > MAX_XMIT_PACKET_SIZE (%u)\n",
506                        max_packet_size, MAX_XMIT_PACKET_SIZE);
507             return false;
508         }
509
510         // the SP specifies how many packets to ISO-buffer
511         int buffers = stream->getNbPacketsIsoXmitBuffer();
512         if (buffers > MAX_XMIT_NB_BUFFERS) {
513             debugOutput(DEBUG_LEVEL_VERBOSE,
514                         "nb buffers (%u) > MAX_XMIT_NB_BUFFERS (%u)\n",
515                         buffers, MAX_XMIT_NB_BUFFERS);
516             buffers = MAX_XMIT_NB_BUFFERS;
517         }
518         unsigned int irq_interval = buffers / MINIMUM_INTERRUPTS_PER_PERIOD;
519         if(irq_interval <= 0) irq_interval=1;
520
521         debugOutput( DEBUG_LEVEL_VERBOSE, " creating IsoXmitHandler\n");
522
523         // create the actual handler
524         h = new IsoHandler(*this, IsoHandler::eHT_Transmit,
525                            buffers, max_packet_size, irq_interval);
526
527         if(!h) {
528             debugFatal("Could not create IsoXmitHandler\n");
529             return false;
530         }
531
532     } else {
533         debugFatal("Bad stream type\n");
534         return false;
535     }
536
537     h->setVerboseLevel(getDebugLevel());
538
539     // init the handler
540     if(!h->init()) {
541         debugFatal("Could not initialize receive handler\n");
542         return false;
543     }
544
545     // set the handler's thread parameters
546     // receive handlers have lower priority than the client thread
547     // since they have ISO side buffering
548     // xmit handlers have higher priority since we want client side
549     // frames to be put into the ISO buffers ASAP
550     int thread_prio;
551     if (stream->getType()==StreamProcessor::ePT_Receive) {
552         thread_prio = m_priority - 1;
553         if (thread_prio < THREAD_MIN_RTPRIO) thread_prio = THREAD_MIN_RTPRIO;
554     } else {
555         thread_prio = m_priority + 1;
556         if (thread_prio > THREAD_MAX_RTPRIO) thread_prio = THREAD_MAX_RTPRIO;
557     }
558
559     // register the stream with the handler
560     if(!h->registerStream(stream)) {
561         debugFatal("Could not register receive stream with handler\n");
562         return false;
563     }
564
565     // register the handler with the manager
566     if(!registerHandler(h)) {
567         debugFatal("Could not register receive handler with manager\n");
568         return false;
569     }
570     debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n", stream, h);
571
572     m_StreamProcessors.push_back(stream);
573     debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
574                                       m_StreamProcessors.size(), m_IsoHandlers.size());
575     return true;
576 }
577
578 bool IsoHandlerManager::unregisterStream(StreamProcessor *stream)
579 {
580     debugOutput( DEBUG_LEVEL_VERBOSE, "Unregistering stream %p\n",stream);
581     assert(stream);
582
583     // make sure the stream isn't attached to a handler anymore
584     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
585       it != m_IsoHandlers.end();
586       ++it )
587     {
588         if((*it)->isStreamRegistered(stream)) {
589             if(!(*it)->unregisterStream(stream)) {
590                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not unregister stream (%p) from handler (%p)...\n",stream,*it);
591                 return false;
592             }
593             debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
594         }
595     }
596
597     // clean up all handlers that aren't used
598     pruneHandlers();
599
600     // remove the stream from the registered streams list
601     for ( StreamProcessorVectorIterator it = m_StreamProcessors.begin();
602       it != m_StreamProcessors.end();
603       ++it )
604     {
605         if ( *it == stream ) {
606             m_StreamProcessors.erase(it);
607             debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
608             return true;
609         }
610     }
611     return false; //not found
612 }
613
614 /**
615  * @brief unregister a handler from the manager
616  * @note called without the lock held.
617  */
618 void IsoHandlerManager::pruneHandlers() {
619     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
620     IsoHandlerVector toUnregister;
621
622     // find all handlers that are not in use
623     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
624           it != m_IsoHandlers.end();
625           ++it )
626     {
627         if(!((*it)->inUse())) {
628             debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
629             toUnregister.push_back(*it);
630         }
631     }
632     // delete them
633     for ( IsoHandlerVectorIterator it = toUnregister.begin();
634           it != toUnregister.end();
635           ++it )
636     {
637         unregisterHandler(*it);
638
639         debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
640
641         // Now the handler's been unregistered it won't be reused
642         // again.  Therefore it really needs to be formally deleted
643         // to free up the raw1394 handle.  Otherwise things fall
644         // apart after several xrun recoveries as the system runs
645         // out of resources to support all the disused but still
646         // allocated raw1394 handles.  At least this is the current
647         // theory as to why we end up with "memory allocation"
648         // failures after several Xrun recoveries.
649         delete *it;
650     }
651 }
652
653 bool
654 IsoHandlerManager::stopHandlerForStream(Streaming::StreamProcessor *stream) {
655     // check state
656     if(m_State != E_Running) {
657         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
658         return false;
659     }
660     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
661       it != m_IsoHandlers.end();
662       ++it )
663     {
664         if((*it)->isStreamRegistered(stream)) {
665             debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler %p for stream %p\n", *it, stream);
666             if(!(*it)->disable()) {
667                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not disable handler (%p)\n",*it);
668                 return false;
669             }
670             if(!updateShadowMapFor(*it)) {
671                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
672                 return false;
673             }
674             return true;
675         }
676     }
677     debugError("Stream %p has no attached handler\n", stream);
678     return false;
679 }
680
681 int
682 IsoHandlerManager::getPacketLatencyForStream(Streaming::StreamProcessor *stream) {
683     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
684       it != m_IsoHandlers.end();
685       ++it )
686     {
687         if((*it)->isStreamRegistered(stream)) {
688             return (*it)->getPacketLatency();
689         }
690     }
691     debugError("Stream %p has no attached handler\n", stream);
692     return 0;
693 }
694
695 void
696 IsoHandlerManager::flushHandlerForStream(Streaming::StreamProcessor *stream) {
697     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
698       it != m_IsoHandlers.end();
699       ++it )
700     {
701         if((*it)->isStreamRegistered(stream)) {
702             return (*it)->flush();
703         }
704     }
705     debugError("Stream %p has no attached handler\n", stream);
706     return;
707 }
708
709 bool
710 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream) {
711     return startHandlerForStream(stream, -1);
712 }
713
714 bool
715 IsoHandlerManager::startHandlerForStream(Streaming::StreamProcessor *stream, int cycle) {
716     // check state
717     if(m_State != E_Running) {
718         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
719         return false;
720     }
721     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
722       it != m_IsoHandlers.end();
723       ++it )
724     {
725         if((*it)->isStreamRegistered(stream)) {
726             debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler %p for stream %p\n", *it, stream);
727             if(!(*it)->enable(cycle)) {
728                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not enable handler (%p)\n",*it);
729                 return false;
730             }
731             if(!updateShadowMapFor(*it)) {
732                 debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
733                 return false;
734             }
735             return true;
736         }
737     }
738     debugError("Stream %p has no attached handler\n", stream);
739     return false;
740 }
741
742 bool IsoHandlerManager::stopHandlers() {
743     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
744
745     // check state
746     if(m_State != E_Running) {
747         debugError("Incorrect state, expected E_Running, got %s\n", eHSToString(m_State));
748         return false;
749     }
750
751     bool retval=true;
752
753     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
754         it != m_IsoHandlers.end();
755         ++it )
756     {
757         debugOutput( DEBUG_LEVEL_VERBOSE, "Stopping handler (%p)\n",*it);
758         if(!(*it)->disable()){
759             debugOutput( DEBUG_LEVEL_VERBOSE, " could not stop handler (%p)\n",*it);
760             retval=false;
761         }
762         if(!updateShadowMapFor(*it)) {
763             debugOutput( DEBUG_LEVEL_VERBOSE, " could not update shadow map for handler (%p)\n",*it);
764             retval=false;
765         }
766     }
767
768     if (retval) {
769         m_State=E_Prepared;
770     } else {
771         m_State=E_Error;
772     }
773     return retval;
774 }
775
776 bool IsoHandlerManager::reset() {
777     debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
778     // check state
779     if(m_State == E_Error) {
780         debugFatal("Resetting from error condition not yet supported...\n");
781         return false;
782     }
783     // if not in an error condition, reset means stop the handlers
784     return stopHandlers();
785 }
786
787 void IsoHandlerManager::setVerboseLevel(int i) {
788     setDebugLevel(i);
789     // propagate the debug level
790     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
791           it != m_IsoHandlers.end();
792           ++it )
793     {
794         (*it)->setVerboseLevel(i);
795     }
796     if(m_ReceiveThread) m_ReceiveThread->setVerboseLevel(i);
797     if(m_ReceiveTask) m_ReceiveTask->setVerboseLevel(i);
798     if(m_TransmitThread) m_TransmitThread->setVerboseLevel(i);
799     if(m_TransmitTask) m_TransmitTask->setVerboseLevel(i);
800 }
801
802 void IsoHandlerManager::dumpInfo() {
803     int i=0;
804     debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
805     debugOutputShort( DEBUG_LEVEL_NORMAL, " State: %d\n",(int)m_State);
806
807     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
808           it != m_IsoHandlers.end();
809           ++it )
810     {
811         debugOutputShort( DEBUG_LEVEL_NORMAL, " IsoHandler %d (%p)\n",i++,*it);
812         (*it)->dumpInfo();
813     }
814 }
815
816 const char *
817 IsoHandlerManager::eHSToString(enum eHandlerStates s) {
818     switch (s) {
819         default: return "Invalid";
820         case E_Created: return "Created";
821         case E_Prepared: return "Prepared";
822         case E_Running: return "Running";
823         case E_Error: return "Error";
824     }
825 }
Note: See TracBrowser for help on using the browser.