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

Revision 204, 7.6 kB (checked in by pieterpalmers, 18 years ago)

- ISO streaming infrastructure starts to look good
- client side infrastructure unexistant

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
33 namespace FreebobStreaming
34 {
35
36 IMPL_DEBUG_MODULE( IsoHandlerManager, IsoHandlerManager, DEBUG_LEVEL_NORMAL );
37
38 IsoHandlerManager::IsoHandlerManager() :
39    m_poll_timeout(100), m_poll_fds(0), m_poll_nfds(0)
40 {
41
42 }
43
44
45 IsoHandlerManager::~IsoHandlerManager()
46 {
47
48 }
49
50 bool IsoHandlerManager::Init()
51 {
52         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
53
54         return true;
55 }
56
57
58 bool IsoHandlerManager::Execute()
59 {
60         int err;
61         int i=0;
62         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "enter...\n");
63
64         err = poll (m_poll_fds, m_poll_nfds, m_poll_timeout);
65        
66         if (err == -1) {
67                 if (errno == EINTR) {
68                         return true;
69                 }
70                 debugFatal("poll error: %s\n", strerror (errno));
71                 return false;
72         }
73
74         for (i = 0; i < m_poll_nfds; i++) {
75                 if (m_poll_fds[i].revents & POLLERR) {
76                         debugWarning("error on fd for %d\n",i);
77                 }
78
79                 if (m_poll_fds[i].revents & POLLHUP) {
80                         debugWarning("hangup on fd for %d\n",i);
81                 }
82                
83                 if(m_poll_fds[i].revents & (POLLIN)) {
84                         IsoHandler *s=m_IsoHandlers.at(i);
85                         assert(s);
86                         s->iterate();
87                 }
88         }
89         return true;
90
91 }
92
93 int IsoHandlerManager::registerHandler(IsoHandler *handler)
94 {
95         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
96         assert(handler);
97         m_IsoHandlers.push_back(handler);
98
99         // rebuild the fd map for poll()'ing.
100         return rebuildFdMap(); 
101
102 }
103
104 int IsoHandlerManager::unregisterHandler(IsoHandler *handler)
105 {
106         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
107         assert(handler);
108
109     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
110           it != m_IsoHandlers.end();
111           ++it )
112     {
113         if ( *it == handler ) {
114                         // erase the iso handler from the list
115             m_IsoHandlers.erase(it);
116
117                         // rebuild the fd map for poll()'ing.
118                         return rebuildFdMap();
119         }
120     }
121
122         return -1; //not found
123
124 }
125
126 int IsoHandlerManager::rebuildFdMap() {
127         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
128         int i=0;
129
130         m_poll_nfds=0;
131         if(m_poll_fds) free(m_poll_fds);
132
133         // count the number of handlers
134         m_poll_nfds=m_IsoHandlers.size();
135
136         // allocate the fd array
137         m_poll_fds   = (struct pollfd *) calloc (m_poll_nfds, sizeof (struct pollfd));
138         if(!m_poll_fds) {
139                 debugFatal("Could not allocate memory for poll FD array\n");
140                 return -1;
141         }
142
143         // fill the fd map
144     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
145           it != m_IsoHandlers.end();
146           ++it )
147     {
148                 m_poll_fds[i].fd=(*it)->getFileDescriptor();
149                 m_poll_fds[i].events = POLLIN;
150                 i++;
151     }
152
153         return 0;
154 }
155
156
157 // FIXME: currently there is a one-to-one mapping
158 //        between streams and handlers, this is not ok for
159 //        multichannel receive
160 int IsoHandlerManager::registerStream(IsoStream *stream)
161 {
162         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
163         assert(stream);
164
165         // make sure the stream isn't already attached to a handler
166     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
167           it != m_IsoHandlers.end();
168           ++it )
169     {
170                 if((*it)->isStreamRegistered(stream)) {
171                         (*it)->unregisterStream(stream);
172                 }
173     }
174
175         // clean up all handlers that aren't used
176         pruneHandlers();
177
178         // allocate a handler for this stream
179         if (stream->getType()==IsoStream::EST_Receive) {
180                 IsoRecvHandler *h = new IsoRecvHandler(stream->getPort());
181                 if(!h) {
182                         debugFatal("Could not create IsoRecvHandler\n");
183                         return -1;
184                 }
185
186                 h->setVerboseLevel(getDebugLevel());
187
188                 // init the handler
189                 if(!h->initialize()) {
190                         debugFatal("Could not initialize receive handler\n");
191                         return -1;
192                 }
193
194                 // register the stream with the handler
195                 if(h->registerStream(stream)) {
196                         debugFatal("Could not register receive stream with handler\n");
197                         return -1;
198                 }
199
200                 // register the handler with the manager
201                 if(this->registerHandler(h)) {
202                         debugFatal("Could not register receive handler with manager\n");
203                         return -1;
204                 }
205         }
206        
207         if (stream->getType()==IsoStream::EST_Transmit) {
208                 IsoXmitHandler *h = new IsoXmitHandler(stream->getPort());
209                 if(!h) {
210                         debugFatal("Could not create IsoXmitHandler\n");
211                         return -1;
212                 }
213
214                 h->setVerboseLevel(getDebugLevel());
215
216                 // init the handler
217                 if(!h->initialize()) {
218                         debugFatal("Could not initialize transmit handler\n");
219                         return -1;
220                 }
221
222                 // register the stream with the handler
223                 if(h->registerStream(stream)) {
224                         debugFatal("Could not register transmit stream with handler\n");
225                         return -1;
226                 }
227
228                 // register the handler with the manager
229                 if(this->registerHandler(h)) {
230                         debugFatal("Could not register transmit handler with manager\n");
231                         return -1;
232                 }
233
234         }
235
236         m_IsoStreams.push_back(stream);
237
238         return 0;
239 }
240
241 int IsoHandlerManager::unregisterStream(IsoStream *stream)
242 {
243         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
244         assert(stream);
245
246         // make sure the stream isn't attached to a handler anymore
247     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
248           it != m_IsoHandlers.end();
249           ++it )
250     {
251                 if((*it)->isStreamRegistered(stream)) {
252                         (*it)->unregisterStream(stream);
253                 }
254     }
255
256         // clean up all handlers that aren't used
257         pruneHandlers();
258
259         // remove the stream from the registered streams list
260     for ( IsoStreamVectorIterator it = m_IsoStreams.begin();
261           it != m_IsoStreams.end();
262           ++it )
263     {
264         if ( *it == stream ) {
265             m_IsoStreams.erase(it);
266                         return 0;
267         }
268     }
269
270         return -1; //not found
271
272 }
273
274 void IsoHandlerManager::pruneHandlers() {
275         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
276         IsoHandlerVector toUnregister;
277
278         // find all handlers that are not in use
279     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
280           it != m_IsoHandlers.end();
281           ++it )
282     {
283                 if(!((*it)->inUse())) {
284                         toUnregister.push_back(*it);
285                 }
286     }
287         // delete them
288     for ( IsoHandlerVectorIterator it = toUnregister.begin();
289           it != toUnregister.end();
290           ++it )
291     {
292                 unregisterHandler(*it);
293     }
294
295 }
296
297 int IsoHandlerManager::startHandlers() {
298         return startHandlers(-1);
299 }
300
301 int IsoHandlerManager::startHandlers(int cycle) {
302         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
303
304     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
305           it != m_IsoHandlers.end();
306           ++it )
307     {
308                 (*it)->start(cycle);
309     }
310         return 0;
311 }
312
313 void IsoHandlerManager::stopHandlers() {
314         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
315
316     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
317           it != m_IsoHandlers.end();
318           ++it )
319     {
320                 (*it)->stop();
321     }
322
323 }
324
325
326 void IsoHandlerManager::dumpInfo() {
327         debugOutput( DEBUG_LEVEL_NORMAL, "Dumping IsoHandlerManager Stream handler information...\n");
328         int i=0;
329
330         // fill the fd map
331     for ( IsoHandlerVectorIterator it = m_IsoHandlers.begin();
332           it != m_IsoHandlers.end();
333           ++it )
334     {
335                 debugOutput( DEBUG_LEVEL_NORMAL, " Stream %d\n",i++);
336
337                 (*it)->dumpInfo();
338     }
339
340 }
341
342 } // end of namespace FreebobStreaming
343
Note: See TracBrowser for help on using the browser.