root/branches/libfreebob-2.0/src/libstreaming/IsoHandlerManager.cpp

Revision 221, 9.2 kB (checked in by pieterpalmers, 18 years ago)

--

Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2006 Pieter Palmers <pieterpalmers@users.sourceforge.net>
10  *
11  *   This program is free software {} you can redistribute it and/or modify
12  *   it under the terms of the GNU General Public License as published by
13  *   the Free Software Foundation {} either version 2 of the License, or
14  *   (at your option) any later version.
15  *
16  *   This program is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY {} without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with this program {} if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  *
26  *
27  */
28
29 #include "IsoHandlerManager.h"
30 #include "IsoHandler.h"
31 #include "IsoStream.h"
32 #include <assert.h>
33
34
35 namespace FreebobStreaming
36 {
37
38 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
39
40 IsoHandlerManager::IsoHandlerManager() :
41    m_poll_timeout(100), m_poll_fds(0), m_poll_nfds(0)
42 {
43
44 }
45
46
47 IsoHandlerManager::~IsoHandlerManager()
48 {
49
50 }
51
52 bool IsoHandlerManager::Init()
53 {
54         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
55
56         return true;
57 }
58
59
60 bool IsoHandlerManager::Execute()
61 {
62         int err;
63         int i=0;
64         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
65
66         err = poll (m_poll_fds, m_poll_nfds, m_poll_timeout);
67        
68         if (err == -1) {
69                 if (errno == EINTR) {
70                         return true;
71                 }
72                 debugFatal("poll error: %s\n", strerror (errno));
73                 return false;
74         }
75
76         for (i = 0; i < m_poll_nfds; i++) {
77                 if (m_poll_fds[i].revents & POLLERR) {
78                         debugWarning("error on fd for %d\n",i);
79                 }
80
81                 if (m_poll_fds[i].revents & POLLHUP) {
82                         debugWarning("hangup on fd for %d\n",i);
83                 }
84                
85                 if(m_poll_fds[i].revents & (POLLIN)) {
86                         IsoHandler *s=m_IsoHandlers.at(i);
87                         assert(s);
88                         s->iterate();
89                 }
90         }
91         return true;
92
93 }
94
95 bool IsoHandlerManager::prepare()
96 {
97         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
98     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
99           it != m_IsoHandlers.end();
100           ++it )
101     {
102         if(!(*it)->prepare()) {
103                         debugFatal("Could not prepare handlers\n");
104                         return false;
105         }
106     }
107
108         return true;
109 }
110
111
112
113 int IsoHandlerManager::registerHandler(IsoHandler *handler)
114 {
115         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
116         assert(handler);
117         m_IsoHandlers.push_back(handler);
118         handler->setVerboseLevel(getDebugLevel());
119
120         // rebuild the fd map for poll()'ing.
121         return rebuildFdMap(); 
122
123 }
124
125 int IsoHandlerManager::unregisterHandler(IsoHandler *handler)
126 {
127         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
128         assert(handler);
129
130     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
131           it != m_IsoHandlers.end();
132           ++it )
133     {
134         if ( *it == handler ) {
135                         // erase the iso handler from the list
136             m_IsoHandlers.erase(it);
137
138                         // rebuild the fd map for poll()'ing.
139                         return rebuildFdMap();
140         }
141     }
142
143         return -1; //not found
144
145 }
146
147 int IsoHandlerManager::rebuildFdMap() {
148         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
149         int i=0;
150
151         m_poll_nfds=0;
152         if(m_poll_fds) free(m_poll_fds);
153
154         // count the number of handlers
155         m_poll_nfds=m_IsoHandlers.size();
156
157         // allocate the fd array
158         m_poll_fds   = (struct pollfd *) calloc (m_poll_nfds, sizeof (struct pollfd));
159         if(!m_poll_fds) {
160                 debugFatal("Could not allocate memory for poll FD array\n");
161                 return -1;
162         }
163
164         // fill the fd map
165     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
166           it != m_IsoHandlers.end();
167           ++it )
168     {
169                 m_poll_fds[i].fd=(*it)->getFileDescriptor();
170                 m_poll_fds[i].events = POLLIN;
171                 i++;
172     }
173
174         return 0;
175 }
176
177
178 // FIXME: currently there is a one-to-one mapping
179 //        between streams and handlers, this is not ok for
180 //        multichannel receive
181 int IsoHandlerManager::registerStream(IsoStream *stream)
182 {
183         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
184         assert(stream);
185
186         // make sure the stream isn't already attached to a handler
187     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
188           it != m_IsoHandlers.end();
189           ++it )
190     {
191                 if((*it)->isStreamRegistered(stream)) {
192                         debugOutput( DEBUG_LEVEL_VERBOSE, "stream already registered!\n");
193                         (*it)->unregisterStream(stream);
194                 }
195     }
196
197         // clean up all handlers that aren't used
198         pruneHandlers();
199
200         // allocate a handler for this stream
201         if (stream->getType()==IsoStream::EST_Receive) {
202                 IsoRecvHandler *h = new IsoRecvHandler(stream->getPort());
203                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoRecvHandler\n");
204
205                 if(!h) {
206                         debugFatal("Could not create IsoRecvHandler\n");
207                         return -1;
208                 }
209
210                 h->setVerboseLevel(getDebugLevel());
211
212                 // init the handler
213                 if(!h->initialize()) {
214                         debugFatal("Could not initialize receive handler\n");
215                         return -1;
216                 }
217
218                 // register the stream with the handler
219                 if(h->registerStream(stream)) {
220                         debugFatal("Could not register receive stream with handler\n");
221                         return -1;
222                 }
223
224                 // register the handler with the manager
225                 if(this->registerHandler(h)) {
226                         debugFatal("Could not register receive handler with manager\n");
227                         return -1;
228                 }
229                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
230         }
231        
232         if (stream->getType()==IsoStream::EST_Transmit) {
233                 IsoXmitHandler *h = new IsoXmitHandler(stream->getPort());
234
235                 debugOutput( DEBUG_LEVEL_VERBOSE, " registering IsoXmitHandler\n");
236
237                 if(!h) {
238                         debugFatal("Could not create IsoXmitHandler\n");
239                         return -1;
240                 }
241
242                 h->setVerboseLevel(getDebugLevel());
243
244                 // init the handler
245                 if(!h->initialize()) {
246                         debugFatal("Could not initialize transmit handler\n");
247                         return -1;
248                 }
249
250                 // register the stream with the handler
251                 if(h->registerStream(stream)) {
252                         debugFatal("Could not register transmit stream with handler\n");
253                         return -1;
254                 }
255
256                 // register the handler with the manager
257                 if(this->registerHandler(h)) {
258                         debugFatal("Could not register transmit handler with manager\n");
259                         return -1;
260                 }
261                 debugOutput( DEBUG_LEVEL_VERBOSE, " registered stream (%p) with handler (%p)\n",stream,h);
262
263         }
264
265         m_IsoStreams.push_back(stream);
266         debugOutput( DEBUG_LEVEL_VERBOSE, " %d streams, %d handlers registered\n",
267                                           m_IsoStreams.size(), m_IsoHandlers.size());
268
269         return 0;
270 }
271
272 int IsoHandlerManager::unregisterStream(IsoStream *stream)
273 {
274         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
275         assert(stream);
276
277         // make sure the stream isn't attached to a handler anymore
278     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
279           it != m_IsoHandlers.end();
280           ++it )
281     {
282                 if((*it)->isStreamRegistered(stream)) {
283                         (*it)->unregisterStream(stream);
284                         debugOutput( DEBUG_LEVEL_VERBOSE, " unregistered stream (%p) from handler (%p)...\n",stream,*it);
285                 }
286     }
287
288         // clean up all handlers that aren't used
289         pruneHandlers();
290
291         // remove the stream from the registered streams list
292     for ( IsoStreamVectorIterator it = m_IsoStreams.begin();
293           it != m_IsoStreams.end();
294           ++it )
295     {
296         if ( *it == stream ) {
297             m_IsoStreams.erase(it);
298                         debugOutput( DEBUG_LEVEL_VERBOSE, " deleted stream (%p) from list...\n", *it);
299                         return 0;
300         }
301     }
302
303         return -1; //not found
304
305 }
306
307 void IsoHandlerManager::pruneHandlers() {
308         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
309         IsoHandlerVector toUnregister;
310
311         // find all handlers that are not in use
312     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
313           it != m_IsoHandlers.end();
314           ++it )
315     {
316                 if(!((*it)->inUse())) {
317                         debugOutput( DEBUG_LEVEL_VERBOSE, " handler (%p) not in use\n",*it);
318                         toUnregister.push_back(*it);
319                 }
320     }
321         // delete them
322     for ( IsoHandlerVectorIterator it = toUnregister.begin();
323           it != toUnregister.end();
324           ++it )
325     {
326                 unregisterHandler(*it);
327                 debugOutput( DEBUG_LEVEL_VERBOSE, " deleting handler (%p)\n",*it);
328     }
329
330 }
331
332 int IsoHandlerManager::startHandlers() {
333         return startHandlers(-1);
334 }
335
336 int IsoHandlerManager::startHandlers(int cycle) {
337         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
338
339     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
340           it != m_IsoHandlers.end();
341           ++it )
342     {
343                 debugOutput( DEBUG_LEVEL_VERBOSE, " starting handler (%p)\n",*it);
344                 (*it)->start(cycle);
345     }
346         return 0;
347 }
348
349 void IsoHandlerManager::stopHandlers() {
350         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
351
352     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
353           it != m_IsoHandlers.end();
354           ++it )
355     {
356                 debugOutput( DEBUG_LEVEL_VERBOSE, " stopping handler (%p)\n",*it);
357                 (*it)->stop();
358     }
359 }
360
361 void IsoHandlerManager::setVerboseLevel(int i) {
362         setDebugLevel(i);
363
364     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
365           it != m_IsoHandlers.end();
366           ++it )
367     {
368                 (*it)->setVerboseLevel(i);
369     }
370 }
371
372 void IsoHandlerManager::dumpInfo() {
373         debugOutputShort( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
374         int i=0;
375
376     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
377           it != m_IsoHandlers.end();
378           ++it )
379     {
380                 debugOutputShort( DEBUG_LEVEL_NORMAL, " Stream %d (%p)\n",i++,*it);
381
382                 (*it)->dumpInfo();
383     }
384
385 }
386
387 } // end of namespace FreebobStreaming
388
Note: See TracBrowser for help on using the browser.