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

Revision 206, 12.4 kB (checked in by pieterpalmers, 18 years ago)

- end of another day... implemented the 'ports' that represent the demuxed data streams (audio, midi and control)

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         return 0;
208
209 }
210
211 int IsoRecvHandler::unregisterStream(IsoStream *stream)
212 {
213         assert(stream);
214         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
215
216         if(stream != m_Client) return -1; //not registered
217
218         m_Client=0;
219         return 0;
220
221 }
222
223 int IsoRecvHandler::start(int cycle)
224 {
225         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
226         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
227 }
228
229 int IsoRecvHandler::handleBusReset(unsigned int generation) {
230         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
231         //TODO: implement busreset
232         return 0;
233 }
234
235 /* ----------------- XMIT --------------- */
236
237 IsoXmitHandler::IsoXmitHandler(int port)
238                 : IsoHandler(port), m_prebuffers(0)
239 {
240         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
241
242 }
243 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
244                                unsigned int max_packet_size, int irq)
245                 : IsoHandler(port, buf_packets, max_packet_size,irq),
246                   m_speed(RAW1394_ISO_SPEED_400), m_prebuffers(0)
247 {
248         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
249
250 }
251 IsoXmitHandler::IsoXmitHandler(int port, unsigned int buf_packets,
252                                unsigned int max_packet_size, int irq,
253                                enum raw1394_iso_speed speed)
254                 : IsoHandler(port, buf_packets,max_packet_size,irq),
255                   m_speed(speed), m_prebuffers(0)
256 {
257         debugOutput( DEBUG_LEVEL_VERBOSE, "IsoXmitHandler enter...\n");
258
259 }
260
261 IsoXmitHandler::~IsoXmitHandler()
262 {
263         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
264         raw1394_iso_shutdown(m_handle);
265         raw1394_destroy_handle(m_handle);
266 }
267
268 bool
269 IsoXmitHandler::initialize() {
270
271         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
272         IsoHandler *base=static_cast<IsoHandler *>(this);
273
274         if(!(base->initialize())) {
275                 return false;
276         }
277
278         raw1394_set_userdata(m_handle, static_cast<void *>(this));
279
280         // this is a dummy init, to see if everything works
281         // the real init is done when a stream is registered
282         if(raw1394_iso_xmit_init(m_handle,
283                              iso_transmit_handler,
284                              m_buf_packets,
285                              m_max_packet_size,
286                                  0,
287                                  m_speed,
288                              m_irq_interval)) {
289                 debugFatal("Could not do xmit initialisation!\n" );
290
291                 return false;
292         }
293
294         return true;
295
296 }
297
298 enum raw1394_iso_disposition IsoXmitHandler::getPacket(unsigned char *data, unsigned int *length,
299                               unsigned char *tag, unsigned char *sy,
300                               int cycle, unsigned int dropped) {
301
302         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
303                      "sending packet: length=%d, cycle=%d\n",
304                      *length, cycle );
305         m_packetcount++;
306         m_dropped+=dropped;
307
308         if(m_Client) {
309         if(m_Client->getPacket(data, length, tag, sy, cycle, dropped, m_max_packet_size)) {
310 //                      return RAW1394_ISO_AGAIN;
311                 }
312         }
313
314         return RAW1394_ISO_OK;
315 }
316
317 // an xmit handler can have only one source IsoStream
318 int IsoXmitHandler::registerStream(IsoStream *stream)
319 {
320         assert(stream);
321         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
322
323         if (m_Client) {
324                 debugFatal("Already a registered client\n");
325                 return -1;
326         }
327
328         m_Client=stream;
329
330         raw1394_iso_shutdown(m_handle);
331
332         if(raw1394_iso_xmit_init(m_handle,
333                              iso_transmit_handler,
334                              m_buf_packets,
335                              m_max_packet_size,
336                                  m_Client->getChannel(),
337                                  m_speed,
338                              m_irq_interval)) {
339                 debugFatal("Could not do xmit initialisation!\n" );
340
341                 m_Client=0;
342
343                 return -1;
344         }
345
346         return 0;
347
348 }
349
350 int IsoXmitHandler::unregisterStream(IsoStream *stream)
351 {
352         assert(stream);
353         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
354
355         if(stream != m_Client) return -1; //not registered
356
357         m_Client=0;
358         return 0;
359
360 }
361
362 int IsoXmitHandler::start(int cycle)
363 {
364         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
365         return raw1394_iso_xmit_start(m_handle, cycle, m_prebuffers);
366 }
367
368 int IsoXmitHandler::handleBusReset(unsigned int generation) {
369         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
370         //TODO: implement busreset
371         return 0;
372 }
373
374 }
375
376 /* multichannel receive  */
377 #if 0
378 IsoRecvHandler::IsoRecvHandler(int port)
379                 : IsoHandler(port)
380 {
381         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
382 }
383 IsoRecvHandler::IsoRecvHandler(int port, unsigned int buf_packets,
384                                unsigned int max_packet_size, int irq)
385                 : IsoHandler(port, buf_packets,max_packet_size,irq)
386 {
387         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
388
389 }
390 IsoRecvHandler::~IsoRecvHandler()
391 {
392         raw1394_iso_shutdown(m_handle);
393
394 }
395
396 bool
397 IsoRecvHandler::initialize() {
398         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
399
400         IsoHandler *base=static_cast<IsoHandler *>(this);
401
402         if(!(base->initialize())) {
403                 return false;
404         }
405
406         raw1394_set_userdata(m_handle, static_cast<void *>(this));
407
408         if(raw1394_iso_multichannel_recv_init(m_handle,
409                                          iso_receive_handler,
410                                          m_buf_packets,
411                                          m_max_packet_size,
412                                          m_irq_interval)) {
413                 debugFatal("Could not do multichannel receive initialisation!\n" );
414
415                 return false;
416         }
417
418         return true;
419
420 }
421
422 enum raw1394_iso_disposition IsoRecvHandler::putPacket(unsigned char *data, unsigned int length,
423                               unsigned char channel, unsigned char tag, unsigned char sy,
424                                   unsigned int cycle, unsigned int dropped) {
425
426         debugOutput( DEBUG_LEVEL_VERY_VERBOSE,
427                      "received packet: length=%d, channel=%d, cycle=%d\n",
428                      length, channel, cycle );
429        
430         return RAW1394_ISO_OK;
431 }
432
433 // an recv handler can have multiple destination IsoStreams
434 // NOTE: this implementation even allows for already registered
435 // streams to be registered again.
436 int IsoRecvHandler::registerStream(IsoRecvStream *stream)
437 {
438         assert(stream);
439         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
440
441         m_Clients.push_back(stream);
442
443         listen(stream->getChannel());
444         return 0;
445
446 }
447
448 int IsoRecvHandler::unregisterStream(IsoRecvStream *stream)
449 {
450         assert(stream);
451         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
452
453     for ( IsoRecvStreamVectorIterator it = m_Clients.begin();
454           it != m_Clients.end();
455           ++it )
456     {
457         IsoRecvStream* s = *it;
458         if ( s == stream ) {
459                         unListen(s->getChannel());
460             m_Clients.erase(it);
461                         return 0;
462         }
463     }
464
465         return -1; //not found
466
467 }
468
469 void IsoRecvHandler::listen(int channel) {
470         int retval;
471         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
472
473         retval=raw1394_iso_recv_listen_channel(m_handle, channel);
474
475 }
476
477 void IsoRecvHandler::unListen(int channel) {
478         int retval;
479         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
480
481         retval=raw1394_iso_recv_unlisten_channel(m_handle, channel);
482
483 }
484
485 int IsoRecvHandler::start(int cycle)
486 {
487         debugOutput( DEBUG_LEVEL_VERBOSE, "enter...\n");
488         return raw1394_iso_recv_start(m_handle, cycle, -1, 0);
489 }
490 #endif
Note: See TracBrowser for help on using the browser.