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

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