source: roaraudio/roard/codecfilter_au.c @ 4005:f98a160c75f0

Last change on this file since 4005:f98a160c75f0 was 4005:f98a160c75f0, checked in by phi, 14 years ago

make write support work

File size: 7.4 KB
Line 
1//codecfilter_au.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2010
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 if ( !self )
37  return -1;
38
39 self->stream               = info;
40 self->vstream              = NULL;
41 self->opened               = 0;
42
43 *inst = (CODECFILTER_USERDATA_T) self;
44
45 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
46
47 s->info.codec = ROAR_CODEC_PCM_S_BE;
48
49 return 0;
50}
51
52int cf_au_close(CODECFILTER_USERDATA_T   inst) {
53// struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
54
55 if ( !inst )
56  return -1;
57
58 roar_mm_free(inst);
59 return 0;
60}
61
62int cf_au_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
63 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
64 int r = -1;
65 char tbuf[ROAR_AU_MIN_HEADER_LEN];
66 uint32_t * header = (uint32_t*)tbuf;
67 struct roar_stream * ps = ROAR_STREAM(self->stream);
68 struct roar_stream *  s;
69 struct roar_audio_info info;
70 char * extra_header;
71 int codec = -1;
72 int vid, fh;
73 int i;
74
75 if ( self->opened ) {
76  return stream_vio_s_read(self->stream, buf, len);
77 } else {
78  if (stream_vio_s_read(self->stream, tbuf, ROAR_AU_MIN_HEADER_LEN) != ROAR_AU_MIN_HEADER_LEN) {
79   return -1;
80  }
81
82  for (i = 0; i < ROAR_AU_MIN_HEADER_LEN/4; i++) {
83   header[i] = ROAR_NET2HOST32(header[i]);
84   ROAR_DBG("cf_au_read(inst=%p, buf=%p, len=%i): header[%i] = 0x%.8x", inst, buf, len, i, header[i]);
85  }
86
87
88  // test the header, is this really a AU stream?
89  if ( header[0] != ROAR_AU_MAGIC )
90   return -1;
91
92  if ( header[1] != ROAR_AU_MIN_HEADER_LEN ) {
93   header[1] -= ROAR_AU_MIN_HEADER_LEN;
94
95   if ( header[1] > 32*1024 ) // do not allow more than 32KiB header...
96    return -1;
97
98   if ( (extra_header = roar_mm_malloc(header[1])) == NULL )
99    return -1;
100
101   if ( stream_vio_s_read(self->stream, extra_header, header[1]) != header[1] ) {
102    roar_mm_free(extra_header);
103    return -1;
104   }
105
106   roar_mm_free(extra_header);
107  }
108
109  // TODO: write better code here!
110
111  if ( (fh = streams_get_fh(ps->id)) == -1 ) {
112   return -1;
113  }
114
115  if ( (vid = streams_new_virtual(ps->id, &(self->vstream))) == -1 ) {
116   return -1;
117  }
118
119  ROAR_DBG("cf_au_read(*): self->vstream=%p", self->vstream);
120
121  s = ROAR_STREAM(self->vstream);
122
123  s->info.rate = header[4];
124
125  s->info.channels = header[5];
126
127  switch (header[3]) {
128   case ROAR_AU_CID_MULAW:
129     s->info.bits  =  8;
130     codec         =  ROAR_CODEC_MULAW;
131    break;
132   case ROAR_AU_CID_ALAW:
133     s->info.bits  =  8;
134     codec         =  ROAR_CODEC_ALAW;
135    break;
136   case ROAR_AU_CID_PCM_S_8:
137     s->info.bits  =  8;
138     codec         =  ROAR_CODEC_PCM_S_BE;
139    break;
140   case ROAR_AU_CID_PCM_S_16:
141     s->info.bits  = 16;
142     codec         =  ROAR_CODEC_PCM_S_BE;
143    break;
144   case ROAR_AU_CID_PCM_S_24:
145     s->info.bits  = 24;
146     codec         =  ROAR_CODEC_PCM_S_BE;
147    break;
148   case ROAR_AU_CID_PCM_S_32:
149     s->info.bits  = 32;
150     codec         =  ROAR_CODEC_PCM_S_BE;
151    break;
152   default:
153     return -1;
154  }
155
156  s->info.codec             = codec;
157  self->vstream->codec_orgi = codec;
158
159  memcpy(&info, &(s->info), sizeof(struct roar_audio_info));
160
161  if ( streams_set_fh(vid, fh) == -1 ) {
162   return -1;
163  }
164
165/*
166  if ( roar_vio_open_pass(&(self->vstream->vio), &(self->stream->vio)) == -1 ) {
167   return -1;
168  }
169*/
170
171  memcpy(&(self->vstream->vio), &(self->stream->vio), sizeof(struct roar_vio_calls));
172
173  if ( streams_set_null_io(ps->id) == -1 ) {
174   return -1;
175  }
176
177  memcpy(&(ps->info), &info, sizeof(struct roar_audio_info));
178
179  self->opened = 1;
180
181  errno = EAGAIN;
182  return -1;
183 }
184
185 return r;
186}
187
188int cf_au_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
189 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
190 struct roar_stream         * s    = ROAR_STREAM(self->stream);
191 void     * headerdata;
192 uint32_t * header;
193 uint32_t codec;
194 int      sid;
195 int      i;
196
197 ROAR_DBG("cf_au_write(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
198 ROAR_DBG("cf_au_write(inst=%p, buf=%p, len=%i): self->opened=%i", inst, buf, len, self->opened);
199
200 if ( self->opened ) {
201  return stream_vio_s_write(self->stream, buf, len);
202 } else {
203
204  if ( s->fh == -1 ) {
205   errno = EAGAIN;
206   return -1;
207  }
208
209  sid = ROAR_STREAM(self->stream)->id;
210
211  if ( stream_prethru_destroy(sid) == -1 ) {
212   return -1;
213  }
214
215  if ( stream_prethru_add_data(sid, &headerdata, ROAR_AU_MIN_HEADER_LEN) == -1 ) {
216   return -1;
217  }
218
219  header = headerdata;
220
221  switch (s->info.codec) {
222   case ROAR_CODEC_PCM_S_BE:
223     switch (s->info.bits) {
224      case  8: codec = ROAR_AU_CID_PCM_S_8;  break;
225      case 16: codec = ROAR_AU_CID_PCM_S_16; break;
226      case 24: codec = ROAR_AU_CID_PCM_S_24; break;
227      case 32: codec = ROAR_AU_CID_PCM_S_32; break;
228      default:
229        ROAR_ERR("cf_au_write(*) bits per sample not supported!");
230        return -1;
231       break;
232     }
233    break;
234   default:
235     ROAR_ERR("cf_au_write(*) Codec not supported!: %s(%i)", roar_codec2str(s->info.codec), s->info.codec);
236     return -1;
237    break;
238  }
239
240  ROAR_DBG("cf_au_write(*) Codec supported!");
241
242  header[0] = ROAR_AU_MAGIC;
243  header[1] = ROAR_AU_MIN_HEADER_LEN;
244  header[2] = ROAR_AU_DATASIZE;
245  header[3] = codec;
246  header[4] = s->info.rate;
247  header[5] = s->info.channels;
248
249  for (i = 0; i < ROAR_AU_MIN_HEADER_LEN/4; i++)
250   header[i] = ROAR_HOST2NET32(header[i]);
251
252  if ( stream_vio_s_write(self->stream, header, ROAR_AU_MIN_HEADER_LEN) != ROAR_AU_MIN_HEADER_LEN )
253   return -1;
254
255  self->opened = 1;
256
257  errno = EAGAIN;
258//  return -1;
259
260  len = stream_vio_s_write(self->stream, buf, len);
261
262  cf_au_close(inst);
263  ROAR_STREAM_SERVER(s)->codecfilter = -1;
264
265  return len;
266
267//  return stream_vio_s_write(self->stream, buf, len);
268 }
269
270 return -1;
271}
272
273int cf_au_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
274 struct codecfilter_au_inst * self = (struct codecfilter_au_inst *) inst;
275 int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
276
277 cmd -= type;
278
279 ROAR_DBG("cf_au_ctl(*): command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
280                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
281
282 switch (cmd) {
283  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_VIRTUAL_DELETE):
284    streams_delete(ROAR_STREAM(self->stream)->id);
285    return 0;
286   break;
287  default:
288    ROAR_DBG("cf_au_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
289                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
290    return -1;
291 }
292
293 return -1;
294}
295
296#endif
297
298//ll
Note: See TracBrowser for help on using the repository browser.