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

Revision 212, 9.1 kB (checked in by pieterpalmers, 18 years ago)

- end of day 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) 2005,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 "AmdtpStreamProcessor.h"
30 #include <assert.h>
31
32
33 namespace FreebobStreaming {
34
35 IMPL_DEBUG_MODULE( AmdtpTransmitStreamProcessor, AmdtpTransmitStreamProcessor, DEBUG_LEVEL_NORMAL );
36 IMPL_DEBUG_MODULE( AmdtpReceiveStreamProcessor, AmdtpReceiveStreamProcessor, DEBUG_LEVEL_NORMAL );
37
38
39 /* transmit */
40 AmdtpTransmitStreamProcessor::AmdtpTransmitStreamProcessor(int channel, int port, int framerate, int dimension)
41         : TransmitStreamProcessor(channel, port, framerate), m_dimension(dimension) {
42
43
44 }
45
46 AmdtpTransmitStreamProcessor::~AmdtpTransmitStreamProcessor() {
47         freebob_ringbuffer_free(m_event_buffer);
48         free(m_cluster_buffer);
49 }
50
51 int AmdtpTransmitStreamProcessor::init() {
52         int fdf=0, syt_interval=0;
53         int m_dbs=0;
54         int err=0;
55
56         // call the parent init
57         // this has to be done before allocating the buffers,
58         // because this sets the buffersizes from the processormanager
59         if((err=TransmitStreamProcessor::init())) {
60                 debugFatal("Could not allocate memory event ringbuffer (%d)",err);
61                 return err;
62         }
63
64
65         switch (m_framerate) {
66         case 32000:
67                 syt_interval = 8;
68                 fdf = IEC61883_FDF_SFC_32KHZ;
69                 break;
70         case 44100:
71                 syt_interval = 8;
72                 fdf = IEC61883_FDF_SFC_44K1HZ;
73                 break;
74         default:
75         case 48000:
76                 syt_interval = 8;
77                 fdf = IEC61883_FDF_SFC_48KHZ;
78                 break;
79         case 88200:
80                 syt_interval = 16;
81                 fdf = IEC61883_FDF_SFC_88K2HZ;
82                 break;
83         case 96000:
84                 syt_interval = 16;
85                 fdf = IEC61883_FDF_SFC_96KHZ;
86                 break;
87         case 176400:
88                 syt_interval = 32;
89                 fdf = IEC61883_FDF_SFC_176K4HZ;
90                 break;
91         case 192000:
92                 syt_interval = 32;
93                 fdf = IEC61883_FDF_SFC_192KHZ;
94                 break;
95         }
96        
97         iec61883_cip_init (
98                 &m_cip_status,
99                 IEC61883_FMT_AMDTP,
100                 fdf,
101                 m_framerate,
102                 m_dbs,
103                 syt_interval);
104
105         // allocate the event buffer
106         if( !(m_event_buffer=freebob_ringbuffer_create(
107                         (m_dimension * m_nb_buffers * m_period) * sizeof(quadlet_t)))) {
108                 debugFatal("Could not allocate memory event ringbuffer");
109 //              return -ENOMEM;
110                 return -1;
111         }
112
113         // allocate the temporary cluster buffer
114         if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) {
115                 debugFatal("Could not allocate temporary cluster buffer");
116                 freebob_ringbuffer_free(m_event_buffer);
117                 return -1;
118 //              return -ENOMEM;
119         }
120
121         // call the parent init
122         return TransmitStreamProcessor::init();
123 }
124
125 void AmdtpTransmitStreamProcessor::setVerboseLevel(int l) {
126         setDebugLevel(l);
127         TransmitStreamProcessor::setVerboseLevel(l);
128 }
129
130
131 int AmdtpTransmitStreamProcessor::getPacket(unsigned char *data, unsigned int *length,
132                       unsigned char *tag, unsigned char *sy,
133                       int cycle, unsigned int dropped, unsigned int max_length) {
134
135         struct iec61883_packet *packet = (struct iec61883_packet *) data;
136        
137         // construct the packet cip
138         int nevents = iec61883_cip_fill_header (getNodeId(), &m_cip_status, packet);
139
140         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
141
142         if (!(nevents > 0)) {
143                 if (m_cip_status.mode == IEC61883_MODE_BLOCKING_EMPTY) {
144                         *length = 8;
145                         return (int)RAW1394_ISO_OK;
146                 }
147                 else {
148                         nevents = m_cip_status.syt_interval;
149                 }
150         }
151        
152         int read_size=nevents*sizeof(quadlet_t)*m_dimension;
153
154         if ((freebob_ringbuffer_read(m_event_buffer,(char *)(data+8),read_size)) <
155                                 read_size)
156         {
157                 debugWarning("Transmit buffer underrun\n");
158                
159                 // signal underrun
160                 m_xruns++;
161
162                 retval=RAW1394_ISO_DEFER;
163                 *length=0;
164
165         } else {
166                 retval=RAW1394_ISO_OK;
167                 *length = read_size + 8;
168                
169                 // TODO: we should do all packet buffered processing here
170 //              freebob_streaming_encode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
171         }
172        
173         *tag = IEC61883_TAG_WITH_CIP;
174         *sy = 0;
175        
176         // update the frame counter
177         m_framecounter+=nevents;
178
179         return (int)retval;
180
181 }
182
183 void AmdtpTransmitStreamProcessor::reset() {
184
185         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
186
187         // reset the event buffer, discard all content
188         freebob_ringbuffer_reset(m_event_buffer);
189        
190         // reset all non-device specific stuff
191         // i.e. the iso stream and the associated ports
192         TransmitStreamProcessor::reset();
193 }
194
195 void AmdtpTransmitStreamProcessor::prepare() {
196
197         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
198
199         // prepare all non-device specific stuff
200         // i.e. the iso stream and the associated ports
201         TransmitStreamProcessor::prepare();
202
203         // after preparing, we should transfer the port buffer contents to the event buffer
204         int i=m_nb_buffers;
205         while(i--) transfer();
206
207 }
208
209 int AmdtpTransmitStreamProcessor::transfer() {
210
211         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
212 // TODO: implement
213
214         return 0;
215 }
216
217 /* --------------------- RECEIVE ----------------------- */
218
219 AmdtpReceiveStreamProcessor::AmdtpReceiveStreamProcessor(int channel, int port, int framerate, int dimension)
220         : ReceiveStreamProcessor(channel, port, framerate), m_dimension(dimension) {
221
222
223 }
224
225 AmdtpReceiveStreamProcessor::~AmdtpReceiveStreamProcessor() {
226         freebob_ringbuffer_free(m_event_buffer);
227         free(m_cluster_buffer);
228
229 }
230
231 int AmdtpReceiveStreamProcessor::init() {
232         int err=0;
233         // call the parent init
234         // this has to be done before allocating the buffers,
235         // because this sets the buffersizes from the processormanager
236         if((err=ReceiveStreamProcessor::init())) {
237                 debugFatal("Could not allocate memory event ringbuffer (%d)",err);
238                 return err;
239         }
240
241         if( !(m_event_buffer=freebob_ringbuffer_create(
242                         (m_dimension * m_nb_buffers * m_period) * sizeof(quadlet_t)))) {
243                 debugFatal("Could not allocate memory event ringbuffer");
244 //              return -ENOMEM;
245                 return -1;
246         }
247
248         // allocate the temporary cluster buffer
249         if( !(m_cluster_buffer=(char *)calloc(m_dimension,sizeof(quadlet_t)))) {
250                 debugFatal("Could not allocate temporary cluster buffer");
251                 freebob_ringbuffer_free(m_event_buffer);
252 //              return -ENOMEM;
253                 return -1;
254         }
255
256         return 0;
257 }
258
259 int AmdtpReceiveStreamProcessor::putPacket(unsigned char *data, unsigned int length,
260                       unsigned char channel, unsigned char tag, unsigned char sy,
261                           unsigned int cycle, unsigned int dropped) {
262
263         enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
264        
265         struct iec61883_packet *packet = (struct iec61883_packet *) data;
266         assert(packet);
267        
268         if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
269                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
270
271                 int write_size=nevents*sizeof(quadlet_t)*m_dimension;
272                 // add the data payload to the ringbuffer
273                
274                 if (freebob_ringbuffer_write(m_event_buffer,(char *)(data+8),write_size) < write_size)
275                 {
276                         debugWarning("Buffer overrun!\n");
277                         m_xruns++;
278
279                         retval=RAW1394_ISO_DEFER;
280                 } else {
281                         retval=RAW1394_ISO_OK;
282                         // we cannot offload midi encoding due to the need for a dbc value
283 //                      freebob_streaming_decode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
284                 }
285
286                 debugOutput(DEBUG_LEVEL_VERY_VERBOSE,
287                         "RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d)\n",
288                         channel, packet->fdf,
289                         packet->syt,
290                         packet->dbs,
291                         packet->dbc,
292                         packet->fmt,
293                         length,
294                         ((length / sizeof (quadlet_t)) - 2)/packet->dbs);
295                
296                 // update the frame counter
297                 m_framecounter+=nevents;
298                
299         } else {
300                 // discard packet
301                 // can be important for sync though
302         }
303
304         return (int)retval;
305 }
306
307 void AmdtpReceiveStreamProcessor::setVerboseLevel(int l) {
308         setDebugLevel(l);
309         ReceiveStreamProcessor::setVerboseLevel(l);
310
311 }
312
313
314 void AmdtpReceiveStreamProcessor::reset() {
315
316         debugOutput( DEBUG_LEVEL_VERBOSE, "Resetting...\n");
317
318         // reset the event buffer, discard all content
319         freebob_ringbuffer_reset(m_event_buffer);
320        
321         // reset all non-device specific stuff
322         // i.e. the iso stream and the associated ports
323         ReceiveStreamProcessor::reset();
324 }
325
326 void AmdtpReceiveStreamProcessor::prepare() {
327
328         debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n");
329
330         // prepare all non-device specific stuff
331         // i.e. the iso stream and the associated ports
332         ReceiveStreamProcessor::prepare();
333 }
334
335 int AmdtpReceiveStreamProcessor::transfer() {
336
337         debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n");
338 // TODO: implement
339        
340         int read_size=m_period*sizeof(quadlet_t)*m_dimension;
341         char *dummybuffer=(char *)calloc(sizeof(quadlet_t),m_period*m_dimension);
342         if (freebob_ringbuffer_read(m_event_buffer,(char *)(dummybuffer),read_size) < read_size) {
343                 debugWarning("Could not read from event buffer\n");
344         }
345         free(dummybuffer);
346
347
348         return 0;
349 }
350
351
352 } // end of namespace FreebobStreaming
Note: See TracBrowser for help on using the browser.