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

Revision 791, 22.9 kB (checked in by ppalmers, 13 years ago)

try and get some better low-latency performance

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