source: roaraudio/roard/codecfilter_wave.c @ 2816:b9e357b0dc43

Last change on this file since 2816:b9e357b0dc43 was 2816:b9e357b0dc43, checked in by phi, 15 years ago

added prethru support and updated list of codecs a bit

File size: 6.2 KB
Line 
1//codecfilter_wave.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
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, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25#include "roard.h"
26
27#ifndef ROAR_WITHOUT_CF_WAVE
28
29int cf_wave_open(CODECFILTER_USERDATA_T * inst, int codec,
30                                            struct roar_stream_server * info,
31                                            struct roar_codecfilter   * filter) {
32 struct codecfilter_wave_inst * self = malloc(sizeof(struct codecfilter_wave_inst));
33 struct roar_stream * s = ROAR_STREAM(info);
34
35 if ( !self )
36  return -1;
37
38 self->stream               = info;
39 self->vstream              = NULL;
40 self->opened               = 0;
41
42 *inst = (CODECFILTER_USERDATA_T) self;
43
44 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
45 return 0;
46}
47
48int cf_wave_close(CODECFILTER_USERDATA_T   inst) {
49// struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
50
51 if ( !inst )
52  return -1;
53
54 free(inst);
55 return 0;
56}
57
58int cf_wave_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
59 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
60 int r = -1;
61 char tbuf[44];
62 struct roar_stream * ps = ROAR_STREAM(self->stream);
63 struct roar_stream *  s;
64 struct roar_audio_info info;
65 uint16_t tmp16;
66 uint32_t tmp32;
67 int codec = -1;
68 int vid, fh;
69
70 if ( self->opened ) {
71  return stream_vio_s_read(self->stream, buf, len);
72 } else {
73  if (stream_vio_s_read(self->stream, tbuf, 44) != 44) {
74   return -1;
75  }
76
77  // TODO: write better code here!
78
79  if ( (fh = streams_get_fh(ps->id)) == -1 ) {
80   return -1;
81  }
82
83  if ( (vid = streams_new_virtual(ps->id, &(self->vstream))) == -1 ) {
84   return -1;
85  }
86
87  ROAR_DBG("cf_wave_read(*): self->vstream=%p", self->vstream);
88
89  s = ROAR_STREAM(self->vstream);
90
91  memcpy(&tmp32, tbuf+24, 4);
92  s->info.rate = ROAR_LE2HOST32(tmp32);
93
94  memcpy(&tmp16, tbuf+22, 2);
95  s->info.channels = ROAR_LE2HOST16(tmp16);
96
97  memcpy(&tmp16, tbuf+34, 2);
98  s->info.bits = ROAR_LE2HOST16(tmp16);
99
100  memcpy(&tmp16, tbuf+20, 2);
101
102  switch (ROAR_LE2HOST16(tmp16)) {
103   case ROAR_RIFF_WAVE_CID_PCM:
104     if ( s->info.bits == 8 ) {
105      codec = ROAR_CODEC_PCM_U_LE;
106     } else {
107      codec = ROAR_CODEC_PCM_S_LE;
108     }
109    break;
110   case ROAR_RIFF_WAVE_CID_ALAW:
111     codec = ROAR_CODEC_ALAW;
112    break;
113   case ROAR_RIFF_WAVE_CID_MULAW:
114     codec = ROAR_CODEC_MULAW;
115    break;
116   case ROAR_RIFF_WAVE_CID_IEEE_FLOAT:
117   default:
118     return -1;
119  }
120
121   s->info.codec            = codec;
122  self->vstream->codec_orgi = codec;
123
124  memcpy(&info, &(s->info), sizeof(struct roar_audio_info));
125
126  if ( streams_set_fh(vid, fh) == -1 ) {
127   return -1;
128  }
129
130/*
131  if ( roar_vio_open_pass(&(self->vstream->vio), &(self->stream->vio)) == -1 ) {
132   return -1;
133  }
134*/
135
136  memcpy(&(self->vstream->vio), &(self->stream->vio), sizeof(struct roar_vio_calls));
137
138  if ( streams_set_null_io(ps->id) == -1 ) {
139   return -1;
140  }
141
142  memcpy(&(ps->info), &info, sizeof(struct roar_audio_info));
143
144  self->opened = 1;
145
146  errno = EAGAIN;
147  return -1;
148 }
149
150 return r;
151}
152
153int cf_wave_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
154 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
155 struct roar_stream           * s    = ROAR_STREAM(self->stream);
156 void   * header;
157 int32_t  tmp32;
158 int16_t  tmp16;
159 int16_t  bits;
160 int16_t  codec;
161 int      sid;
162
163 ROAR_DBG("cf_wave_write(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
164 ROAR_DBG("cf_wave_write(inst=%p, buf=%p, len=%i): self->opened=%i", inst, buf, len, self->opened);
165
166 if ( self->opened ) {
167  return stream_vio_s_write(self->stream, buf, len);
168 } else {
169
170  if ( s->fh == -1 ) {
171   errno = EAGAIN;
172   return -1;
173  }
174
175  sid = ROAR_STREAM(self->stream)->id;
176
177  if ( stream_prethru_destroy(sid) == -1 ) {
178   return -1;
179  }
180
181  if ( stream_prethru_add_data(sid, &header, 44) == -1 ) {
182   return -1;
183  }
184
185  memcpy(header   , "RIFF\367\377\377\177WAVEfmt \020", 17);
186  memcpy(header+36, "data\313\377\377\177", 8);
187
188  switch (s->info.codec) {
189   case ROAR_CODEC_PCM_S_LE:
190     codec = 0x0001;
191    break;
192   default:
193     ROAR_ERR("cf_wave_write(*) Codec not supported!");
194     return -1;
195    break;
196  }
197
198  ROAR_DBG("cf_wave_write(*) Codec supported!");
199
200  bits = s->info.bits;
201  memcpy(header+24, &(s->info.rate    ), 4);
202  memcpy(header+22, &(s->info.channels), 2);
203  memcpy(header+34, &bits, 2);
204
205  tmp16 = s->info.channels * bits / 8;
206  memcpy(header+32, &tmp16, 2);
207  tmp32 = tmp16 * s->info.rate;
208  memcpy(header+28, &tmp32, 4);
209  memcpy(header+20, &codec, 2);
210
211  if ( stream_vio_s_write(self->stream, header, 44) != 44 )
212   return -1;
213
214  self->opened = 1;
215
216  errno = EAGAIN;
217//  return -1;
218
219  len = stream_vio_s_write(self->stream, buf, len);
220
221  cf_wave_close(inst);
222  ROAR_STREAM_SERVER(s)->codecfilter = -1;
223
224  return len;
225
226//  return stream_vio_s_write(self->stream, buf, len);
227 }
228
229 return -1;
230}
231
232int cf_wave_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
233 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
234 int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
235
236 cmd -= type;
237
238 ROAR_DBG("cf_wave_ctl(*): command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
239                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
240
241 switch (cmd) {
242  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_VIRTUAL_DELETE):
243    streams_delete(ROAR_STREAM(self->stream)->id);
244    return 0;
245   break;
246  default:
247    ROAR_DBG("cf_wave_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
248                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
249    return -1;
250 }
251
252 return -1;
253}
254
255#endif
256
257//ll
Note: See TracBrowser for help on using the repository browser.