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

Revision 750, 25.4 kB (checked in by ppalmers, 16 years ago)

Code refactoring. Tries to simplify things and tries to put all code where it belongs.

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