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

Revision 225, 12.7 kB (checked in by pieterpalmers, 18 years ago)

- reworked the code
- this runs on a bebob device, as long as no xruns occur
- partly documented

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 "IsoHandler.h"
30 #include "IsoStream.h"
31 #include <errno.h>
32 #include <netinet/in.h>
33 #include <assert.h>
34
35
36 #include <iostream>
37 using namespace std;
38
39
40 namespace FreebobStreaming
41 {
42
43 IMPL_DEBUG_MODULE( IsoHandler, IsoHandler, DEBUG_LEVEL_NORMAL );
44
45 /* the C callbacks */
46 enum raw1394_iso_disposition
47 IsoXmitHandler::iso_transmit_handler(raw1394handle_t handle,
48                 unsigned char *data, unsigned int *length,
49                 unsigned char *tag, unsigned char *sy,
50                 int cycle, unsigned int dropped) {
51
52         IsoXmitHandler *xmitHandler=static_cast<IsoXmitHandler *>(raw1394_get_userdata(handle));
53         assert(xmitHandler);
54
55         return xmitHandler->getPacket(data, length, tag, sy, cycle, dropped);
56 }
57
58 enum raw1394_iso_disposition
59 IsoRecvHandler::iso_receive_handler(raw1394handle_t handle, unsigned char *data,
60                                                 unsigned int length, unsigned char channel,
61                                                 unsigned char tag, unsigned char sy, unsigned int cycle,
62                                                 unsigned int dropped) {
63
64         IsoRecvHandler *recvHandler=static_cast<IsoRecvHandler *>(raw1394_get_userdata(handle));
65         assert(recvHandler);
66
67         return recvHandler->putPacket(data, length, channel, tag, sy, cycle, dropped);
68 }
69
70 int IsoHandler::busreset_handler(raw1394handle_t handle, unsigned int generation)
71 {       
72         debugOutput( DEBUG_LEVEL_VERBOSE, "Busreset happened, generation %d...\n", generation);
73
74         IsoHandler *handler=static_cast<IsoHandler *>(raw1394_get_userdata(handle));
75         assert(handler);
76         return handler->handleBusReset(generation);
77 }
78
79
80 /* Base class implementation */
81 bool
82 IsoHandler::init()
83 {
84         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoHandler (%p) enter...\n",this);
85
86         m_handle = raw1394_new_handle_on_port( m_port );
87         if ( !m_handle ) {
88                 if ( !errno ) {
89                         cerr << "libraw1394 not compatible" << endl;
90                 } else {
91                         perror( "IsoHandler::Initialize: Could not get 1394 handle" );
92                         cerr << "Is ieee1394 and raw1394 driver loaded?" << endl;
93                 }
94                 return false;
95         }
96        
97         raw1394_set_userdata(m_handle, static_cast<void *>(this));
98        
99         if(raw1394_busreset_notify (m_handle, RAW1394_NOTIFY_ON)) {
100                 debugWarning("Could not enable busreset notification.\n");
101                 debugWarning(" Error message: %s\n",strerror(errno));
102         }
103        
104         raw1394_set_bus_reset_handler(m_handle, busreset_handler);
105
106         return true;
107 }
108
109 bool IsoHandler::stop()
110 {
111         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
112         raw1394_iso_stop(m_handle);
113         return true;
114 };
115
116 void IsoHandler::dumpInfo()
117 {
118
119         int channel=-1;
120         if (m_Client) channel=m_Client->getChannel();
121
122         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Handler type    : %s\n",
123              (this->getType()==EHT_Receive ? "Receive" : "Transmit"));
124         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Port, Channel  : %d, %d\n",
125              m_port, channel);
126         debugOutputShort( DEBUG_LEVEL_NORMAL, "  Packet count   : %d (%d dropped)\n\n",
127              this->getPacketCount(), this->getDroppedCount());
128
129 };
130
131 void IsoHandler::setVerboseLevel(int l)
132 {
133         setDebugLevel(l);
134 }
135
136 bool IsoHandler::registerStream(IsoStream *stream)
137 {
138         assert(stream);
139         debugOutput( DEBUG_LEVEL_VERBOSE, "registering stream (%p)\n", stream);
140
141         if (m_Client) {
142                 debugFatal( "Generic IsoHandlers can have only one client\n"); 
143                 return false;
144         }
145
146         m_Client=stream;
147
148         m_Client->setHandler(this);
149
150         return true;
151
152 }
153
154 bool IsoHandler::unregisterStream(IsoStream *stream)
155 {
156         assert(stream);
157         debugOutput( DEBUG_LEVEL_VERBOSE, "unregistering stream (%p)\n", stream);
158
159         if(stream != m_Client) {
160                 debugFatal( "no client registered\n"); 
161                 return false;
162         }
163
164         m_Client->clearHandler();
165        
166         m_Client=0;
167         return true;
168
169 }
170
171 /* Child class implementations */
172
173 IsoRecvHandler::IsoRecvHandler(int port)
174                 : IsoHandler(port)
175 {
176         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
177 }
178 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
179                                unsigned int max_packet_size, int irq)
180                 : IsoHandler(port, buf_packets,max_packet_size,irq)
181 {
182         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
183
184 }
185 IsoRecvHandler::~IsoRecvHandler()
186 {
187         raw1394_iso_shutdown(m_handle);
188         raw1394_destroy_handle(m_handle);
189
190 }
191
192 bool
193 IsoRecvHandler::init() {
194         debugOutput( DEBUG_LEVEL_VERBOSE, "init recv handler %p\n",this);
195
196         if(!(IsoHandler::init())) {
197                 return false;
198         }
199         return true;
200
201 }
202
203 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
204                               unsigned char channel, unsigned char tag, unsigned char sy,
205                                   unsigned int cycle, unsigned int dropped) {
206
207         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
208                      "received packet: length=%d, channel=%d, cycle=%d\n",
209                      length, channel, cycle );
210         m_packetcount++;
211         m_dropped+=dropped;
212
213         if(m_Client) {
214                 if(m_Client->putPacket(data, length, channel, tag, sy, cycle, dropped)) {
215 //                      return RAW1394_ISO_AGAIN;
216                 }
217         }
218        
219         return RAW1394_ISO_OK;
220 }
221
222 bool IsoRecvHandler::prepare()
223 {
224         raw1394_iso_shutdown(m_handle);
225        
226         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso receive handler (%p)\n",this);
227         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
228         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
229         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
230         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
231
232         if(raw1394_iso_recv_init(m_handle,   iso_receive_handler,
233                                          m_buf_packets,
234                                          m_max_packet_size,
235                                              m_Client->getChannel(),
236                                              RAW1394_DMA_BUFFERFILL,
237                                          m_irq_interval)) {
238                 debugFatal("Could not do receive initialisation!\n" );
239
240                 return false;
241         }
242         return true;
243 }
244
245 bool IsoRecvHandler::start(int cycle)
246 {
247         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
248        
249         if(raw1394_iso_recv_start(m_handle, cycle, -1, 0)) {
250                 debugFatal("Could not start receive handler (%s)\n",strerror(errno));
251                 return false;
252         }
253         return true;
254 }
255
256 int IsoRecvHandler::handleBusReset(unsigned int generation) {
257         debugOutput( DEBUG_LEVEL_VERBOSE, "handle bus reset...\n");
258         //TODO: implement busreset
259         return 0;
260 }
261
262 /* ----------------- XMIT --------------- */
263
264 IsoXmitHandler::IsoXmitHandler(int port)
265                 : IsoHandler(port), m_prebuffers(0)
266 {
267         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
268
269 }
270 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
271                                unsigned int max_packet_size, int irq)
272                 : IsoHandler(port, buf_packets, max_packet_size,irq),
273                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
274 {
275         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
276
277 }
278 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
279                                unsigned int max_packet_size, int irq,
280                                enum raw1394_iso_speed speed)
281                 : IsoHandler(port, buf_packets,max_packet_size,irq),
282                   m_speed(speed), m_prebuffers(0)
283 {
284         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
285
286 }
287
288 IsoXmitHandler::~IsoXmitHandler()
289 {
290         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
291         raw1394_iso_shutdown(m_handle);
292         raw1394_destroy_handle(m_handle);
293 }
294
295 bool
296 IsoXmitHandler::init() {
297
298         debugOutput( DEBUG_LEVEL_VERBOSE, "init xmit handler %p\n",this);
299
300         if(!(IsoHandler::init())) {
301                 return false;
302         }
303
304         return true;
305
306 }
307
308 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length,
309                               unsigned char *tag, unsigned char *sy,
310                               int cycle, unsigned int dropped) {
311
312         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
313                      "sending packet: length=%d, cycle=%d\n",
314                      *length, cycle );
315         m_packetcount++;
316         m_dropped+=dropped;
317
318         if(m_Client) {
319         if(m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size)) {
320 //                      return RAW1394_ISO_AGAIN;
321                 }
322         }
323
324         return RAW1394_ISO_OK;
325 }
326
327 bool IsoXmitHandler::prepare()
328 {
329         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing iso transmit handler (%p, client=%p)\n",this,m_Client);
330        
331 //      raw1394_iso_shutdown(m_handle);
332         debugOutput( DEBUG_LEVEL_VERBOSE, " Buffers         : %d \n",m_buf_packets);
333         debugOutput( DEBUG_LEVEL_VERBOSE, " Max Packet size : %d \n",m_max_packet_size);
334         debugOutput( DEBUG_LEVEL_VERBOSE, " Channel         : %d \n",m_Client->getChannel());
335         debugOutput( DEBUG_LEVEL_VERBOSE, " Speed           : %d \n",m_speed);
336         debugOutput( DEBUG_LEVEL_VERBOSE, " Irq interval    : %d \n",m_irq_interval);
337
338         if(raw1394_iso_xmit_init(m_handle,
339                              iso_transmit_handler,
340                              m_buf_packets,
341                              m_max_packet_size,
342                                  m_Client->getChannel(),
343                                  m_speed,
344                              m_irq_interval)) {
345                 debugFatal("Could not do xmit initialisation!\n" );
346
347                 return false;
348         }
349
350         return true;
351 }
352
353 bool IsoXmitHandler::start(int cycle)
354 {
355         debugOutput( DEBUG_LEVEL_VERBOSE, "start on cycle %d\n", cycle);
356         if(raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers)) {
357                 debugFatal("Could not start xmit handler (%s)\n",strerror(errno));
358                 return false;
359         }
360         return true;
361 }
362
363 int IsoXmitHandler::handleBusReset(unsigned int generation) {
364         debugOutput( DEBUG_LEVEL_VERBOSE, "bus reset...\n");
365         //TODO: implement busreset
366         return 0;
367 }
368
369 }
370
371 /* multichannel receive  */
372 #if 0
373 IsoRecvHandler::IsoRecvHandler(int port)
374                 : IsoHandler(port)
375 {
376         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
377 }
378 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
379                                unsigned int max_packet_size, int irq)
380                 : IsoHandler(port, buf_packets,max_packet_size,irq)
381 {
382         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
383
384 }
385 IsoRecvHandler::~IsoRecvHandler()
386 {
387         raw1394_iso_shutdown(m_handle);
388
389 }
390
391 bool
392 IsoRecvHandler::initialize() {
393         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
394
395         IsoHandler *base=static_cast<IsoHandler *>(this);
396
397         if(!(base->initialize())) {
398                 return false;
399         }
400
401         raw1394_set_userdata(m_handle, static_cast<void *>(this));
402
403         if(raw1394_iso_multichannel_recv_init(m_handle,
404                                          iso_receive_handler,
405                                          m_buf_packets,
406                                          m_max_packet_size,
407                                          m_irq_interval)) {
408                 debugFatal("Could not do multichannel receive initialisation!\n" );
409
410                 return false;
411         }
412
413         return true;
414
415 }
416
417 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
418                               unsigned char channel, unsigned char tag, unsigned char sy,
419                                   unsigned int cycle, unsigned int dropped) {
420
421         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
422                      "received packet: length=%d, channel=%d, cycle=%d\n",
423                      length, channel, cycle );
424        
425         return RAW1394_ISO_OK;
426 }
427
428 // an recv handler can have multiple destination IsoStreams
429 // NOTE: this implementation even allows for already registered
430 // streams to be registered again.
431 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
432 {
433         assert(stream);
434         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
435
436         m_Clients.push_back(stream);
437
438         listen(stream->getChannel());
439         return 0;
440
441 }
442
443 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
444 {
445         assert(stream);
446         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
447
448     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
449           it != m_Clients.end();
450           ++it )
451     {
452         IsoRecvStream* s = *it;
453         if ( s == stream ) {
454                         unListen(s->getChannel());
455             m_Clients.erase(it);
456                         return 0;
457         }
458     }
459
460         return -1; //not found
461
462 }
463
464 void IsoRecvHandler::listen(int channel) {
465         int retval;
466         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
467
468         retval=raw1394_iso_recv_listen_channel(m_handle, channel);
469
470 }
471
472 void IsoRecvHandler::unListen(int channel) {
473         int retval;
474         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
475
476         retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
477
478 }
479
480 int IsoRecvHandler::start(int cycle)
481 {
482         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
483         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
484 }
485 #endif
Note: See TracBrowser for help on using the browser.