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

Revision 207, 12.5 kB (checked in by pieterpalmers, 18 years ago)

- temp commit

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