source: roaraudio/roard/codecfilter_au.c @ 6056:8d4468a24909

Last change on this file since 6056:8d4468a24909 was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

File size: 7.5 KB
Line 
1//codecfilter_au.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2015
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifndef ROAR_WITHOUT_CF_AU
29
30int cf_au_open(CODECFILTER_USERDATA_T * inst, int codec,
31                                            struct roar_stream_server * info,
32                                            struct roar_codecfilter   * filter) {
33 struct codecfilter_au_inst * self = roar_mm_malloc(sizeof(struct codecfilter_au_inst));
34 struct roar_stream * s = ROAR_STREAM(info);
35
36 (void)codec, (void)filter;
37
38 if ( self == NULL )
39  return -1;
40
41 self->stream               = info;
42 self->vstream              = NULL;
43 self->opened               = 0;
44
45 *inst = (CODECFILTER_USERDATA_T) self;
46
47 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
48
49 s->info.codec = ROAR_CODEC_PCM_S_BE;
50
51 return 0;
52}
53
54int cf_au_close(CODECFILTER_USERDATA_T   inst) {
55// struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
56
57 if ( !inst )
58  return -1;
59
60 roar_mm_free(inst);
61 return 0;
62}
63
64int cf_au_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
65 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
66 int r = -1;
67 char tbuf[ROAR_AU_MIN_HEADER_LEN];
68 uint32_t * header = (uint32_t*)tbuf;
69 struct roar_stream * ps = ROAR_STREAM(self->stream);
70 struct roar_stream *  s;
71 struct roar_audio_info info;
72 char * extra_header;
73 int codec = -1;
74 int vid, fh;
75 int i;
76
77 if ( self->opened ) {
78  return stream_vio_s_read(self->stream, buf, len);
79 } else {
80  if (stream_vio_s_read(self->stream, tbuf, ROAR_AU_MIN_HEADER_LEN) != ROAR_AU_MIN_HEADER_LEN) {
81   return -1;
82  }
83
84  for (i = 0; i < ROAR_AU_MIN_HEADER_LEN/4; i++) {
85   header[i] = ROAR_NET2HOST32(header[i]);
86   ROAR_DBG("cf_au_read(inst=%p, buf=%p, len=%i): header[%i] = 0x%.8x", inst, buf, len, i, header[i]);
87  }
88
89
90  // test the header, is this really a AU stream?
91  if ( header[0] != ROAR_AU_MAGIC )
92   return -1;
93
94  if ( header[1] != ROAR_AU_MIN_HEADER_LEN ) {
95   header[1] -= ROAR_AU_MIN_HEADER_LEN;
96
97   if ( header[1] > (uint32_t)32768U ) // do not allow more than 32KiB header...
98    return -1;
99
100   if ( (extra_header = roar_mm_malloc(header[1])) == NULL )
101    return -1;
102
103   if ( stream_vio_s_read(self->stream, extra_header, header[1]) != (ssize_t)header[1] ) {
104    roar_mm_free(extra_header);
105    return -1;
106   }
107
108   roar_mm_free(extra_header);
109  }
110
111  // TODO: write better code here!
112
113  if ( (fh = streams_get_fh(ps->id)) == -1 ) {
114   return -1;
115  }
116
117  if ( (vid = streams_new_virtual(ps->id, &(self->vstream))) == -1 ) {
118   return -1;
119  }
120
121  ROAR_DBG("cf_au_read(*): self->vstream=%p", self->vstream);
122
123  s = ROAR_STREAM(self->vstream);
124
125  s->info.rate = header[4];
126
127  s->info.channels = header[5];
128
129  switch (header[3]) {
130   case ROAR_AU_CID_MULAW:
131     s->info.bits  =  8;
132     codec         =  ROAR_CODEC_MULAW;
133    break;
134   case ROAR_AU_CID_ALAW:
135     s->info.bits  =  8;
136     codec         =  ROAR_CODEC_ALAW;
137    break;
138   case ROAR_AU_CID_PCM_S_8:
139     s->info.bits  =  8;
140     codec         =  ROAR_CODEC_PCM_S_BE;
141    break;
142   case ROAR_AU_CID_PCM_S_16:
143     s->info.bits  = 16;
144     codec         =  ROAR_CODEC_PCM_S_BE;
145    break;
146   case ROAR_AU_CID_PCM_S_24:
147     s->info.bits  = 24;
148     codec         =  ROAR_CODEC_PCM_S_BE;
149    break;
150   case ROAR_AU_CID_PCM_S_32:
151     s->info.bits  = 32;
152     codec         =  ROAR_CODEC_PCM_S_BE;
153    break;
154   default:
155     return -1;
156  }
157
158  s->info.codec             = codec;
159  self->vstream->codec_orgi = codec;
160
161  memcpy(&info, &(s->info), sizeof(struct roar_audio_info));
162
163  if ( streams_set_fh(vid, fh) == -1 ) {
164   return -1;
165  }
166
167/*
168  if ( roar_vio_open_pass(&(self->vstream->vio), &(self->stream->vio)) == -1 ) {
169   return -1;
170  }
171*/
172
173  memcpy(&(self->vstream->vio), &(self->stream->vio), sizeof(struct roar_vio_calls));
174
175  if ( streams_set_null_io(ps->id) == -1 ) {
176   return -1;
177  }
178
179  memcpy(&(ps->info), &info, sizeof(struct roar_audio_info));
180
181  self->opened = 1;
182
183  errno = EAGAIN;
184  return -1;
185 }
186
187 return r;
188}
189
190int cf_au_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
191 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
192 struct roar_stream         * s    = ROAR_STREAM(self->stream);
193 void     * headerdata;
194 uint32_t * header;
195 uint32_t codec;
196 int      sid;
197 int      i;
198
199 ROAR_DBG("cf_au_write(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
200 ROAR_DBG("cf_au_write(inst=%p, buf=%p, len=%i): self->opened=%i", inst, buf, len, self->opened);
201
202 if ( self->opened ) {
203  return stream_vio_s_write(self->stream, buf, len);
204 } else {
205
206  if ( s->fh == -1 ) {
207   errno = EAGAIN;
208   return -1;
209  }
210
211  sid = ROAR_STREAM(self->stream)->id;
212
213  if ( stream_prethru_destroy(sid) == -1 ) {
214   return -1;
215  }
216
217  if ( stream_prethru_add_data(sid, &headerdata, ROAR_AU_MIN_HEADER_LEN) == -1 ) {
218   return -1;
219  }
220
221  header = headerdata;
222
223  switch (s->info.codec) {
224   case ROAR_CODEC_PCM_S_BE:
225     switch (s->info.bits) {
226      case  8: codec = ROAR_AU_CID_PCM_S_8;  break;
227      case 16: codec = ROAR_AU_CID_PCM_S_16; break;
228      case 24: codec = ROAR_AU_CID_PCM_S_24; break;
229      case 32: codec = ROAR_AU_CID_PCM_S_32; break;
230      default:
231        ROAR_ERR("cf_au_write(*) bits per sample not supported!");
232        return -1;
233       break;
234     }
235    break;
236   default:
237     ROAR_ERR("cf_au_write(*) Codec not supported!: %s(%i)", roar_codec2str(s->info.codec), s->info.codec);
238     return -1;
239    break;
240  }
241
242  ROAR_DBG("cf_au_write(*) Codec supported!");
243
244  header[0] = ROAR_AU_MAGIC;
245  header[1] = ROAR_AU_MIN_HEADER_LEN;
246  header[2] = ROAR_AU_DATASIZE;
247  header[3] = codec;
248  header[4] = s->info.rate;
249  header[5] = s->info.channels;
250
251  for (i = 0; i < ROAR_AU_MIN_HEADER_LEN/4; i++)
252   header[i] = ROAR_HOST2NET32(header[i]);
253
254  if ( stream_vio_s_write(self->stream, header, ROAR_AU_MIN_HEADER_LEN) != ROAR_AU_MIN_HEADER_LEN )
255   return -1;
256
257  self->opened = 1;
258
259  errno = EAGAIN;
260//  return -1;
261
262  len = stream_vio_s_write(self->stream, buf, len);
263
264  cf_au_close(inst);
265  ROAR_STREAM_SERVER(s)->codecfilter = -1;
266
267  return len;
268
269//  return stream_vio_s_write(self->stream, buf, len);
270 }
271
272 return -1;
273}
274
275int cf_au_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
276 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
277 int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
278
279 (void)data;
280
281 cmd -= type;
282
283 ROAR_DBG("cf_au_ctl(*): command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
284                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
285
286 switch (cmd) {
287  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_VIRTUAL_DELETE):
288    streams_delete(ROAR_STREAM(self->stream)->id);
289    return 0;
290   break;
291  default:
292    ROAR_DBG("cf_au_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
293                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
294    return -1;
295 }
296
297 return -1;
298}
299
300#endif
301
302//ll
Note: See TracBrowser for help on using the repository browser.