Sun Aug 28 01:17:48 2011 UTC ()
ANSIfy. Add static. Add __dead.


(joerg)
diff -r1.19 -r1.20 src/usr.bin/audio/common/audio.c
diff -r1.16 -r1.17 src/usr.bin/audio/common/libaudio.h
diff -r1.6 -r1.7 src/usr.bin/audio/common/sun.c
diff -r1.9 -r1.10 src/usr.bin/audio/common/wav.c
diff -r1.38 -r1.39 src/usr.bin/audio/ctl/ctl.c
diff -r1.53 -r1.54 src/usr.bin/audio/play/play.c
diff -r1.50 -r1.51 src/usr.bin/audio/record/record.c

cvs diff -r1.19 -r1.20 src/usr.bin/audio/common/audio.c (switch to unified diff)

--- src/usr.bin/audio/common/audio.c 2008/05/29 14:51:27 1.19
+++ src/usr.bin/audio/common/audio.c 2011/08/28 01:17:47 1.20
@@ -1,244 +1,234 @@ @@ -1,244 +1,234 @@
1/* $NetBSD: audio.c,v 1.19 2008/05/29 14:51:27 mrg Exp $ */ 1/* $NetBSD: audio.c,v 1.20 2011/08/28 01:17:47 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999 Matthew R. Green 4 * Copyright (c) 1999 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * XXX this is slightly icky in places... 30 * XXX this is slightly icky in places...
31 */ 31 */
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34#ifndef lint 34#ifndef lint
35__RCSID("$NetBSD: audio.c,v 1.19 2008/05/29 14:51:27 mrg Exp $"); 35__RCSID("$NetBSD: audio.c,v 1.20 2011/08/28 01:17:47 joerg Exp $");
36#endif 36#endif
37 37
38 38
39#include <sys/types.h> 39#include <sys/types.h>
40#include <sys/audioio.h> 40#include <sys/audioio.h>
41#include <sys/ioctl.h> 41#include <sys/ioctl.h>
42#include <sys/time.h> 42#include <sys/time.h>
43 43
44#include <ctype.h> 44#include <ctype.h>
45#include <err.h> 45#include <err.h>
46#include <stdio.h> 46#include <stdio.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "libaudio.h" 50#include "libaudio.h"
51 51
52/* what format am i? */ 52/* what format am i? */
53 53
54struct { 54static const struct {
55 const char *fname; 55 const char *fname;
56 int fno; 56 int fno;
57} formats[] = { 57} formats[] = {
58 { "sunau", AUDIO_FORMAT_SUN }, 58 { "sunau", AUDIO_FORMAT_SUN },
59 { "au", AUDIO_FORMAT_SUN }, 59 { "au", AUDIO_FORMAT_SUN },
60 { "sun", AUDIO_FORMAT_SUN }, 60 { "sun", AUDIO_FORMAT_SUN },
61 { "wav", AUDIO_FORMAT_WAV }, 61 { "wav", AUDIO_FORMAT_WAV },
62 { "wave", AUDIO_FORMAT_WAV }, 62 { "wave", AUDIO_FORMAT_WAV },
63 { "riff", AUDIO_FORMAT_WAV }, 63 { "riff", AUDIO_FORMAT_WAV },
64 { "no", AUDIO_FORMAT_NONE }, 64 { "no", AUDIO_FORMAT_NONE },
65 { "none", AUDIO_FORMAT_NONE }, 65 { "none", AUDIO_FORMAT_NONE },
66 { NULL, -1 } 66 { NULL, -1 }
67}; 67};
68 68
69int 69int
70audio_format_from_str(str) 70audio_format_from_str(char *str)
71 char *str; 
72{ 71{
73 int i; 72 int i;
74 73
75 for (i = 0; formats[i].fname; i++) 74 for (i = 0; formats[i].fname; i++)
76 if (strcasecmp(formats[i].fname, str) == 0) 75 if (strcasecmp(formats[i].fname, str) == 0)
77 break; 76 break;
78 return (formats[i].fno); 77 return (formats[i].fno);
79} 78}
80 79
81 80
82 81
83/* back and forth between encodings */ 82/* back and forth between encodings */
84struct { 83static const struct {
85 const char *ename; 84 const char *ename;
86 int eno; 85 int eno;
87} encs[] = { 86} encs[] = {
88 { AudioEmulaw, AUDIO_ENCODING_ULAW }, 87 { AudioEmulaw, AUDIO_ENCODING_ULAW },
89 { "ulaw", AUDIO_ENCODING_ULAW }, 88 { "ulaw", AUDIO_ENCODING_ULAW },
90 { AudioEalaw, AUDIO_ENCODING_ALAW }, 89 { AudioEalaw, AUDIO_ENCODING_ALAW },
91 { AudioEslinear, AUDIO_ENCODING_SLINEAR }, 90 { AudioEslinear, AUDIO_ENCODING_SLINEAR },
92 { "linear", AUDIO_ENCODING_SLINEAR }, 91 { "linear", AUDIO_ENCODING_SLINEAR },
93 { AudioEulinear, AUDIO_ENCODING_ULINEAR }, 92 { AudioEulinear, AUDIO_ENCODING_ULINEAR },
94 { AudioEadpcm, AUDIO_ENCODING_ADPCM }, 93 { AudioEadpcm, AUDIO_ENCODING_ADPCM },
95 { "ADPCM", AUDIO_ENCODING_ADPCM }, 94 { "ADPCM", AUDIO_ENCODING_ADPCM },
96 { AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE }, 95 { AudioEslinear_le, AUDIO_ENCODING_SLINEAR_LE },
97 { "linear_le", AUDIO_ENCODING_SLINEAR_LE }, 96 { "linear_le", AUDIO_ENCODING_SLINEAR_LE },
98 { AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE }, 97 { AudioEulinear_le, AUDIO_ENCODING_ULINEAR_LE },
99 { AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE }, 98 { AudioEslinear_be, AUDIO_ENCODING_SLINEAR_BE },
100 { "linear_be", AUDIO_ENCODING_SLINEAR_BE }, 99 { "linear_be", AUDIO_ENCODING_SLINEAR_BE },
101 { AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE }, 100 { AudioEulinear_be, AUDIO_ENCODING_ULINEAR_BE },
102 { AudioEmpeg_l1_stream, AUDIO_ENCODING_MPEG_L1_STREAM }, 101 { AudioEmpeg_l1_stream, AUDIO_ENCODING_MPEG_L1_STREAM },
103 { AudioEmpeg_l1_packets,AUDIO_ENCODING_MPEG_L1_PACKETS }, 102 { AudioEmpeg_l1_packets,AUDIO_ENCODING_MPEG_L1_PACKETS },
104 { AudioEmpeg_l1_system, AUDIO_ENCODING_MPEG_L1_SYSTEM }, 103 { AudioEmpeg_l1_system, AUDIO_ENCODING_MPEG_L1_SYSTEM },
105 { AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM }, 104 { AudioEmpeg_l2_stream, AUDIO_ENCODING_MPEG_L2_STREAM },
106 { AudioEmpeg_l2_packets,AUDIO_ENCODING_MPEG_L2_PACKETS }, 105 { AudioEmpeg_l2_packets,AUDIO_ENCODING_MPEG_L2_PACKETS },
107 { AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM }, 106 { AudioEmpeg_l2_system, AUDIO_ENCODING_MPEG_L2_SYSTEM },
108 { NULL, -1 } 107 { NULL, -1 }
109}; 108};
110 109
111 110
112const char * 111const char *
113audio_enc_from_val(val) 112audio_enc_from_val(int val)
114 int val; 
115{ 113{
116 int i; 114 int i;
117 115
118 for (i = 0; encs[i].ename; i++) 116 for (i = 0; encs[i].ename; i++)
119 if (encs[i].eno == val) 117 if (encs[i].eno == val)
120 break; 118 break;
121 return (encs[i].ename); 119 return (encs[i].ename);
122} 120}
123 121
124int 122int
125audio_enc_to_val(enc) 123audio_enc_to_val(const char *enc)
126 const char *enc; 
127{ 124{
128 int i; 125 int i;
129 126
130 for (i = 0; encs[i].ename; i++) 127 for (i = 0; encs[i].ename; i++)
131 if (strcmp(encs[i].ename, enc) == 0) 128 if (strcmp(encs[i].ename, enc) == 0)
132 break; 129 break;
133 if (encs[i].ename) 130 if (encs[i].ename)
134 return (encs[i].eno); 131 return (encs[i].eno);
135 else 132 else
136 return (AUDIO_ENOENT); 133 return (AUDIO_ENOENT);
137} 134}
138 135
139void 136void
140decode_int(arg, intp) 137decode_int(const char *arg, int *intp)
141 const char *arg; 
142 int *intp; 
143{ 138{
144 char *ep; 139 char *ep;
145 int ret; 140 int ret;
146 141
147 ret = (int)strtoul(arg, &ep, 10); 142 ret = (int)strtoul(arg, &ep, 10);
148 143
149 if (ep[0] == '\0') { 144 if (ep[0] == '\0') {
150 *intp = ret; 145 *intp = ret;
151 return; 146 return;
152 } 147 }
153 errx(1, "argument `%s' not a valid integer", arg); 148 errx(1, "argument `%s' not a valid integer", arg);
154} 149}
155 150
156void 151void
157decode_time(arg, tvp) 152decode_time(const char *arg, struct timeval *tvp)
158 const char *arg; 
159 struct timeval *tvp; 
160{ 153{
161 char *s, *colon, *dot; 154 char *s, *colon, *dot;
162 char *copy = strdup(arg); 155 char *copy = strdup(arg);
163 int first; 156 int first;
164 157
165 if (copy == NULL) 158 if (copy == NULL)
166 err(1, "could not allocate a copy of %s", arg); 159 err(1, "could not allocate a copy of %s", arg);
167 160
168 tvp->tv_sec = tvp->tv_usec = 0; 161 tvp->tv_sec = tvp->tv_usec = 0;
169 s = copy; 162 s = copy;
170  163
171 /* handle [hh:]mm:ss.dd */ 164 /* handle [hh:]mm:ss.dd */
172 if ((colon = strchr(s, ':')) != NULL) { 165 if ((colon = strchr(s, ':')) != NULL) {
173 *colon++ = '\0'; 166 *colon++ = '\0';
174 decode_int(s, &first); 167 decode_int(s, &first);
175 tvp->tv_sec = first * 60; /* minutes */ 168 tvp->tv_sec = first * 60; /* minutes */
176 s = colon; 169 s = colon;
177 170
178 if ((colon = strchr(s, ':')) != NULL) { 171 if ((colon = strchr(s, ':')) != NULL) {
179 *colon++ = '\0'; 172 *colon++ = '\0';
180 decode_int(s, &first); 173 decode_int(s, &first);
181 tvp->tv_sec += first; /* minutes and hours */ 174 tvp->tv_sec += first; /* minutes and hours */
182 tvp->tv_sec *= 60; 175 tvp->tv_sec *= 60;
183 s = colon; 176 s = colon;
184 } 177 }
185 } 178 }
186 if ((dot = strchr(s, '.')) != NULL) { 179 if ((dot = strchr(s, '.')) != NULL) {
187 int i, base = 100000; 180 int i, base = 100000;
188 181
189 *dot++ = '\0'; 182 *dot++ = '\0';
190 183
191 for (i = 0; i < 6; i++, base /= 10) { 184 for (i = 0; i < 6; i++, base /= 10) {
192 if (!dot[i]) 185 if (!dot[i])
193 break; 186 break;
194 if (!isdigit((unsigned char)dot[i])) 187 if (!isdigit((unsigned char)dot[i]))
195 errx(1, "argument `%s' is not a value time specification", arg); 188 errx(1, "argument `%s' is not a value time specification", arg);
196 tvp->tv_usec += base * (dot[i] - '0'); 189 tvp->tv_usec += base * (dot[i] - '0');
197 } 190 }
198 } 191 }
199 decode_int(s, &first); 192 decode_int(s, &first);
200 tvp->tv_sec += first; 193 tvp->tv_sec += first;
201 194
202 free(copy); 195 free(copy);
203} 196}
204 197
205/* 198/*
206 * decode a string into an encoding value. 199 * decode a string into an encoding value.
207 */ 200 */
208void 201void
209decode_encoding(arg, encp) 202decode_encoding(const char *arg, int *encp)
210 const char *arg; 
211 int *encp; 
212{ 203{
213 size_t len; 204 size_t len;
214 int i; 205 int i;
215 206
216 len = strlen(arg); 207 len = strlen(arg);
217 for (i = 0; encs[i].ename; i++) 208 for (i = 0; encs[i].ename; i++)
218 if (strncmp(encs[i].ename, arg, len) == 0) { 209 if (strncmp(encs[i].ename, arg, len) == 0) {
219 *encp = encs[i].eno; 210 *encp = encs[i].eno;
220 return; 211 return;
221 } 212 }
222 errx(1, "unknown encoding `%s'", arg); 213 errx(1, "unknown encoding `%s'", arg);
223} 214}
224 215
225const char *const audio_errlist[] = { 216static const char *const audio_errlist[] = {
226 "error zero", /* nothing? */ 217 "error zero", /* nothing? */
227 "no audio entry", /* AUDIO_ENOENT */ 218 "no audio entry", /* AUDIO_ENOENT */
228 "short header", /* AUDIO_ESHORTHDR */ 219 "short header", /* AUDIO_ESHORTHDR */
229 "unsupported WAV format", /* AUDIO_EWAVUNSUPP */ 220 "unsupported WAV format", /* AUDIO_EWAVUNSUPP */
230 "bad (unsupported) WAV PCM format", /* AUDIO_EWAVBADPCM */ 221 "bad (unsupported) WAV PCM format", /* AUDIO_EWAVBADPCM */
231 "no WAV audio data", /* AUDIO_EWAVNODATA */ 222 "no WAV audio data", /* AUDIO_EWAVNODATA */
232 "internal error", /* AUDIO_EINTERNAL */ 223 "internal error", /* AUDIO_EINTERNAL */
233}; 224};
234 225
235const char * 226const char *
236audio_errstring(errval) 227audio_errstring(int errval)
237 int errval; 
238{ 228{
239 229
240 errval = -errval; 230 errval = -errval;
241 if (errval < 1 || errval > AUDIO_MAXERRNO) 231 if (errval < 1 || errval > AUDIO_MAXERRNO)
242 return "Invalid error"; 232 return "Invalid error";
243 return audio_errlist[errval]; 233 return audio_errlist[errval];
244} 234}

cvs diff -r1.16 -r1.17 src/usr.bin/audio/common/libaudio.h (switch to unified diff)

--- src/usr.bin/audio/common/libaudio.h 2009/06/18 02:37:27 1.16
+++ src/usr.bin/audio/common/libaudio.h 2011/08/28 01:17:47 1.17
@@ -1,215 +1,217 @@ @@ -1,215 +1,217 @@
1/* $NetBSD: libaudio.h,v 1.16 2009/06/18 02:37:27 mrg Exp $ */ 1/* $NetBSD: libaudio.h,v 1.17 2011/08/28 01:17:47 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2009 Matthew R. Green 4 * Copyright (c) 1999, 2009 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * audio formats 30 * audio formats
31 */ 31 */
32#define AUDIO_FORMAT_DEFAULT -1 32#define AUDIO_FORMAT_DEFAULT -1
33#define AUDIO_FORMAT_NONE 1 33#define AUDIO_FORMAT_NONE 1
34#define AUDIO_FORMAT_SUN 2 34#define AUDIO_FORMAT_SUN 2
35#define AUDIO_FORMAT_WAV 3 35#define AUDIO_FORMAT_WAV 3
36 36
37int audio_format_from_str (char *); 37int audio_format_from_str (char *);
38 38
39/* 39/*
40 * We copy the Sun/NeXT on-disk audio header format and document what 40 * We copy the Sun/NeXT on-disk audio header format and document what
41 * we know of it here. 41 * we know of it here.
42 * 42 *
43 * The header size appears to be an offset to where the data really 43 * The header size appears to be an offset to where the data really
44 * begins, rather than defining the real length of the audio header. 44 * begins, rather than defining the real length of the audio header.
45 * The Sun/NeXT audio format seems to only use 24 bytes of data (with 45 * The Sun/NeXT audio format seems to only use 24 bytes of data (with
46 * an additional 8 bytes of nuls written, padding it to 32 bytes). 46 * an additional 8 bytes of nuls written, padding it to 32 bytes).
47 * 47 *
48 * If the size of the audio data is unknown (eg, reading from a pipe) 48 * If the size of the audio data is unknown (eg, reading from a pipe)
49 * the Sun demo audio tools place AUDIO_UNKNOWN_SIZE in the 49 * the Sun demo audio tools place AUDIO_UNKNOWN_SIZE in the
50 * `data_size' member. 50 * `data_size' member.
51 * 51 *
52 * For stereo data, the channels appear to be interleaved with the 52 * For stereo data, the channels appear to be interleaved with the
53 * left channel first. For more channels, who knows? 53 * left channel first. For more channels, who knows?
54 */ 54 */
55 55
56/* 56/*
57 * This is the Sun/NeXT audio file magic value. Note that it 57 * This is the Sun/NeXT audio file magic value. Note that it
58 * is also `.snd' in ASCII. 58 * is also `.snd' in ASCII.
59 */ 59 */
60#define AUDIO_FILE_MAGIC ((u_int32_t)0x2e736e64) 60#define AUDIO_FILE_MAGIC ((u_int32_t)0x2e736e64)
61#define AUDIO_UNKNOWN_SIZE ((unsigned)(~0)) 61#define AUDIO_UNKNOWN_SIZE ((unsigned)(~0))
62 62
63typedef struct { 63typedef struct {
64 u_int32_t magic; 64 u_int32_t magic;
65 u_int32_t hdr_size; /* header size; in bytes */ 65 u_int32_t hdr_size; /* header size; in bytes */
66 u_int32_t data_size; /* optional; in bytes */ 66 u_int32_t data_size; /* optional; in bytes */
67 u_int32_t encoding; /* see below */ 67 u_int32_t encoding; /* see below */
68 u_int32_t sample_rate; /* per second */ 68 u_int32_t sample_rate; /* per second */
69 u_int32_t channels; /* number of interleaved channels */ 69 u_int32_t channels; /* number of interleaved channels */
70} sun_audioheader; 70} sun_audioheader;
71 71
72#define Audio_filehdr sun_audioheader /* SunOS compat(?) */ 72#define Audio_filehdr sun_audioheader /* SunOS compat(?) */
73 73
74/* 74/*
75 * these are the types of "encoding" for above. taken from the 75 * these are the types of "encoding" for above. taken from the
76 * SunOS <multimedia/audio_filehdr.h>. 76 * SunOS <multimedia/audio_filehdr.h>.
77 */ 77 */
78#define AUDIO_FILE_ENCODING_MULAW_8 1 78#define AUDIO_FILE_ENCODING_MULAW_8 1
79#define AUDIO_FILE_ENCODING_LINEAR_8 2 79#define AUDIO_FILE_ENCODING_LINEAR_8 2
80#define AUDIO_FILE_ENCODING_LINEAR_16 3 80#define AUDIO_FILE_ENCODING_LINEAR_16 3
81#define AUDIO_FILE_ENCODING_LINEAR_24 4 81#define AUDIO_FILE_ENCODING_LINEAR_24 4
82#define AUDIO_FILE_ENCODING_LINEAR_32 5 82#define AUDIO_FILE_ENCODING_LINEAR_32 5
83#define AUDIO_FILE_ENCODING_FLOAT 6 83#define AUDIO_FILE_ENCODING_FLOAT 6
84#define AUDIO_FILE_ENCODING_DOUBLE 7 84#define AUDIO_FILE_ENCODING_DOUBLE 7
85#define AUDIO_FILE_ENCODING_ADPCM_G721 23 85#define AUDIO_FILE_ENCODING_ADPCM_G721 23
86#define AUDIO_FILE_ENCODING_ADPCM_G722 24 86#define AUDIO_FILE_ENCODING_ADPCM_G722 24
87#define AUDIO_FILE_ENCODING_ADPCM_G723_3 25 87#define AUDIO_FILE_ENCODING_ADPCM_G723_3 25
88#define AUDIO_FILE_ENCODING_ADPCM_G723_5 26 88#define AUDIO_FILE_ENCODING_ADPCM_G723_5 26
89#define AUDIO_FILE_ENCODING_ALAW_8 27 89#define AUDIO_FILE_ENCODING_ALAW_8 27
90 90
91const char *audio_enc_from_val (int); 91const char *audio_enc_from_val (int);
92int audio_enc_to_val (const char *); 92int audio_enc_to_val (const char *);
93 93
94int audio_sun_to_encoding (int, u_int *, u_int *); 94int audio_sun_to_encoding (int, u_int *, u_int *);
95int audio_encoding_to_sun (int, int, int *); 95int audio_encoding_to_sun (int, int, int *);
96 96
97/* 97/*
98 * M$ WAV files, info gleamed from sox sources 98 * M$ WAV files, info gleamed from sox sources
99 */ 99 */
100 100
101/* 101/*
102 * This is the WAV audio file magic value. Note that it 102 * This is the WAV audio file magic value. Note that it
103 * is also `RIFF' and `WAVE' in ASCII. 103 * is also `RIFF' and `WAVE' in ASCII.
104 */ 104 */
105#define WAVAUDIO_FILE_MAGIC_RIFF ((u_int32_t)0x52494646) 105#define WAVAUDIO_FILE_MAGIC_RIFF ((u_int32_t)0x52494646)
106#define WAVAUDIO_FILE_MAGIC_WAVE ((u_int32_t)0x57415645) 106#define WAVAUDIO_FILE_MAGIC_WAVE ((u_int32_t)0x57415645)
107#define WAVAUDIO_FILE_MAGIC_FMT ((u_int32_t)0x666d7420) 107#define WAVAUDIO_FILE_MAGIC_FMT ((u_int32_t)0x666d7420)
108#define WAVAUDIO_FILE_MAGIC_DATA ((u_int32_t)0x64617461) 108#define WAVAUDIO_FILE_MAGIC_DATA ((u_int32_t)0x64617461)
109 109
110/* purloined from public Microsoft RIFF docs via sox or mplayer */ 110/* purloined from public Microsoft RIFF docs via sox or mplayer */
111#define WAVE_FORMAT_UNKNOWN (0x0000) 111#define WAVE_FORMAT_UNKNOWN (0x0000)
112#define WAVE_FORMAT_PCM (0x0001) 112#define WAVE_FORMAT_PCM (0x0001)
113#define WAVE_FORMAT_ADPCM (0x0002) 113#define WAVE_FORMAT_ADPCM (0x0002)
114#define WAVE_FORMAT_ALAW (0x0006) 114#define WAVE_FORMAT_ALAW (0x0006)
115#define WAVE_FORMAT_MULAW (0x0007) 115#define WAVE_FORMAT_MULAW (0x0007)
116#define WAVE_FORMAT_OKI_ADPCM (0x0010) 116#define WAVE_FORMAT_OKI_ADPCM (0x0010)
117#define WAVE_FORMAT_IMA_ADPCM (0x0011) 117#define WAVE_FORMAT_IMA_ADPCM (0x0011)
118#define WAVE_FORMAT_DIGISTD (0x0015) 118#define WAVE_FORMAT_DIGISTD (0x0015)
119#define WAVE_FORMAT_DIGIFIX (0x0016) 119#define WAVE_FORMAT_DIGIFIX (0x0016)
120#define WAVE_FORMAT_DOLBY_AC2 (0x0030) 120#define WAVE_FORMAT_DOLBY_AC2 (0x0030)
121#define WAVE_FORMAT_GSM610 (0x0031) 121#define WAVE_FORMAT_GSM610 (0x0031)
122#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b) 122#define WAVE_FORMAT_ROCKWELL_ADPCM (0x003b)
123#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c) 123#define WAVE_FORMAT_ROCKWELL_DIGITALK (0x003c)
124#define WAVE_FORMAT_G721_ADPCM (0x0040) 124#define WAVE_FORMAT_G721_ADPCM (0x0040)
125#define WAVE_FORMAT_G728_CELP (0x0041) 125#define WAVE_FORMAT_G728_CELP (0x0041)
126#define WAVE_FORMAT_MPEG (0x0050) 126#define WAVE_FORMAT_MPEG (0x0050)
127#define WAVE_FORMAT_MPEGLAYER3 (0x0055) 127#define WAVE_FORMAT_MPEGLAYER3 (0x0055)
128#define WAVE_FORMAT_G726_ADPCM (0x0064) 128#define WAVE_FORMAT_G726_ADPCM (0x0064)
129#define WAVE_FORMAT_G722_ADPCM (0x0065) 129#define WAVE_FORMAT_G722_ADPCM (0x0065)
130#define IBM_FORMAT_MULAW (0x0101) 130#define IBM_FORMAT_MULAW (0x0101)
131#define IBM_FORMAT_ALAW (0x0102) 131#define IBM_FORMAT_ALAW (0x0102)
132#define IBM_FORMAT_ADPCM (0x0103) 132#define IBM_FORMAT_ADPCM (0x0103)
133#define WAVE_FORMAT_EXTENSIBLE (0xfffe) 133#define WAVE_FORMAT_EXTENSIBLE (0xfffe)
134 134
135const char *wav_enc_from_val (int); 135const char *wav_enc_from_val (int);
136 136
137typedef struct { 137typedef struct {
138 char name[4]; 138 char name[4];
139 u_int32_t len; 139 u_int32_t len;
140} wav_audioheaderpart; 140} wav_audioheaderpart;
141 141
142typedef struct { 142typedef struct {
143 u_int16_t tag; 143 u_int16_t tag;
144 u_int16_t channels; 144 u_int16_t channels;
145 u_int32_t sample_rate; 145 u_int32_t sample_rate;
146 u_int32_t avg_bps; 146 u_int32_t avg_bps;
147 u_int16_t alignment; 147 u_int16_t alignment;
148 u_int16_t bits_per_sample; 148 u_int16_t bits_per_sample;
149} __packed wav_audioheaderfmt; 149} __packed wav_audioheaderfmt;
150 150
151typedef struct { 151typedef struct {
152 u_int16_t len; 152 u_int16_t len;
153 u_int16_t valid_bits; 153 u_int16_t valid_bits;
154 u_int32_t speaker_pos_mask; 154 u_int32_t speaker_pos_mask;
155 u_int16_t sub_tag; 155 u_int16_t sub_tag;
156 u_int8_t dummy[14]; 156 u_int8_t dummy[14];
157} __packed wav_audiohdrextensible; 157} __packed wav_audiohdrextensible;
158 158
159/* returns size of header, or -ve for failure */ 159/* returns size of header, or -ve for failure */
160ssize_t audio_wav_parse_hdr (void *, size_t, u_int *, u_int *, u_int *, u_int *, size_t *); 160ssize_t audio_wav_parse_hdr (void *, size_t, u_int *, u_int *, u_int *, u_int *, size_t *);
161 161
 162extern int verbose;
 163
162/* 164/*
163 * audio routine error codes 165 * audio routine error codes
164 */ 166 */
165#define AUDIO_ENOENT -1 /* no such audio format */ 167#define AUDIO_ENOENT -1 /* no such audio format */
166#define AUDIO_ESHORTHDR -2 /* short header */ 168#define AUDIO_ESHORTHDR -2 /* short header */
167#define AUDIO_EWAVUNSUPP -3 /* WAV: unsupported file */ 169#define AUDIO_EWAVUNSUPP -3 /* WAV: unsupported file */
168#define AUDIO_EWAVBADPCM -4 /* WAV: bad PCM bps */ 170#define AUDIO_EWAVBADPCM -4 /* WAV: bad PCM bps */
169#define AUDIO_EWAVNODATA -5 /* WAV: missing data */ 171#define AUDIO_EWAVNODATA -5 /* WAV: missing data */
170#define AUDIO_EINTERNAL -6 /* internal error */ 172#define AUDIO_EINTERNAL -6 /* internal error */
171 173
172#define AUDIO_MAXERRNO 5 174#define AUDIO_MAXERRNO 5
173 175
174/* and something to get a string associated with this error */ 176/* and something to get a string associated with this error */
175const char *audio_errstring (int); 177const char *audio_errstring (int);
176 178
177/* 179/*
178 * generic routines? 180 * generic routines?
179 */ 181 */
180void decode_int (const char *, int *); 182void decode_int (const char *, int *);
181void decode_time (const char *, struct timeval *); 183void decode_time (const char *, struct timeval *);
182void decode_encoding (const char *, int *); 184void decode_encoding (const char *, int *);
183 185
184/* 186/*
185 * get/put 16/32 bits of big/little endian data 187 * get/put 16/32 bits of big/little endian data
186 */ 188 */
187#include <sys/types.h> 189#include <sys/types.h>
188#include <machine/endian.h> 190#include <machine/endian.h>
189#include <machine/bswap.h> 191#include <machine/bswap.h>
190 192
191#if BYTE_ORDER == BIG_ENDIAN 193#if BYTE_ORDER == BIG_ENDIAN
192 194
193#define getle16(v) bswap16(v) 195#define getle16(v) bswap16(v)
194#define getle32(v) bswap32(v) 196#define getle32(v) bswap32(v)
195#define getbe16(v) (v) 197#define getbe16(v) (v)
196#define getbe32(v) (v) 198#define getbe32(v) (v)
197 199
198#define putle16(x,v) (x) = bswap16(v) 200#define putle16(x,v) (x) = bswap16(v)
199#define putle32(x,v) (x) = bswap32(v) 201#define putle32(x,v) (x) = bswap32(v)
200#define putbe16(x,v) (x) = (v) 202#define putbe16(x,v) (x) = (v)
201#define putbe32(x,v) (x) = (v) 203#define putbe32(x,v) (x) = (v)
202 204
203#else 205#else
204 206
205#define getle16(v) (v) 207#define getle16(v) (v)
206#define getle32(v) (v) 208#define getle32(v) (v)
207#define getbe16(v) bswap16(v) 209#define getbe16(v) bswap16(v)
208#define getbe32(v) bswap32(v) 210#define getbe32(v) bswap32(v)
209 211
210#define putle16(x,v) (x) = (v) 212#define putle16(x,v) (x) = (v)
211#define putle32(x,v) (x) = (v) 213#define putle32(x,v) (x) = (v)
212#define putbe16(x,v) (x) = bswap16(v) 214#define putbe16(x,v) (x) = bswap16(v)
213#define putbe32(x,v) (x) = bswap32(v) 215#define putbe32(x,v) (x) = bswap32(v)
214 216
215#endif 217#endif

cvs diff -r1.6 -r1.7 src/usr.bin/audio/common/sun.c (switch to unified diff)

--- src/usr.bin/audio/common/sun.c 2008/05/29 14:51:27 1.6
+++ src/usr.bin/audio/common/sun.c 2011/08/28 01:17:47 1.7
@@ -1,114 +1,108 @@ @@ -1,114 +1,108 @@
1/* $NetBSD: sun.c,v 1.6 2008/05/29 14:51:27 mrg Exp $ */ 1/* $NetBSD: sun.c,v 1.7 2011/08/28 01:17:47 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002 Matthew R. Green 4 * Copyright (c) 2002 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * XXX this is slightly icky in places... 30 * XXX this is slightly icky in places...
31 */ 31 */
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34#ifndef lint 34#ifndef lint
35__RCSID("$NetBSD: sun.c,v 1.6 2008/05/29 14:51:27 mrg Exp $"); 35__RCSID("$NetBSD: sun.c,v 1.7 2011/08/28 01:17:47 joerg Exp $");
36#endif 36#endif
37 37
38 38
39#include <sys/types.h> 39#include <sys/types.h>
40#include <sys/audioio.h> 40#include <sys/audioio.h>
41#include <sys/ioctl.h> 41#include <sys/ioctl.h>
42#include <sys/time.h> 42#include <sys/time.h>
43 43
44#include <ctype.h> 44#include <ctype.h>
45#include <err.h> 45#include <err.h>
46#include <stdio.h> 46#include <stdio.h>
47#include <stdlib.h> 47#include <stdlib.h>
48#include <string.h> 48#include <string.h>
49 49
50#include "libaudio.h" 50#include "libaudio.h"
51 51
52/* 52/*
53 * SunOS/NeXT .au format helpers 53 * SunOS/NeXT .au format helpers
54 */ 54 */
55struct { 55static const struct {
56 int file_encoding; 56 int file_encoding;
57 int encoding; 57 int encoding;
58 int precision; 58 int precision;
59} file2sw_encodings[] = { 59} file2sw_encodings[] = {
60 { AUDIO_FILE_ENCODING_MULAW_8, AUDIO_ENCODING_ULAW, 8 }, 60 { AUDIO_FILE_ENCODING_MULAW_8, AUDIO_ENCODING_ULAW, 8 },
61 { AUDIO_FILE_ENCODING_LINEAR_8, AUDIO_ENCODING_SLINEAR_BE, 8 }, 61 { AUDIO_FILE_ENCODING_LINEAR_8, AUDIO_ENCODING_SLINEAR_BE, 8 },
62 { AUDIO_FILE_ENCODING_LINEAR_16, AUDIO_ENCODING_SLINEAR_BE, 16 }, 62 { AUDIO_FILE_ENCODING_LINEAR_16, AUDIO_ENCODING_SLINEAR_BE, 16 },
63 { AUDIO_FILE_ENCODING_LINEAR_24, AUDIO_ENCODING_SLINEAR_BE, 24 }, 63 { AUDIO_FILE_ENCODING_LINEAR_24, AUDIO_ENCODING_SLINEAR_BE, 24 },
64 { AUDIO_FILE_ENCODING_LINEAR_32, AUDIO_ENCODING_SLINEAR_BE, 32 }, 64 { AUDIO_FILE_ENCODING_LINEAR_32, AUDIO_ENCODING_SLINEAR_BE, 32 },
65#if 0 65#if 0
66 /* 66 /*
67 * we should make some of these available. the, eg ultrasparc, port 67 * we should make some of these available. the, eg ultrasparc, port
68 * can use the VIS instructions (if available) do do some of these 68 * can use the VIS instructions (if available) do do some of these
69 * mpeg ones. 69 * mpeg ones.
70 */ 70 */
71 { AUDIO_FILE_ENCODING_FLOAT, AUDIO_ENCODING_ULAW, 32 }, 71 { AUDIO_FILE_ENCODING_FLOAT, AUDIO_ENCODING_ULAW, 32 },
72 { AUDIO_FILE_ENCODING_DOUBLE, AUDIO_ENCODING_ULAW, 64 }, 72 { AUDIO_FILE_ENCODING_DOUBLE, AUDIO_ENCODING_ULAW, 64 },
73 { AUDIO_FILE_ENCODING_ADPCM_G721, AUDIO_ENCODING_ULAW, 4 }, 73 { AUDIO_FILE_ENCODING_ADPCM_G721, AUDIO_ENCODING_ULAW, 4 },
74 { AUDIO_FILE_ENCODING_ADPCM_G722, AUDIO_ENCODING_ULAW, 0 }, 74 { AUDIO_FILE_ENCODING_ADPCM_G722, AUDIO_ENCODING_ULAW, 0 },
75 { AUDIO_FILE_ENCODING_ADPCM_G723_3, AUDIO_ENCODING_ULAW, 3 }, 75 { AUDIO_FILE_ENCODING_ADPCM_G723_3, AUDIO_ENCODING_ULAW, 3 },
76 { AUDIO_FILE_ENCODING_ADPCM_G723_5, AUDIO_ENCODING_ULAW, 5 }, 76 { AUDIO_FILE_ENCODING_ADPCM_G723_5, AUDIO_ENCODING_ULAW, 5 },
77#endif 77#endif
78 { AUDIO_FILE_ENCODING_ALAW_8, AUDIO_ENCODING_ALAW, 8 }, 78 { AUDIO_FILE_ENCODING_ALAW_8, AUDIO_ENCODING_ALAW, 8 },
79 { -1, -1, -1 } 79 { -1, -1, -1 }
80}; 80};
81 81
82int 82int
83audio_sun_to_encoding(sun_encoding, encp, precp) 83audio_sun_to_encoding(int sun_encoding, u_int *encp, u_int *precp)
84 int sun_encoding; 
85 u_int *encp; 
86 u_int *precp; 
87{ 84{
88 int i; 85 int i;
89 86
90 for (i = 0; file2sw_encodings[i].file_encoding != -1; i++) 87 for (i = 0; file2sw_encodings[i].file_encoding != -1; i++)
91 if (file2sw_encodings[i].file_encoding == sun_encoding) { 88 if (file2sw_encodings[i].file_encoding == sun_encoding) {
92 *precp = file2sw_encodings[i].precision; 89 *precp = file2sw_encodings[i].precision;
93 *encp = file2sw_encodings[i].encoding; 90 *encp = file2sw_encodings[i].encoding;
94 return (0); 91 return (0);
95 } 92 }
96 return (1); 93 return (1);
97} 94}
98 95
99int 96int
100audio_encoding_to_sun(encoding, precision, sunep) 97audio_encoding_to_sun(int encoding, int precision, int *sunep)
101 int encoding; 
102 int precision; 
103 int *sunep; 
104{ 98{
105 int i; 99 int i;
106 100
107 for (i = 0; file2sw_encodings[i].file_encoding != -1; i++) 101 for (i = 0; file2sw_encodings[i].file_encoding != -1; i++)
108 if (file2sw_encodings[i].encoding == encoding && 102 if (file2sw_encodings[i].encoding == encoding &&
109 file2sw_encodings[i].precision == precision) { 103 file2sw_encodings[i].precision == precision) {
110 *sunep = file2sw_encodings[i].file_encoding; 104 *sunep = file2sw_encodings[i].file_encoding;
111 return (0); 105 return (0);
112 } 106 }
113 return (1); 107 return (1);
114} 108}

cvs diff -r1.9 -r1.10 src/usr.bin/audio/common/wav.c (switch to unified diff)

--- src/usr.bin/audio/common/wav.c 2009/06/18 02:37:27 1.9
+++ src/usr.bin/audio/common/wav.c 2011/08/28 01:17:47 1.10
@@ -1,219 +1,211 @@ @@ -1,219 +1,211 @@
1/* $NetBSD: wav.c,v 1.9 2009/06/18 02:37:27 mrg Exp $ */ 1/* $NetBSD: wav.c,v 1.10 2011/08/28 01:17:47 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002, 2009 Matthew R. Green 4 * Copyright (c) 2002, 2009 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * WAV support for the audio tools; thanks go to the sox utility for 30 * WAV support for the audio tools; thanks go to the sox utility for
31 * clearing up issues with WAV files. 31 * clearing up issues with WAV files.
32 */ 32 */
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34 34
35#ifndef lint 35#ifndef lint
36__RCSID("$NetBSD: wav.c,v 1.9 2009/06/18 02:37:27 mrg Exp $"); 36__RCSID("$NetBSD: wav.c,v 1.10 2011/08/28 01:17:47 joerg Exp $");
37#endif 37#endif
38 38
39 39
40#include <sys/types.h> 40#include <sys/types.h>
41#include <sys/audioio.h> 41#include <sys/audioio.h>
42#include <sys/ioctl.h> 42#include <sys/ioctl.h>
43#include <sys/time.h> 43#include <sys/time.h>
44 44
45#include <ctype.h> 45#include <ctype.h>
46#include <err.h> 46#include <err.h>
47#include <stdio.h> 47#include <stdio.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <string.h> 49#include <string.h>
50#include <stdint.h> 50#include <stdint.h>
51 51
52#include "libaudio.h" 52#include "libaudio.h"
53 53
54struct { 54static const struct {
55 int wenc; 55 int wenc;
56 const char *wname; 56 const char *wname;
57} wavencs[] = { 57} wavencs[] = {
58 { WAVE_FORMAT_UNKNOWN, "Microsoft Official Unknown" }, 58 { WAVE_FORMAT_UNKNOWN, "Microsoft Official Unknown" },
59 { WAVE_FORMAT_PCM, "Microsoft PCM" }, 59 { WAVE_FORMAT_PCM, "Microsoft PCM" },
60 { WAVE_FORMAT_ADPCM, "Microsoft ADPCM" }, 60 { WAVE_FORMAT_ADPCM, "Microsoft ADPCM" },
61 { WAVE_FORMAT_ALAW, "Microsoft A-law" }, 61 { WAVE_FORMAT_ALAW, "Microsoft A-law" },
62 { WAVE_FORMAT_MULAW, "Microsoft mu-law" }, 62 { WAVE_FORMAT_MULAW, "Microsoft mu-law" },
63 { WAVE_FORMAT_OKI_ADPCM,"OKI ADPCM" }, 63 { WAVE_FORMAT_OKI_ADPCM,"OKI ADPCM" },
64 { WAVE_FORMAT_DIGISTD, "Digistd format" }, 64 { WAVE_FORMAT_DIGISTD, "Digistd format" },
65 { WAVE_FORMAT_DIGIFIX, "Digifix format" }, 65 { WAVE_FORMAT_DIGIFIX, "Digifix format" },
66 { -1, "?Unknown?" }, 66 { -1, "?Unknown?" },
67}; 67};
68 68
69const char * 69const char *
70wav_enc_from_val(int encoding) 70wav_enc_from_val(int encoding)
71{ 71{
72 int i; 72 int i;
73 73
74 for (i = 0; wavencs[i].wenc != -1; i++) 74 for (i = 0; wavencs[i].wenc != -1; i++)
75 if (wavencs[i].wenc == encoding) 75 if (wavencs[i].wenc == encoding)
76 break; 76 break;
77 return (wavencs[i].wname); 77 return (wavencs[i].wname);
78} 78}
79 79
80extern int verbose; 
81 
82/* 80/*
83 * sample header is: 81 * sample header is:
84 * 82 *
85 * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@ 83 * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@
86 * 84 *
87 */ 85 */
88/* 86/*
89 * WAV format helpers 87 * WAV format helpers
90 */ 88 */
91/* 89/*
92 * find a .wav header, etc. returns header length on success 90 * find a .wav header, etc. returns header length on success
93 */ 91 */
94ssize_t 92ssize_t
95audio_wav_parse_hdr(hdr, sz, enc, prec, sample, channels, datasize) 93audio_wav_parse_hdr(void *hdr, size_t sz, u_int *enc, u_int *prec,
96 void *hdr; 94 u_int *sample, u_int *channels, size_t *datasize)
97 size_t sz; 
98 u_int *enc; 
99 u_int *prec; 
100 u_int *sample; 
101 u_int *channels; 
102 size_t *datasize; 
103{ 95{
104 char *where = hdr, *owhere; 96 char *where = hdr, *owhere;
105 wav_audioheaderpart part; 97 wav_audioheaderpart part;
106 wav_audioheaderfmt fmt; 98 wav_audioheaderfmt fmt;
107 wav_audiohdrextensible ext; 99 wav_audiohdrextensible ext;
108 char *end = (((char *)hdr) + sz); 100 char *end = (((char *)hdr) + sz);
109 u_int newenc, newprec; 101 u_int newenc, newprec;
110 u_int16_t fmttag; 102 u_int16_t fmttag;
111 static const char 103 static const char
112 strfmt[4] = "fmt ", 104 strfmt[4] = "fmt ",
113 strRIFF[4] = "RIFF", 105 strRIFF[4] = "RIFF",
114 strWAVE[4] = "WAVE", 106 strWAVE[4] = "WAVE",
115 strdata[4] = "data"; 107 strdata[4] = "data";
116  108
117 if (sz < 32) 109 if (sz < 32)
118 return (AUDIO_ENOENT); 110 return (AUDIO_ENOENT);
119 111
120 if (strncmp(where, strRIFF, sizeof strRIFF)) 112 if (strncmp(where, strRIFF, sizeof strRIFF))
121 return (AUDIO_ENOENT); 113 return (AUDIO_ENOENT);
122 where += 8; 114 where += 8;
123 if (strncmp(where, strWAVE, sizeof strWAVE)) 115 if (strncmp(where, strWAVE, sizeof strWAVE))
124 return (AUDIO_ENOENT); 116 return (AUDIO_ENOENT);
125 where += 4; 117 where += 4;
126 118
127 do { 119 do {
128 memcpy(&part, where, sizeof part); 120 memcpy(&part, where, sizeof part);
129 owhere = where; 121 owhere = where;
130 where += getle32(part.len) + 8; 122 where += getle32(part.len) + 8;
131 } while (where < end && strncmp(part.name, strfmt, sizeof strfmt)); 123 } while (where < end && strncmp(part.name, strfmt, sizeof strfmt));
132 124
133 /* too short ? */ 125 /* too short ? */
134 if (where + sizeof fmt > end) 126 if (where + sizeof fmt > end)
135 return (AUDIO_ESHORTHDR); 127 return (AUDIO_ESHORTHDR);
136 128
137 memcpy(&fmt, (owhere + 8), sizeof fmt); 129 memcpy(&fmt, (owhere + 8), sizeof fmt);
138 130
139 fmttag = getle16(fmt.tag); 131 fmttag = getle16(fmt.tag);
140 if (verbose) 132 if (verbose)
141 printf("WAVE format tag: %x\n", fmttag); 133 printf("WAVE format tag: %x\n", fmttag);
142 134
143 if (fmttag == WAVE_FORMAT_EXTENSIBLE) { 135 if (fmttag == WAVE_FORMAT_EXTENSIBLE) {
144 if ((uintptr_t)(where - owhere) < sizeof(fmt) + sizeof(ext)) 136 if ((uintptr_t)(where - owhere) < sizeof(fmt) + sizeof(ext))
145 return (AUDIO_ESHORTHDR); 137 return (AUDIO_ESHORTHDR);
146 memcpy(&ext, owhere + sizeof fmt, sizeof ext); 138 memcpy(&ext, owhere + sizeof fmt, sizeof ext);
147 if (getle16(ext.len) < sizeof(ext) - sizeof(ext.len)) 139 if (getle16(ext.len) < sizeof(ext) - sizeof(ext.len))
148 return (AUDIO_ESHORTHDR); 140 return (AUDIO_ESHORTHDR);
149 fmttag = ext.sub_tag; 141 fmttag = ext.sub_tag;
150 if (verbose) 142 if (verbose)
151 printf("WAVE extensible sub tag: %x\n", fmttag); 143 printf("WAVE extensible sub tag: %x\n", fmttag);
152 } 144 }
153 145
154 switch (fmttag) { 146 switch (fmttag) {
155 case WAVE_FORMAT_UNKNOWN: 147 case WAVE_FORMAT_UNKNOWN:
156 case IBM_FORMAT_MULAW: 148 case IBM_FORMAT_MULAW:
157 case IBM_FORMAT_ALAW: 149 case IBM_FORMAT_ALAW:
158 case IBM_FORMAT_ADPCM: 150 case IBM_FORMAT_ADPCM:
159 default: 151 default:
160 return (AUDIO_EWAVUNSUPP); 152 return (AUDIO_EWAVUNSUPP);
161 153
162 case WAVE_FORMAT_PCM: 154 case WAVE_FORMAT_PCM:
163 case WAVE_FORMAT_ADPCM: 155 case WAVE_FORMAT_ADPCM:
164 case WAVE_FORMAT_OKI_ADPCM: 156 case WAVE_FORMAT_OKI_ADPCM:
165 case WAVE_FORMAT_IMA_ADPCM: 157 case WAVE_FORMAT_IMA_ADPCM:
166 case WAVE_FORMAT_DIGIFIX: 158 case WAVE_FORMAT_DIGIFIX:
167 case WAVE_FORMAT_DIGISTD: 159 case WAVE_FORMAT_DIGISTD:
168 switch (getle16(fmt.bits_per_sample)) { 160 switch (getle16(fmt.bits_per_sample)) {
169 case 8: 161 case 8:
170 newprec = 8; 162 newprec = 8;
171 break; 163 break;
172 case 16: 164 case 16:
173 newprec = 16; 165 newprec = 16;
174 break; 166 break;
175 case 24: 167 case 24:
176 newprec = 24; 168 newprec = 24;
177 break; 169 break;
178 case 32: 170 case 32:
179 newprec = 32; 171 newprec = 32;
180 break; 172 break;
181 default: 173 default:
182 return (AUDIO_EWAVBADPCM); 174 return (AUDIO_EWAVBADPCM);
183 } 175 }
184 if (newprec == 8) 176 if (newprec == 8)
185 newenc = AUDIO_ENCODING_ULINEAR_LE; 177 newenc = AUDIO_ENCODING_ULINEAR_LE;
186 else 178 else
187 newenc = AUDIO_ENCODING_SLINEAR_LE; 179 newenc = AUDIO_ENCODING_SLINEAR_LE;
188 break; 180 break;
189 case WAVE_FORMAT_ALAW: 181 case WAVE_FORMAT_ALAW:
190 newenc = AUDIO_ENCODING_ALAW; 182 newenc = AUDIO_ENCODING_ALAW;
191 newprec = 8; 183 newprec = 8;
192 break; 184 break;
193 case WAVE_FORMAT_MULAW: 185 case WAVE_FORMAT_MULAW:
194 newenc = AUDIO_ENCODING_ULAW; 186 newenc = AUDIO_ENCODING_ULAW;
195 newprec = 8; 187 newprec = 8;
196 break; 188 break;
197 } 189 }
198 190
199 do { 191 do {
200 memcpy(&part, where, sizeof part); 192 memcpy(&part, where, sizeof part);
201 owhere = where; 193 owhere = where;
202 where += (getle32(part.len) + 8); 194 where += (getle32(part.len) + 8);
203 } while (where < end && strncmp(part.name, strdata, sizeof strdata)); 195 } while (where < end && strncmp(part.name, strdata, sizeof strdata));
204 196
205 if ((where - getle32(part.len)) <= end) { 197 if ((where - getle32(part.len)) <= end) {
206 if (channels) 198 if (channels)
207 *channels = (u_int)getle16(fmt.channels); 199 *channels = (u_int)getle16(fmt.channels);
208 if (sample) 200 if (sample)
209 *sample = getle32(fmt.sample_rate); 201 *sample = getle32(fmt.sample_rate);
210 if (enc) 202 if (enc)
211 *enc = newenc; 203 *enc = newenc;
212 if (prec) 204 if (prec)
213 *prec = newprec; 205 *prec = newprec;
214 if (datasize) 206 if (datasize)
215 *datasize = (size_t)getle32(part.len); 207 *datasize = (size_t)getle32(part.len);
216 return (owhere - (char *)hdr + 8); 208 return (owhere - (char *)hdr + 8);
217 } 209 }
218 return (AUDIO_EWAVNODATA); 210 return (AUDIO_EWAVNODATA);
219} 211}

cvs diff -r1.38 -r1.39 src/usr.bin/audio/ctl/ctl.c (switch to unified diff)

--- src/usr.bin/audio/ctl/ctl.c 2009/04/11 10:43:09 1.38
+++ src/usr.bin/audio/ctl/ctl.c 2011/08/28 01:17:48 1.39
@@ -1,465 +1,453 @@ @@ -1,465 +1,453 @@
1/* $NetBSD: ctl.c,v 1.38 2009/04/11 10:43:09 lukem Exp $ */ 1/* $NetBSD: ctl.c,v 1.39 2011/08/28 01:17:48 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss@NetBSD.org). 8 * by Lennart Augustsson (augustss@NetBSD.org).
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32 32
33#ifndef lint 33#ifndef lint
34__RCSID("$NetBSD: ctl.c,v 1.38 2009/04/11 10:43:09 lukem Exp $"); 34__RCSID("$NetBSD: ctl.c,v 1.39 2011/08/28 01:17:48 joerg Exp $");
35#endif 35#endif
36 36
37 37
38#include <sys/types.h> 38#include <sys/types.h>
39#include <sys/stat.h> 39#include <sys/stat.h>
40#include <sys/ioctl.h> 40#include <sys/ioctl.h>
41#include <sys/audioio.h> 41#include <sys/audioio.h>
42 42
43#include <err.h> 43#include <err.h>
44#include <fcntl.h> 44#include <fcntl.h>
45#include <stdio.h> 45#include <stdio.h>
46#include <stdlib.h> 46#include <stdlib.h>
47#include <string.h> 47#include <string.h>
48#include <unistd.h> 48#include <unistd.h>
49 49
50#include <paths.h> 50#include <paths.h>
51 51
52#include "libaudio.h" 52#include "libaudio.h"
53 53
54struct field *findfield (const char *name); 54static struct field *findfield(const char *name);
55void prfield (struct field *p, const char *sep); 55static void prfield(const struct field *p, const char *sep);
56void rdfield (struct field *p, char *q); 56static void rdfield(struct field *p, char *q);
57void getinfo (int fd); 57static void getinfo(int fd);
58void audioctl_write (int, int, char *[]); 58static void audioctl_write(int, int, char *[]);
59void usage (void); 59__dead static void usage(void);
60int main (int argc, char **argv); 
61 60
62audio_device_t adev; 61static audio_device_t adev;
63 62
64audio_info_t info; 63static audio_info_t info;
65 64
66char encbuf[1000]; 65static char encbuf[1000];
67 66
68int properties, fullduplex, rerror; 67static int properties, fullduplex, rerror;
69 68
70struct field { 69static struct field {
71 const char *name; 70 const char *name;
72 void *valp; 71 void *valp;
73 int format; 72 int format;
74#define STRING 1 73#define STRING 1
75#define INT 2 74#define INT 2
76#define UINT 3 75#define UINT 3
77#define P_R 4 76#define P_R 4
78#define ULONG 5 /* XXX obsolete now */ 77#define ULONG 5 /* XXX obsolete now */
79#define UCHAR 6 78#define UCHAR 6
80#define ENC 7 79#define ENC 7
81#define PROPS 8 80#define PROPS 8
82#define XINT 9 81#define XINT 9
83#define FORMAT 10 82#define FORMAT 10
84 char flags; 83 char flags;
85#define READONLY 1 84#define READONLY 1
86#define ALIAS 2 85#define ALIAS 2
87#define SET 4 86#define SET 4
88} fields[] = { 87} fields[] = {
89 { "name", &adev.name, STRING, READONLY }, 88 { "name", &adev.name, STRING, READONLY },
90 { "version", &adev.version, STRING, READONLY }, 89 { "version", &adev.version, STRING, READONLY },
91 { "config", &adev.config, STRING, READONLY }, 90 { "config", &adev.config, STRING, READONLY },
92 { "encodings", encbuf, STRING, READONLY }, 91 { "encodings", encbuf, STRING, READONLY },
93 { "properties", &properties, PROPS, READONLY }, 92 { "properties", &properties, PROPS, READONLY },
94 { "full_duplex", &fullduplex, UINT, 0 }, 93 { "full_duplex", &fullduplex, UINT, 0 },
95 { "fullduplex", &fullduplex, UINT, 0 }, 94 { "fullduplex", &fullduplex, UINT, 0 },
96 { "blocksize", &info.blocksize, UINT, 0 }, 95 { "blocksize", &info.blocksize, UINT, 0 },
97 { "hiwat", &info.hiwat, UINT, 0 }, 96 { "hiwat", &info.hiwat, UINT, 0 },
98 { "lowat", &info.lowat, UINT, 0 }, 97 { "lowat", &info.lowat, UINT, 0 },
99 { "monitor_gain", &info.monitor_gain, UINT, 0 }, 98 { "monitor_gain", &info.monitor_gain, UINT, 0 },
100 { "mode", &info.mode, P_R, READONLY }, 99 { "mode", &info.mode, P_R, READONLY },
101 { "play", &info.play, FORMAT, ALIAS }, 100 { "play", &info.play, FORMAT, ALIAS },
102 { "play.rate", &info.play.sample_rate, UINT, 0 }, 101 { "play.rate", &info.play.sample_rate, UINT, 0 },
103 { "play.sample_rate", &info.play.sample_rate, UINT, ALIAS }, 102 { "play.sample_rate", &info.play.sample_rate, UINT, ALIAS },
104 { "play.channels", &info.play.channels, UINT, 0 }, 103 { "play.channels", &info.play.channels, UINT, 0 },
105 { "play.precision", &info.play.precision, UINT, 0 }, 104 { "play.precision", &info.play.precision, UINT, 0 },
106 { "play.encoding", &info.play.encoding, ENC, 0 }, 105 { "play.encoding", &info.play.encoding, ENC, 0 },
107 { "play.gain", &info.play.gain, UINT, 0 }, 106 { "play.gain", &info.play.gain, UINT, 0 },
108 { "play.balance", &info.play.balance, UCHAR, 0 }, 107 { "play.balance", &info.play.balance, UCHAR, 0 },
109 { "play.port", &info.play.port, XINT, 0 }, 108 { "play.port", &info.play.port, XINT, 0 },
110 { "play.avail_ports", &info.play.avail_ports, XINT, 0 }, 109 { "play.avail_ports", &info.play.avail_ports, XINT, 0 },
111 { "play.seek", &info.play.seek, UINT, READONLY }, 110 { "play.seek", &info.play.seek, UINT, READONLY },
112 { "play.samples", &info.play.samples, UINT, READONLY }, 111 { "play.samples", &info.play.samples, UINT, READONLY },
113 { "play.eof", &info.play.eof, UINT, READONLY }, 112 { "play.eof", &info.play.eof, UINT, READONLY },
114 { "play.pause", &info.play.pause, UCHAR, 0 }, 113 { "play.pause", &info.play.pause, UCHAR, 0 },
115 { "play.error", &info.play.error, UCHAR, READONLY }, 114 { "play.error", &info.play.error, UCHAR, READONLY },
116 { "play.waiting", &info.play.waiting, UCHAR, READONLY }, 115 { "play.waiting", &info.play.waiting, UCHAR, READONLY },
117 { "play.open", &info.play.open, UCHAR, READONLY }, 116 { "play.open", &info.play.open, UCHAR, READONLY },
118 { "play.active", &info.play.active, UCHAR, READONLY }, 117 { "play.active", &info.play.active, UCHAR, READONLY },
119 { "play.buffer_size", &info.play.buffer_size, UINT, 0 }, 118 { "play.buffer_size", &info.play.buffer_size, UINT, 0 },
120 { "record", &info.record, FORMAT, ALIAS }, 119 { "record", &info.record, FORMAT, ALIAS },
121 { "record.rate", &info.record.sample_rate,UINT, 0 }, 120 { "record.rate", &info.record.sample_rate,UINT, 0 },
122 { "record.sample_rate", &info.record.sample_rate,UINT, ALIAS }, 121 { "record.sample_rate", &info.record.sample_rate,UINT, ALIAS },
123 { "record.channels", &info.record.channels, UINT, 0 }, 122 { "record.channels", &info.record.channels, UINT, 0 },
124 { "record.precision", &info.record.precision, UINT, 0 }, 123 { "record.precision", &info.record.precision, UINT, 0 },
125 { "record.encoding", &info.record.encoding, ENC, 0 }, 124 { "record.encoding", &info.record.encoding, ENC, 0 },
126 { "record.gain", &info.record.gain, UINT, 0 }, 125 { "record.gain", &info.record.gain, UINT, 0 },
127 { "record.balance", &info.record.balance, UCHAR, 0 }, 126 { "record.balance", &info.record.balance, UCHAR, 0 },
128 { "record.port", &info.record.port, XINT, 0 }, 127 { "record.port", &info.record.port, XINT, 0 },
129 { "record.avail_ports", &info.record.avail_ports,XINT, 0 }, 128 { "record.avail_ports", &info.record.avail_ports,XINT, 0 },
130 { "record.seek", &info.record.seek, UINT, READONLY }, 129 { "record.seek", &info.record.seek, UINT, READONLY },
131 { "record.samples", &info.record.samples, UINT, READONLY }, 130 { "record.samples", &info.record.samples, UINT, READONLY },
132 { "record.eof", &info.record.eof, UINT, READONLY }, 131 { "record.eof", &info.record.eof, UINT, READONLY },
133 { "record.pause", &info.record.pause, UCHAR, 0 }, 132 { "record.pause", &info.record.pause, UCHAR, 0 },
134 { "record.error", &info.record.error, UCHAR, READONLY }, 133 { "record.error", &info.record.error, UCHAR, READONLY },
135 { "record.waiting", &info.record.waiting, UCHAR, READONLY }, 134 { "record.waiting", &info.record.waiting, UCHAR, READONLY },
136 { "record.open", &info.record.open, UCHAR, READONLY }, 135 { "record.open", &info.record.open, UCHAR, READONLY },
137 { "record.active", &info.record.active, UCHAR, READONLY }, 136 { "record.active", &info.record.active, UCHAR, READONLY },
138 { "record.buffer_size", &info.record.buffer_size,UINT, 0 }, 137 { "record.buffer_size", &info.record.buffer_size,UINT, 0 },
139 { "record.errors", &rerror, INT, READONLY }, 138 { "record.errors", &rerror, INT, READONLY },
140 { .name = NULL }, 139 { .name = NULL },
141}; 140};
142 141
143static struct { 142static const struct {
144 const char *name; 143 const char *name;
145 u_int prop; 144 u_int prop;
146} props[] = { 145} props[] = {
147 { "full_duplex", AUDIO_PROP_FULLDUPLEX }, 146 { "full_duplex", AUDIO_PROP_FULLDUPLEX },
148 { "mmap", AUDIO_PROP_MMAP }, 147 { "mmap", AUDIO_PROP_MMAP },
149 { "independent", AUDIO_PROP_INDEPENDENT }, 148 { "independent", AUDIO_PROP_INDEPENDENT },
150 { .name = NULL }, 149 { .name = NULL },
151}; 150};
152 151
153struct field * 152static struct field *
154findfield(name) 153findfield(const char *name)
155 const char *name; 
156{ 154{
157 int i; 155 int i;
158 for (i = 0; fields[i].name; i++) 156 for (i = 0; fields[i].name; i++)
159 if (strcmp(fields[i].name, name) == 0) 157 if (strcmp(fields[i].name, name) == 0)
160 return &fields[i]; 158 return &fields[i];
161 return 0; 159 return 0;
162} 160}
163 161
164void 162static void
165prfield(p, sep) 163prfield(const struct field *p, const char *sep)
166 struct field *p; 
167 const char *sep; 
168{ 164{
169 u_int v; 165 u_int v;
170 const char *cm, *encstr; 166 const char *cm, *encstr;
171 int i; 167 int i;
172 168
173 if (sep) 169 if (sep)
174 printf("%s%s", p->name, sep); 170 printf("%s%s", p->name, sep);
175 switch(p->format) { 171 switch(p->format) {
176 case STRING: 172 case STRING:
177 printf("%s", (char*)p->valp); 173 printf("%s", (const char*)p->valp);
178 break; 174 break;
179 case INT: 175 case INT:
180 printf("%d", *(int*)p->valp); 176 printf("%d", *(const int*)p->valp);
181 break; 177 break;
182 case UINT: 178 case UINT:
183 printf("%u", *(u_int*)p->valp); 179 printf("%u", *(const u_int*)p->valp);
184 break; 180 break;
185 case XINT: 181 case XINT:
186 printf("0x%x", *(u_int*)p->valp); 182 printf("0x%x", *(const u_int*)p->valp);
187 break; 183 break;
188 case UCHAR: 184 case UCHAR:
189 printf("%u", *(u_char*)p->valp); 185 printf("%u", *(const u_char*)p->valp);
190 break; 186 break;
191 case ULONG: 187 case ULONG:
192 printf("%lu", *(u_long*)p->valp); 188 printf("%lu", *(const u_long*)p->valp);
193 break; 189 break;
194 case P_R: 190 case P_R:
195 v = *(u_int*)p->valp; 191 v = *(const u_int*)p->valp;
196 cm = ""; 192 cm = "";
197 if (v & AUMODE_PLAY) { 193 if (v & AUMODE_PLAY) {
198 if (v & AUMODE_PLAY_ALL) 194 if (v & AUMODE_PLAY_ALL)
199 printf("play"); 195 printf("play");
200 else 196 else
201 printf("playsync"); 197 printf("playsync");
202 cm = ","; 198 cm = ",";
203 } 199 }
204 if (v & AUMODE_RECORD) 200 if (v & AUMODE_RECORD)
205 printf("%srecord", cm); 201 printf("%srecord", cm);
206 break; 202 break;
207 case ENC: 203 case ENC:
208 v = *(u_int*)p->valp; 204 v = *(u_int*)p->valp;
209 encstr = audio_enc_from_val(v); 205 encstr = audio_enc_from_val(v);
210 if (encstr) 206 if (encstr)
211 printf("%s", encstr); 207 printf("%s", encstr);
212 else 208 else
213 printf("%u", v); 209 printf("%u", v);
214 break; 210 break;
215 case PROPS: 211 case PROPS:
216 v = *(u_int*)p->valp; 212 v = *(u_int*)p->valp;
217 for (cm = "", i = 0; props[i].name; i++) { 213 for (cm = "", i = 0; props[i].name; i++) {
218 if (v & props[i].prop) { 214 if (v & props[i].prop) {
219 printf("%s%s", cm, props[i].name); 215 printf("%s%s", cm, props[i].name);
220 cm = ","; 216 cm = ",";
221 } 217 }
222 } 218 }
223 break; 219 break;
224 case FORMAT: 220 case FORMAT:
225 prfield(p + 1, 0); 221 prfield(p + 1, 0);
226 printf(","); 222 printf(",");
227 prfield(p + 3, 0); 223 prfield(p + 3, 0);
228 printf(","); 224 printf(",");
229 prfield(p + 4, 0); 225 prfield(p + 4, 0);
230 printf(","); 226 printf(",");
231 prfield(p + 5, 0); 227 prfield(p + 5, 0);
232 break; 228 break;
233 default: 229 default:
234 errx(1, "Invalid print format."); 230 errx(1, "Invalid print format.");
235 } 231 }
236} 232}
237 233
238void 234static void
239rdfield(p, q) 235rdfield(struct field *p, char *q)
240 struct field *p; 
241 char *q; 
242{ 236{
243 int enc; 237 int enc;
244 u_int u; 238 u_int u;
245 char *s; 239 char *s;
246 240
247 switch(p->format) { 241 switch(p->format) {
248 case UINT: 242 case UINT:
249 if (sscanf(q, "%u", (unsigned int *)p->valp) != 1) 243 if (sscanf(q, "%u", (unsigned int *)p->valp) != 1)
250 errx(1, "Bad number: %s", q); 244 errx(1, "Bad number: %s", q);
251 break; 245 break;
252 case UCHAR: 246 case UCHAR:
253 if (sscanf(q, "%u", &u) != 1) 247 if (sscanf(q, "%u", &u) != 1)
254 errx(1, "Bad number: %s", q); 248 errx(1, "Bad number: %s", q);
255 else 249 else
256 *(u_char *)p->valp = u; 250 *(u_char *)p->valp = u;
257 break; 251 break;
258 case XINT: 252 case XINT:
259 if (sscanf(q, "0x%x", (unsigned int *)p->valp) != 1 && 253 if (sscanf(q, "0x%x", (unsigned int *)p->valp) != 1 &&
260 sscanf(q, "%x", (unsigned int *)p->valp) != 1) 254 sscanf(q, "%x", (unsigned int *)p->valp) != 1)
261 errx(1, "Bad number: %s", q); 255 errx(1, "Bad number: %s", q);
262 break; 256 break;
263 case ENC: 257 case ENC:
264 enc = audio_enc_to_val(q); 258 enc = audio_enc_to_val(q);
265 if (enc >= 0) 259 if (enc >= 0)
266 *(u_int*)p->valp = enc; 260 *(u_int*)p->valp = enc;
267 else 261 else
268 errx(1, "Unknown encoding: %s", q); 262 errx(1, "Unknown encoding: %s", q);
269 break; 263 break;
270 case FORMAT: 264 case FORMAT:
271 s = strsep(&q, ","); 265 s = strsep(&q, ",");
272 if (s) 266 if (s)
273 rdfield(p + 1, s); 267 rdfield(p + 1, s);
274 s = strsep(&q, ","); 268 s = strsep(&q, ",");
275 if (s) 269 if (s)
276 rdfield(p + 3, s); 270 rdfield(p + 3, s);
277 s = strsep(&q, ","); 271 s = strsep(&q, ",");
278 if (s) 272 if (s)
279 rdfield(p + 4, s); 273 rdfield(p + 4, s);
280 s = strsep(&q, ","); 274 s = strsep(&q, ",");
281 if (s) 275 if (s)
282 rdfield(p + 5, s); 276 rdfield(p + 5, s);
283 if (!s || q) 277 if (!s || q)
284 errx(1, "Bad format"); 278 errx(1, "Bad format");
285 break; 279 break;
286 default: 280 default:
287 errx(1, "Invalid read format."); 281 errx(1, "Invalid read format.");
288 } 282 }
289 p->flags |= SET; 283 p->flags |= SET;
290} 284}
291 285
292void 286static void
293getinfo(fd) 287getinfo(int fd)
294 int fd; 
295{ 288{
296 int pos, i; 289 int pos, i;
297 290
298 if (ioctl(fd, AUDIO_GETDEV, &adev) < 0) 291 if (ioctl(fd, AUDIO_GETDEV, &adev) < 0)
299 err(1, "AUDIO_GETDEV"); 292 err(1, "AUDIO_GETDEV");
300 for (pos = 0, i = 0; ; i++) { 293 for (pos = 0, i = 0; ; i++) {
301 audio_encoding_t enc; 294 audio_encoding_t enc;
302 enc.index = i; 295 enc.index = i;
303 if (ioctl(fd, AUDIO_GETENC, &enc) < 0) 296 if (ioctl(fd, AUDIO_GETENC, &enc) < 0)
304 break; 297 break;
305 if (pos >= (int)sizeof(encbuf)-1) 298 if (pos >= (int)sizeof(encbuf)-1)
306 break; 299 break;
307 if (pos) 300 if (pos)
308 encbuf[pos++] = ','; 301 encbuf[pos++] = ',';
309 if (pos >= (int)sizeof(encbuf)-1) 302 if (pos >= (int)sizeof(encbuf)-1)
310 break; 303 break;
311 pos += snprintf(encbuf+pos, sizeof(encbuf)-pos, "%s:%d%s", 304 pos += snprintf(encbuf+pos, sizeof(encbuf)-pos, "%s:%d%s",
312 enc.name, enc.precision, 305 enc.name, enc.precision,
313 enc.flags & AUDIO_ENCODINGFLAG_EMULATED ? "*" : ""); 306 enc.flags & AUDIO_ENCODINGFLAG_EMULATED ? "*" : "");
314 } 307 }
315 if (ioctl(fd, AUDIO_GETFD, &fullduplex) < 0) 308 if (ioctl(fd, AUDIO_GETFD, &fullduplex) < 0)
316 err(1, "AUDIO_GETFD"); 309 err(1, "AUDIO_GETFD");
317 if (ioctl(fd, AUDIO_GETPROPS, &properties) < 0) 310 if (ioctl(fd, AUDIO_GETPROPS, &properties) < 0)
318 err(1, "AUDIO_GETPROPS"); 311 err(1, "AUDIO_GETPROPS");
319 if (ioctl(fd, AUDIO_RERROR, &rerror) < 0) 312 if (ioctl(fd, AUDIO_RERROR, &rerror) < 0)
320 err(1, "AUDIO_RERROR"); 313 err(1, "AUDIO_RERROR");
321 if (ioctl(fd, AUDIO_GETINFO, &info) < 0) 314 if (ioctl(fd, AUDIO_GETINFO, &info) < 0)
322 err(1, "AUDIO_GETINFO"); 315 err(1, "AUDIO_GETINFO");
323} 316}
324 317
325void 318static void
326usage() 319usage(void)
327{ 320{
328 const char *prog = getprogname(); 321 const char *prog = getprogname();
329 322
330 fprintf(stderr, "Usage: %s [-d file] [-n] name ...\n", prog); 323 fprintf(stderr, "Usage: %s [-d file] [-n] name ...\n", prog);
331 fprintf(stderr, "Usage: %s [-d file] [-n] -w name=value ...\n", prog); 324 fprintf(stderr, "Usage: %s [-d file] [-n] -w name=value ...\n", prog);
332 fprintf(stderr, "Usage: %s [-d file] [-n] -a\n", prog); 325 fprintf(stderr, "Usage: %s [-d file] [-n] -a\n", prog);
333 exit(1); 326 exit(1);
334} 327}
335 328
336int 329int
337main(argc, argv) 330main(int argc, char *argv[])
338 int argc; 
339 char **argv; 
340{ 331{
341 int fd, i, ch; 332 int fd, i, ch;
342 int aflag = 0, wflag = 0; 333 int aflag = 0, wflag = 0;
343 const char *deffile = _PATH_AUDIOCTL; 334 const char *deffile = _PATH_AUDIOCTL;
344 const char *file; 335 const char *file;
345 const char *sep = "="; 336 const char *sep = "=";
346 337
347 file = getenv("AUDIOCTLDEVICE"); 338 file = getenv("AUDIOCTLDEVICE");
348 if (file == NULL) 339 if (file == NULL)
349 file = deffile; 340 file = deffile;
350 341
351 while ((ch = getopt(argc, argv, "ad:f:nw")) != -1) { 342 while ((ch = getopt(argc, argv, "ad:f:nw")) != -1) {
352 switch(ch) { 343 switch(ch) {
353 case 'a': 344 case 'a':
354 aflag++; 345 aflag++;
355 break; 346 break;
356 case 'w': 347 case 'w':
357 wflag++; 348 wflag++;
358 break; 349 break;
359 case 'n': 350 case 'n':
360 sep = 0; 351 sep = 0;
361 break; 352 break;
362 case 'f': /* compatibility */ 353 case 'f': /* compatibility */
363 case 'd': 354 case 'd':
364 file = optarg; 355 file = optarg;
365 break; 356 break;
366 case '?': 357 case '?':
367 default: 358 default:
368 usage(); 359 usage();
369 } 360 }
370 } 361 }
371 argc -= optind; 362 argc -= optind;
372 argv += optind; 363 argv += optind;
373 364
374 fd = open(file, O_WRONLY); 365 fd = open(file, O_WRONLY);
375 if (fd < 0) 366 if (fd < 0)
376 fd = open(file, O_RDONLY); 367 fd = open(file, O_RDONLY);
377 if (fd < 0 && file == deffile) { 368 if (fd < 0 && file == deffile) {
378 file = _PATH_AUDIOCTL0; 369 file = _PATH_AUDIOCTL0;
379 fd = open(file, O_WRONLY); 370 fd = open(file, O_WRONLY);
380 if (fd < 0) 371 if (fd < 0)
381 fd = open(file, O_RDONLY); 372 fd = open(file, O_RDONLY);
382 } 373 }
383 374
384 if (fd < 0) 375 if (fd < 0)
385 err(1, "%s", file); 376 err(1, "%s", file);
386 377
387 if (!wflag) 378 if (!wflag)
388 getinfo(fd); 379 getinfo(fd);
389 380
390 if (argc == 0 && aflag && !wflag) { 381 if (argc == 0 && aflag && !wflag) {
391 for (i = 0; fields[i].name; i++) { 382 for (i = 0; fields[i].name; i++) {
392 if (!(fields[i].flags & ALIAS)) { 383 if (!(fields[i].flags & ALIAS)) {
393 prfield(&fields[i], sep); 384 prfield(&fields[i], sep);
394 printf("\n"); 385 printf("\n");
395 } 386 }
396 } 387 }
397 } else if (argc > 0 && !aflag) { 388 } else if (argc > 0 && !aflag) {
398 if (wflag) { 389 if (wflag) {
399 audioctl_write(fd, argc, argv); 390 audioctl_write(fd, argc, argv);
400 if (sep) { 391 if (sep) {
401 getinfo(fd); 392 getinfo(fd);
402 for (i = 0; fields[i].name; i++) { 393 for (i = 0; fields[i].name; i++) {
403 if (fields[i].flags & SET) { 394 if (fields[i].flags & SET) {
404 printf("%s: -> ", fields[i].name); 395 printf("%s: -> ", fields[i].name);
405 prfield(&fields[i], 0); 396 prfield(&fields[i], 0);
406 printf("\n"); 397 printf("\n");
407 } 398 }
408 } 399 }
409 } 400 }
410 } else { 401 } else {
411 struct field *p; 402 struct field *p;
412 while (argc--) { 403 while (argc--) {
413 p = findfield(*argv); 404 p = findfield(*argv);
414 if (p == 0) { 405 if (p == 0) {
415 if (strchr(*argv, '=')) 406 if (strchr(*argv, '='))
416 warnx("field %s does not exist (use -w to set a variable)", *argv); 407 warnx("field %s does not exist (use -w to set a variable)", *argv);
417 else 408 else
418 warnx("field %s does not exist", *argv); 409 warnx("field %s does not exist", *argv);
419 } else { 410 } else {
420 prfield(p, sep); 411 prfield(p, sep);
421 printf("\n"); 412 printf("\n");
422 } 413 }
423 argv++; 414 argv++;
424 } 415 }
425 } 416 }
426 } else 417 } else
427 usage(); 418 usage();
428 exit(0); 419 exit(0);
429} 420}
430 421
431void 422static void
432audioctl_write(fd, argc, argv) 423audioctl_write(int fd, int argc, char *argv[])
433 int fd; 
434 int argc; 
435 char *argv[]; 
436{ 424{
437 struct field *p; 425 struct field *p;
438 426
439 AUDIO_INITINFO(&info); 427 AUDIO_INITINFO(&info);
440 while (argc--) { 428 while (argc--) {
441 char *q; 429 char *q;
442 430
443 q = strchr(*argv, '='); 431 q = strchr(*argv, '=');
444 if (q) { 432 if (q) {
445 *q++ = 0; 433 *q++ = 0;
446 p = findfield(*argv); 434 p = findfield(*argv);
447 if (p == 0) 435 if (p == 0)
448 warnx("field `%s' does not exist", *argv); 436 warnx("field `%s' does not exist", *argv);
449 else { 437 else {
450 if (p->flags & READONLY) 438 if (p->flags & READONLY)
451 warnx("`%s' is read only", *argv); 439 warnx("`%s' is read only", *argv);
452 else { 440 else {
453 rdfield(p, q); 441 rdfield(p, q);
454 if (p->valp == &fullduplex) 442 if (p->valp == &fullduplex)
455 if (ioctl(fd, AUDIO_SETFD, &fullduplex) < 0) 443 if (ioctl(fd, AUDIO_SETFD, &fullduplex) < 0)
456 err(1, "set failed"); 444 err(1, "set failed");
457 } 445 }
458 } 446 }
459 } else 447 } else
460 warnx("No `=' in %s", *argv); 448 warnx("No `=' in %s", *argv);
461 argv++; 449 argv++;
462 } 450 }
463 if (ioctl(fd, AUDIO_SETINFO, &info) < 0) 451 if (ioctl(fd, AUDIO_SETINFO, &info) < 0)
464 err(1, "set failed"); 452 err(1, "set failed");
465} 453}

cvs diff -r1.53 -r1.54 src/usr.bin/audio/play/play.c (switch to unified diff)

--- src/usr.bin/audio/play/play.c 2010/12/29 18:48:40 1.53
+++ src/usr.bin/audio/play/play.c 2011/08/28 01:17:48 1.54
@@ -1,489 +1,477 @@ @@ -1,489 +1,477 @@
1/* $NetBSD: play.c,v 1.53 2010/12/29 18:48:40 wiz Exp $ */ 1/* $NetBSD: play.c,v 1.54 2011/08/28 01:17:48 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2000, 2001, 2002, 2010 Matthew R. Green 4 * Copyright (c) 1999, 2000, 2001, 2002, 2010 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29 29
30#ifndef lint 30#ifndef lint
31__RCSID("$NetBSD: play.c,v 1.53 2010/12/29 18:48:40 wiz Exp $"); 31__RCSID("$NetBSD: play.c,v 1.54 2011/08/28 01:17:48 joerg Exp $");
32#endif 32#endif
33 33
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/audioio.h> 36#include <sys/audioio.h>
37#include <sys/ioctl.h> 37#include <sys/ioctl.h>
38#include <sys/mman.h> 38#include <sys/mman.h>
39#include <sys/stat.h> 39#include <sys/stat.h>
40 40
41#include <err.h> 41#include <err.h>
42#include <fcntl.h> 42#include <fcntl.h>
43#include <signal.h> 43#include <signal.h>
44#include <stdio.h> 44#include <stdio.h>
45#include <stdlib.h> 45#include <stdlib.h>
46#include <string.h> 46#include <string.h>
47#include <unistd.h> 47#include <unistd.h>
48#include <util.h> 48#include <util.h>
49 49
50#include <paths.h> 50#include <paths.h>
51 51
52#include "libaudio.h" 52#include "libaudio.h"
53 53
54int main(int, char *[]); 54static void usage(void) __dead;
55void usage(void); 55static void play(char *);
56void play(char *); 56static void play_fd(const char *, int);
57void play_fd(const char *, int); 57static ssize_t audioctl_write_fromhdr(void *, size_t, int, size_t *, const char *);
58ssize_t audioctl_write_fromhdr(void *, size_t, int, size_t *, const char *); 58static void cleanup(int) __dead;
59void cleanup(int) __dead; 59
60 60static audio_info_t info;
61audio_info_t info; 61static int volume;
62int volume; 62static int balance;
63int balance; 63static int port;
64int port; 64static int fflag;
65int fflag; 65static int qflag;
66int qflag; 
67int verbose; 66int verbose;
68int sample_rate; 67static int sample_rate;
69int encoding; 68static int encoding;
70char *encoding_str; 69static char *encoding_str;
71int precision; 70static int precision;
72int channels; 71static int channels;
73 72
74char const *play_errstring = NULL; 73static char const *play_errstring = NULL;
75size_t bufsize; 74static size_t bufsize;
76int audiofd; 75static int audiofd;
77int exitstatus = EXIT_SUCCESS; 76static int exitstatus = EXIT_SUCCESS;
78 77
79int 78int
80main(argc, argv) 79main(int argc, char *argv[])
81 int argc; 
82 char *argv[]; 
83{ 80{
84 size_t len; 81 size_t len;
85 int ch; 82 int ch;
86 int iflag = 0; 83 int iflag = 0;
87 const char *defdevice = _PATH_SOUND; 84 const char *defdevice = _PATH_SOUND;
88 const char *device = NULL; 85 const char *device = NULL;
89 86
90 while ((ch = getopt(argc, argv, "b:B:C:c:d:e:fhip:P:qs:Vv:")) != -1) { 87 while ((ch = getopt(argc, argv, "b:B:C:c:d:e:fhip:P:qs:Vv:")) != -1) {
91 switch (ch) { 88 switch (ch) {
92 case 'b': 89 case 'b':
93 decode_int(optarg, &balance); 90 decode_int(optarg, &balance);
94 if (balance < 0 || balance > 64) 91 if (balance < 0 || balance > 64)
95 errx(1, "balance must be between 0 and 63"); 92 errx(1, "balance must be between 0 and 63");
96 break; 93 break;
97 case 'B': 94 case 'B':
98 bufsize = strsuftoll("write buffer size", optarg, 95 bufsize = strsuftoll("write buffer size", optarg,
99 1, UINT_MAX); 96 1, UINT_MAX);
100 break; 97 break;
101 case 'c': 98 case 'c':
102 decode_int(optarg, &channels); 99 decode_int(optarg, &channels);
103 if (channels < 0) 100 if (channels < 0)
104 errx(1, "channels must be positive"); 101 errx(1, "channels must be positive");
105 break; 102 break;
106 case 'C': 103 case 'C':
107 /* Ignore, compatibility */ 104 /* Ignore, compatibility */
108 break; 105 break;
109 case 'd': 106 case 'd':
110 device = optarg; 107 device = optarg;
111 break; 108 break;
112 case 'e': 109 case 'e':
113 encoding_str = optarg; 110 encoding_str = optarg;
114 break; 111 break;
115 case 'f': 112 case 'f':
116 fflag = 1; 113 fflag = 1;
117 break; 114 break;
118 case 'i': 115 case 'i':
119 iflag++; 116 iflag++;
120 break; 117 break;
121 case 'q': 118 case 'q':
122 qflag++; 119 qflag++;
123 break; 120 break;
124 case 'P': 121 case 'P':
125 decode_int(optarg, &precision); 122 decode_int(optarg, &precision);
126 if (precision != 4 && precision != 8 && 123 if (precision != 4 && precision != 8 &&
127 precision != 16 && precision != 24 && 124 precision != 16 && precision != 24 &&
128 precision != 32) 125 precision != 32)
129 errx(1, "precision must be between 4, 8, 16, 24 or 32"); 126 errx(1, "precision must be between 4, 8, 16, 24 or 32");
130 break; 127 break;
131 case 'p': 128 case 'p':
132 len = strlen(optarg); 129 len = strlen(optarg);
133 130
134 if (strncmp(optarg, "speaker", len) == 0) 131 if (strncmp(optarg, "speaker", len) == 0)
135 port |= AUDIO_SPEAKER; 132 port |= AUDIO_SPEAKER;
136 else if (strncmp(optarg, "headphone", len) == 0) 133 else if (strncmp(optarg, "headphone", len) == 0)
137 port |= AUDIO_HEADPHONE; 134 port |= AUDIO_HEADPHONE;
138 else if (strncmp(optarg, "line", len) == 0) 135 else if (strncmp(optarg, "line", len) == 0)
139 port |= AUDIO_LINE_OUT; 136 port |= AUDIO_LINE_OUT;
140 else 137 else
141 errx(1, 138 errx(1,
142 "port must be `speaker', `headphone', or `line'"); 139 "port must be `speaker', `headphone', or `line'");
143 break; 140 break;
144 case 's': 141 case 's':
145 decode_int(optarg, &sample_rate); 142 decode_int(optarg, &sample_rate);
146 if (sample_rate < 0 || sample_rate > 48000 * 2) /* XXX */ 143 if (sample_rate < 0 || sample_rate > 48000 * 2) /* XXX */
147 errx(1, "sample rate must be between 0 and 96000"); 144 errx(1, "sample rate must be between 0 and 96000");
148 break; 145 break;
149 case 'V': 146 case 'V':
150 verbose++; 147 verbose++;
151 break; 148 break;
152 case 'v': 149 case 'v':
153 volume = atoi(optarg); 150 volume = atoi(optarg);
154 if (volume < 0 || volume > 255) 151 if (volume < 0 || volume > 255)
155 errx(1, "volume must be between 0 and 255"); 152 errx(1, "volume must be between 0 and 255");
156 break; 153 break;
157 /* case 'h': */ 154 /* case 'h': */
158 default: 155 default:
159 usage(); 156 usage();
160 /* NOTREACHED */ 157 /* NOTREACHED */
161 } 158 }
162 } 159 }
163 argc -= optind; 160 argc -= optind;
164 argv += optind; 161 argv += optind;
165 162
166 if (encoding_str) { 163 if (encoding_str) {
167 encoding = audio_enc_to_val(encoding_str); 164 encoding = audio_enc_to_val(encoding_str);
168 if (encoding == -1) 165 if (encoding == -1)
169 errx(1, "unknown encoding, bailing..."); 166 errx(1, "unknown encoding, bailing...");
170 } 167 }
171 168
172 if (device == NULL && (device = getenv("AUDIODEVICE")) == NULL && 169 if (device == NULL && (device = getenv("AUDIODEVICE")) == NULL &&
173 (device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */ 170 (device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */
174 device = defdevice; 171 device = defdevice;
175 172
176 audiofd = open(device, O_WRONLY); 173 audiofd = open(device, O_WRONLY);
177 if (audiofd < 0 && device == defdevice) { 174 if (audiofd < 0 && device == defdevice) {
178 device = _PATH_SOUND0; 175 device = _PATH_SOUND0;
179 audiofd = open(device, O_WRONLY); 176 audiofd = open(device, O_WRONLY);
180 } 177 }
181 178
182 if (audiofd < 0) 179 if (audiofd < 0)
183 err(1, "failed to open %s", device); 180 err(1, "failed to open %s", device);
184 181
185 if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0) 182 if (ioctl(audiofd, AUDIO_GETINFO, &info) < 0)
186 err(1, "failed to get audio info"); 183 err(1, "failed to get audio info");
187 if (bufsize == 0) { 184 if (bufsize == 0) {
188 bufsize = info.play.buffer_size; 185 bufsize = info.play.buffer_size;
189 if (bufsize < 32 * 1024) 186 if (bufsize < 32 * 1024)
190 bufsize = 32 * 1024; 187 bufsize = 32 * 1024;
191 } 188 }
192 189
193 signal(SIGINT, cleanup); 190 signal(SIGINT, cleanup);
194 signal(SIGTERM, cleanup); 191 signal(SIGTERM, cleanup);
195 signal(SIGHUP, cleanup); 192 signal(SIGHUP, cleanup);
196 193
197 if (*argv) 194 if (*argv)
198 do 195 do
199 play(*argv++); 196 play(*argv++);
200 while (*argv); 197 while (*argv);
201 else 198 else
202 play_fd("standard input", STDIN_FILENO); 199 play_fd("standard input", STDIN_FILENO);
203 200
204 cleanup(0); 201 cleanup(0);
205} 202}
206 203
207void 204static void
208cleanup(signo) 205cleanup(int signo)
209 int signo; 
210{ 206{
211 207
212 (void)ioctl(audiofd, AUDIO_FLUSH, NULL); 208 (void)ioctl(audiofd, AUDIO_FLUSH, NULL);
213 (void)ioctl(audiofd, AUDIO_SETINFO, &info); 209 (void)ioctl(audiofd, AUDIO_SETINFO, &info);
214 close(audiofd); 210 close(audiofd);
215 if (signo != 0) { 211 if (signo != 0) {
216 (void)raise_default_signal(signo); 212 (void)raise_default_signal(signo);
217 } 213 }
218 exit(exitstatus); 214 exit(exitstatus);
219} 215}
220 216
221void 217static void
222play(file) 218play(char *file)
223 char *file; 
224{ 219{
225 struct stat sb; 220 struct stat sb;
226 void *addr, *oaddr; 221 void *addr, *oaddr;
227 off_t filesize; 222 off_t filesize;
228 size_t sizet_filesize; 223 size_t sizet_filesize;
229 size_t datasize = 0; 224 size_t datasize = 0;
230 ssize_t hdrlen; 225 ssize_t hdrlen;
231 int fd; 226 int fd;
232 227
233 if (file[0] == '-' && file[1] == 0) { 228 if (file[0] == '-' && file[1] == 0) {
234 play_fd("standard input", STDIN_FILENO); 229 play_fd("standard input", STDIN_FILENO);
235 return; 230 return;
236 } 231 }
237 232
238 fd = open(file, O_RDONLY); 233 fd = open(file, O_RDONLY);
239 if (fd < 0) { 234 if (fd < 0) {
240 if (!qflag) 235 if (!qflag)
241 warn("could not open %s", file); 236 warn("could not open %s", file);
242 exitstatus = EXIT_FAILURE; 237 exitstatus = EXIT_FAILURE;
243 return; 238 return;
244 } 239 }
245 240
246 if (fstat(fd, &sb) < 0) 241 if (fstat(fd, &sb) < 0)
247 err(1, "could not fstat %s", file); 242 err(1, "could not fstat %s", file);
248 filesize = sb.st_size; 243 filesize = sb.st_size;
249 sizet_filesize = (size_t)filesize; 244 sizet_filesize = (size_t)filesize;
250 245
251 /* 246 /*
252 * if the file is not a regular file, doesn't fit in a size_t, 247 * if the file is not a regular file, doesn't fit in a size_t,
253 * or if we failed to mmap the file, try to read it instead, so 248 * or if we failed to mmap the file, try to read it instead, so
254 * that filesystems, etc, that do not support mmap() work 249 * that filesystems, etc, that do not support mmap() work
255 */ 250 */
256 if (S_ISREG(sb.st_rdev & S_IFMT) == 0 ||  251 if (S_ISREG(sb.st_rdev & S_IFMT) == 0 ||
257 ((off_t)sizet_filesize != filesize) || 252 ((off_t)sizet_filesize != filesize) ||
258 (oaddr = addr = mmap(0, sizet_filesize, PROT_READ, 253 (oaddr = addr = mmap(0, sizet_filesize, PROT_READ,
259 MAP_SHARED, fd, 0)) == MAP_FAILED) { 254 MAP_SHARED, fd, 0)) == MAP_FAILED) {
260 play_fd(file, fd); 255 play_fd(file, fd);
261 close(fd); 256 close(fd);
262 return; 257 return;
263 } 258 }
264 259
265 /* 260 /*
266 * give the VM system a bit of a hint about the type 261 * give the VM system a bit of a hint about the type
267 * of accesses we will make. we don't care about errors. 262 * of accesses we will make. we don't care about errors.
268 */ 263 */
269 madvise(addr, sizet_filesize, MADV_SEQUENTIAL); 264 madvise(addr, sizet_filesize, MADV_SEQUENTIAL);
270 265
271 /* 266 /*
272 * get the header length and set up the audio device 267 * get the header length and set up the audio device
273 */ 268 */
274 if ((hdrlen = audioctl_write_fromhdr(addr, 269 if ((hdrlen = audioctl_write_fromhdr(addr,
275 sizet_filesize, audiofd, &datasize, file)) < 0) { 270 sizet_filesize, audiofd, &datasize, file)) < 0) {
276 if (play_errstring) 271 if (play_errstring)
277 errx(1, "%s: %s", play_errstring, file); 272 errx(1, "%s: %s", play_errstring, file);
278 else 273 else
279 errx(1, "unknown audio file: %s", file); 274 errx(1, "unknown audio file: %s", file);
280 } 275 }
281 276
282 filesize -= hdrlen; 277 filesize -= hdrlen;
283 addr = (char *)addr + hdrlen; 278 addr = (char *)addr + hdrlen;
284 if ((uint64_t)filesize < datasize || datasize == 0) { 279 if ((uint64_t)filesize < datasize || datasize == 0) {
285 if ((uint64_t)filesize < datasize) 280 if ((uint64_t)filesize < datasize)
286 warnx("bogus datasize: %ld", (u_long)datasize); 281 warnx("bogus datasize: %ld", (u_long)datasize);
287 datasize = filesize; 282 datasize = filesize;
288 } 283 }
289 284
290 while (datasize > bufsize) { 285 while (datasize > bufsize) {
291 if ((size_t)write(audiofd, addr, bufsize) != bufsize) 286 if ((size_t)write(audiofd, addr, bufsize) != bufsize)
292 err(1, "write failed"); 287 err(1, "write failed");
293 addr = (char *)addr + bufsize; 288 addr = (char *)addr + bufsize;
294 datasize -= bufsize; 289 datasize -= bufsize;
295 } 290 }
296 if ((size_t)write(audiofd, addr, datasize) != datasize) 291 if ((size_t)write(audiofd, addr, datasize) != datasize)
297 err(1, "final write failed"); 292 err(1, "final write failed");
298 293
299 if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag) 294 if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
300 warn("audio drain ioctl failed"); 295 warn("audio drain ioctl failed");
301 if (munmap(oaddr, sizet_filesize) < 0) 296 if (munmap(oaddr, sizet_filesize) < 0)
302 err(1, "munmap failed"); 297 err(1, "munmap failed");
303 298
304 close(fd); 299 close(fd);
305} 300}
306 301
307/* 302/*
308 * play the file on the file descriptor fd 303 * play the file on the file descriptor fd
309 */ 304 */
310void 305static void
311play_fd(file, fd) 306play_fd(const char *file, int fd)
312 const char *file; 
313 int fd; 
314{ 307{
315 char *buffer = malloc(bufsize); 308 char *buffer = malloc(bufsize);
316 ssize_t hdrlen; 309 ssize_t hdrlen;
317 int nr, nw; 310 int nr, nw;
318 size_t datasize = 0; 311 size_t datasize = 0;
319 size_t dataout = 0; 312 size_t dataout = 0;
320 313
321 if (buffer == NULL) 314 if (buffer == NULL)
322 err(1, "malloc of read buffer failed"); 315 err(1, "malloc of read buffer failed");
323 316
324 nr = read(fd, buffer, bufsize); 317 nr = read(fd, buffer, bufsize);
325 if (nr < 0) 318 if (nr < 0)
326 goto read_error; 319 goto read_error;
327 if (nr == 0) { 320 if (nr == 0) {
328 if (fflag) { 321 if (fflag) {
329 free(buffer); 322 free(buffer);
330 return; 323 return;
331 } 324 }
332 err(1, "unexpected EOF"); 325 err(1, "unexpected EOF");
333 } 326 }
334 hdrlen = audioctl_write_fromhdr(buffer, nr, audiofd, &datasize, file); 327 hdrlen = audioctl_write_fromhdr(buffer, nr, audiofd, &datasize, file);
335 if (hdrlen < 0) { 328 if (hdrlen < 0) {
336 if (play_errstring) 329 if (play_errstring)
337 errx(1, "%s: %s", play_errstring, file); 330 errx(1, "%s: %s", play_errstring, file);
338 else 331 else
339 errx(1, "unknown audio file: %s", file); 332 errx(1, "unknown audio file: %s", file);
340 } 333 }
341 if (hdrlen > 0) { 334 if (hdrlen > 0) {
342 if (hdrlen > nr) /* shouldn't happen */ 335 if (hdrlen > nr) /* shouldn't happen */
343 errx(1, "header seems really large: %lld", (long long)hdrlen); 336 errx(1, "header seems really large: %lld", (long long)hdrlen);
344 memmove(buffer, buffer + hdrlen, nr - hdrlen); 337 memmove(buffer, buffer + hdrlen, nr - hdrlen);
345 nr -= hdrlen; 338 nr -= hdrlen;
346 } 339 }
347 while (datasize == 0 || dataout < datasize) { 340 while (datasize == 0 || dataout < datasize) {
348 if (datasize != 0 && dataout + nr > datasize) 341 if (datasize != 0 && dataout + nr > datasize)
349 nr = datasize - dataout; 342 nr = datasize - dataout;
350 nw = write(audiofd, buffer, nr); 343 nw = write(audiofd, buffer, nr);
351 if (nw != nr) 344 if (nw != nr)
352 goto write_error; 345 goto write_error;
353 dataout += nw; 346 dataout += nw;
354 nr = read(fd, buffer, bufsize); 347 nr = read(fd, buffer, bufsize);
355 if (nr == -1) 348 if (nr == -1)
356 goto read_error; 349 goto read_error;
357 if (nr == 0) 350 if (nr == 0)
358 break; 351 break;
359 } 352 }
360 /* something to think about: no message given for dataout < datasize */ 353 /* something to think about: no message given for dataout < datasize */
361 if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag) 354 if (ioctl(audiofd, AUDIO_DRAIN) < 0 && !qflag)
362 warn("audio drain ioctl failed"); 355 warn("audio drain ioctl failed");
363 return; 356 return;
364read_error: 357read_error:
365 err(1, "read of standard input failed"); 358 err(1, "read of standard input failed");
366write_error: 359write_error:
367 err(1, "audio device write failed"); 360 err(1, "audio device write failed");
368} 361}
369 362
370/* 363/*
371 * only support sun and wav audio files so far ... 364 * only support sun and wav audio files so far ...
372 * 365 *
373 * XXX this should probably be mostly part of libaudio, but it 366 * XXX this should probably be mostly part of libaudio, but it
374 * uses the local "info" variable. blah... fix me! 367 * uses the local "info" variable. blah... fix me!
375 */ 368 */
376ssize_t 369static ssize_t
377audioctl_write_fromhdr(hdr, fsz, fd, datasize, file) 370audioctl_write_fromhdr(void *hdr, size_t fsz, int fd, size_t *datasize, const char *file)
378 void *hdr; 
379 size_t fsz; 
380 int fd; 
381 size_t *datasize; 
382 const char *file; 
383{ 371{
384 sun_audioheader *sunhdr; 372 sun_audioheader *sunhdr;
385 ssize_t hdr_len = 0; 373 ssize_t hdr_len = 0;
386 374
387 AUDIO_INITINFO(&info); 375 AUDIO_INITINFO(&info);
388 sunhdr = hdr; 376 sunhdr = hdr;
389 if (ntohl(sunhdr->magic) == AUDIO_FILE_MAGIC) { 377 if (ntohl(sunhdr->magic) == AUDIO_FILE_MAGIC) {
390 if (audio_sun_to_encoding(ntohl(sunhdr->encoding), 378 if (audio_sun_to_encoding(ntohl(sunhdr->encoding),
391 &info.play.encoding, &info.play.precision)) { 379 &info.play.encoding, &info.play.precision)) {
392 if (!qflag) 380 if (!qflag)
393 warnx("unknown unsupported Sun audio encoding" 381 warnx("unknown unsupported Sun audio encoding"
394 " format %d", ntohl(sunhdr->encoding)); 382 " format %d", ntohl(sunhdr->encoding));
395 if (fflag) 383 if (fflag)
396 goto set_audio_mode; 384 goto set_audio_mode;
397 return (-1); 385 return (-1);
398 } 386 }
399 387
400 info.play.sample_rate = ntohl(sunhdr->sample_rate); 388 info.play.sample_rate = ntohl(sunhdr->sample_rate);
401 info.play.channels = ntohl(sunhdr->channels); 389 info.play.channels = ntohl(sunhdr->channels);
402 hdr_len = ntohl(sunhdr->hdr_size); 390 hdr_len = ntohl(sunhdr->hdr_size);
403 391
404 *datasize = ntohl(sunhdr->data_size); 392 *datasize = ntohl(sunhdr->data_size);
405 goto set_audio_mode; 393 goto set_audio_mode;
406 } 394 }
407 395
408 hdr_len = audio_wav_parse_hdr(hdr, fsz, &info.play.encoding, 396 hdr_len = audio_wav_parse_hdr(hdr, fsz, &info.play.encoding,
409 &info.play.precision, &info.play.sample_rate, &info.play.channels, 397 &info.play.precision, &info.play.sample_rate, &info.play.channels,
410 datasize); 398 datasize);
411 399
412 switch (hdr_len) { 400 switch (hdr_len) {
413 case AUDIO_ESHORTHDR: 401 case AUDIO_ESHORTHDR:
414 case AUDIO_EWAVUNSUPP: 402 case AUDIO_EWAVUNSUPP:
415 case AUDIO_EWAVBADPCM: 403 case AUDIO_EWAVBADPCM:
416 case AUDIO_EWAVNODATA: 404 case AUDIO_EWAVNODATA:
417 play_errstring = audio_errstring(hdr_len); 405 play_errstring = audio_errstring(hdr_len);
418 /* FALL THROUGH */ 406 /* FALL THROUGH */
419 case AUDIO_ENOENT: 407 case AUDIO_ENOENT:
420 break; 408 break;
421 default: 409 default:
422 if (hdr_len < 1) 410 if (hdr_len < 1)
423 break; 411 break;
424 goto set_audio_mode; 412 goto set_audio_mode;
425 } 413 }
426 /* 414 /*
427 * if we don't know it, bail unless we are forcing. 415 * if we don't know it, bail unless we are forcing.
428 */ 416 */
429 if (fflag == 0) 417 if (fflag == 0)
430 return (-1); 418 return (-1);
431set_audio_mode: 419set_audio_mode:
432 if (port) 420 if (port)
433 info.play.port = port; 421 info.play.port = port;
434 if (volume) 422 if (volume)
435 info.play.gain = volume; 423 info.play.gain = volume;
436 if (balance) 424 if (balance)
437 info.play.balance = balance; 425 info.play.balance = balance;
438 if (fflag) { 426 if (fflag) {
439 if (sample_rate) 427 if (sample_rate)
440 info.play.sample_rate = sample_rate; 428 info.play.sample_rate = sample_rate;
441 if (channels) 429 if (channels)
442 info.play.channels = channels; 430 info.play.channels = channels;
443 if (encoding) 431 if (encoding)
444 info.play.encoding = encoding; 432 info.play.encoding = encoding;
445 if (precision) 433 if (precision)
446 info.play.precision = precision; 434 info.play.precision = precision;
447 hdr_len = 0; 435 hdr_len = 0;
448 } 436 }
449 info.mode = AUMODE_PLAY_ALL; 437 info.mode = AUMODE_PLAY_ALL;
450 438
451 if (verbose) { 439 if (verbose) {
452 const char *enc = audio_enc_from_val(info.play.encoding); 440 const char *enc = audio_enc_from_val(info.play.encoding);
453 441
454 printf("%s: sample_rate=%d channels=%d " 442 printf("%s: sample_rate=%d channels=%d "
455 "datasize=%lld " 443 "datasize=%lld "
456 "precision=%d%s%s\n", file, 444 "precision=%d%s%s\n", file,
457 info.play.sample_rate, 445 info.play.sample_rate,
458 info.play.channels, 446 info.play.channels,
459 (long long)*datasize, 447 (long long)*datasize,
460 info.play.precision, 448 info.play.precision,
461 enc ? " encoding=" : "",  449 enc ? " encoding=" : "",
462 enc ? enc : ""); 450 enc ? enc : "");
463 } 451 }
464 452
465 if (ioctl(fd, AUDIO_SETINFO, &info) < 0) 453 if (ioctl(fd, AUDIO_SETINFO, &info) < 0)
466 err(1, "failed to set audio info"); 454 err(1, "failed to set audio info");
467 455
468 return (hdr_len); 456 return (hdr_len);
469} 457}
470 458
471void 459static void
472usage() 460usage(void)
473{ 461{
474 462
475 fprintf(stderr, "Usage: %s [-hiqV] [options] files\n", getprogname()); 463 fprintf(stderr, "Usage: %s [-hiqV] [options] files\n", getprogname());
476 fprintf(stderr, "Options:\n\t" 464 fprintf(stderr, "Options:\n\t"
477 "-B buffer size\n\t" 465 "-B buffer size\n\t"
478 "-b balance (0-63)\n\t" 466 "-b balance (0-63)\n\t"
479 "-d audio device\n\t" 467 "-d audio device\n\t"
480 "-f force settings\n\t" 468 "-f force settings\n\t"
481 "\t-c forced channels\n\t" 469 "\t-c forced channels\n\t"
482 "\t-e forced encoding\n\t" 470 "\t-e forced encoding\n\t"
483 "\t-P forced precision\n\t" 471 "\t-P forced precision\n\t"
484 "\t-s forced sample rate\n\t" 472 "\t-s forced sample rate\n\t"
485 "-i header information\n\t" 473 "-i header information\n\t"
486 "-p output port\n\t" 474 "-p output port\n\t"
487 "-v volume\n"); 475 "-v volume\n");
488 exit(EXIT_FAILURE); 476 exit(EXIT_FAILURE);
489} 477}

cvs diff -r1.50 -r1.51 src/usr.bin/audio/record/record.c (switch to unified diff)

--- src/usr.bin/audio/record/record.c 2010/12/29 18:49:41 1.50
+++ src/usr.bin/audio/record/record.c 2011/08/28 01:17:48 1.51
@@ -1,796 +1,784 @@ @@ -1,796 +1,784 @@
1/* $NetBSD: record.c,v 1.50 2010/12/29 18:49:41 wiz Exp $ */ 1/* $NetBSD: record.c,v 1.51 2011/08/28 01:17:48 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2002, 2003, 2005, 2010 Matthew R. Green 4 * Copyright (c) 1999, 2002, 2003, 2005, 2010 Matthew R. Green
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * SunOS compatible audiorecord(1) 30 * SunOS compatible audiorecord(1)
31 */ 31 */
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34#ifndef lint 34#ifndef lint
35__RCSID("$NetBSD: record.c,v 1.50 2010/12/29 18:49:41 wiz Exp $"); 35__RCSID("$NetBSD: record.c,v 1.51 2011/08/28 01:17:48 joerg Exp $");
36#endif 36#endif
37 37
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/audioio.h> 40#include <sys/audioio.h>
41#include <sys/ioctl.h> 41#include <sys/ioctl.h>
42#include <sys/time.h> 42#include <sys/time.h>
43#include <sys/uio.h> 43#include <sys/uio.h>
44 44
45#include <err.h> 45#include <err.h>
46#include <fcntl.h> 46#include <fcntl.h>
47#include <paths.h> 47#include <paths.h>
48#include <signal.h> 48#include <signal.h>
49#include <stdio.h> 49#include <stdio.h>
50#include <stdlib.h> 50#include <stdlib.h>
51#include <string.h> 51#include <string.h>
52#include <unistd.h> 52#include <unistd.h>
53#include <util.h> 53#include <util.h>
54 54
55#include "libaudio.h" 55#include "libaudio.h"
56#include "auconv.h" 56#include "auconv.h"
57 57
58audio_info_t info, oinfo; 58static audio_info_t info, oinfo;
59ssize_t total_size = -1; 59static ssize_t total_size = -1;
60const char *device; 60static const char *device;
61int format = AUDIO_FORMAT_DEFAULT; 61static int format = AUDIO_FORMAT_DEFAULT;
62char *header_info; 62static char *header_info;
63char default_info[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; 63static char default_info[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
64int audiofd, outfd; 64static int audiofd, outfd;
65int qflag, aflag, fflag; 65static int qflag, aflag, fflag;
66int verbose; 66int verbose;
67int monitor_gain, omonitor_gain; 67static int monitor_gain, omonitor_gain;
68int gain; 68static int gain;
69int balance; 69static int balance;
70int port; 70static int port;
71int encoding; 71static int encoding;
72char *encoding_str; 72static char *encoding_str;
73int precision; 73static int precision;
74int sample_rate; 74static int sample_rate;
75int channels; 75static int channels;
76struct timeval record_time; 76static struct timeval record_time;
77struct timeval start_time; 77static struct timeval start_time;
78 78
79void (*conv_func) (u_char *, int); 79static void (*conv_func) (u_char *, int);
80 80
81void usage (void); 81static void usage (void) __dead;
82int main (int, char *[]); 82static int timeleft (struct timeval *, struct timeval *);
83int timeleft (struct timeval *, struct timeval *); 83static void cleanup (int) __dead;
84void cleanup (int) __dead; 84static int write_header_sun (void **, size_t *, int *);
85int write_header_sun (void **, size_t *, int *); 85static int write_header_wav (void **, size_t *, int *);
86int write_header_wav (void **, size_t *, int *); 86static void write_header (void);
87void write_header (void); 87static void rewrite_header (void);
88void rewrite_header (void); 
89 88
90int 89int
91main(argc, argv) 90main(int argc, char *argv[])
92 int argc; 
93 char *argv[]; 
94{ 91{
95 u_char *buffer; 92 u_char *buffer;
96 size_t len, bufsize = 0; 93 size_t len, bufsize = 0;
97 int ch, no_time_limit = 1; 94 int ch, no_time_limit = 1;
98 const char *defdevice = _PATH_SOUND; 95 const char *defdevice = _PATH_SOUND;
99 96
100 while ((ch = getopt(argc, argv, "ab:B:C:F:c:d:e:fhi:m:P:p:qt:s:Vv:")) != -1) { 97 while ((ch = getopt(argc, argv, "ab:B:C:F:c:d:e:fhi:m:P:p:qt:s:Vv:")) != -1) {
101 switch (ch) { 98 switch (ch) {
102 case 'a': 99 case 'a':
103 aflag++; 100 aflag++;
104 break; 101 break;
105 case 'b': 102 case 'b':
106 decode_int(optarg, &balance); 103 decode_int(optarg, &balance);
107 if (balance < 0 || balance > 63) 104 if (balance < 0 || balance > 63)
108 errx(1, "balance must be between 0 and 63"); 105 errx(1, "balance must be between 0 and 63");
109 break; 106 break;
110 case 'B': 107 case 'B':
111 bufsize = strsuftoll("read buffer size", optarg, 108 bufsize = strsuftoll("read buffer size", optarg,
112 1, UINT_MAX); 109 1, UINT_MAX);
113 break; 110 break;
114 case 'C': 111 case 'C':
115 /* Ignore, compatibility */ 112 /* Ignore, compatibility */
116 break; 113 break;
117 case 'F': 114 case 'F':
118 format = audio_format_from_str(optarg); 115 format = audio_format_from_str(optarg);
119 if (format < 0) 116 if (format < 0)
120 errx(1, "Unknown audio format; supported " 117 errx(1, "Unknown audio format; supported "
121 "formats: \"sun\", \"wav\", and \"none\""); 118 "formats: \"sun\", \"wav\", and \"none\"");
122 break; 119 break;
123 case 'c': 120 case 'c':
124 decode_int(optarg, &channels); 121 decode_int(optarg, &channels);
125 if (channels < 0 || channels > 16) 122 if (channels < 0 || channels > 16)
126 errx(1, "channels must be between 0 and 16"); 123 errx(1, "channels must be between 0 and 16");
127 break; 124 break;
128 case 'd': 125 case 'd':
129 device = optarg; 126 device = optarg;
130 break; 127 break;
131 case 'e': 128 case 'e':
132 encoding_str = optarg; 129 encoding_str = optarg;
133 break; 130 break;
134 case 'f': 131 case 'f':
135 fflag++; 132 fflag++;
136 break; 133 break;
137 case 'i': 134 case 'i':
138 header_info = optarg; 135 header_info = optarg;
139 break; 136 break;
140 case 'm': 137 case 'm':
141 decode_int(optarg, &monitor_gain); 138 decode_int(optarg, &monitor_gain);
142 if (monitor_gain < 0 || monitor_gain > 255) 139 if (monitor_gain < 0 || monitor_gain > 255)
143 errx(1, "monitor volume must be between 0 and 255"); 140 errx(1, "monitor volume must be between 0 and 255");
144 break; 141 break;
145 case 'P': 142 case 'P':
146 decode_int(optarg, &precision); 143 decode_int(optarg, &precision);
147 if (precision != 4 && precision != 8 && 144 if (precision != 4 && precision != 8 &&
148 precision != 16 && precision != 24 && 145 precision != 16 && precision != 24 &&
149 precision != 32) 146 precision != 32)
150 errx(1, "precision must be between 4, 8, 16, 24 or 32"); 147 errx(1, "precision must be between 4, 8, 16, 24 or 32");
151 break; 148 break;
152 case 'p': 149 case 'p':
153 len = strlen(optarg); 150 len = strlen(optarg);
154 151
155 if (strncmp(optarg, "mic", len) == 0) 152 if (strncmp(optarg, "mic", len) == 0)
156 port |= AUDIO_MICROPHONE; 153 port |= AUDIO_MICROPHONE;
157 else if (strncmp(optarg, "cd", len) == 0 || 154 else if (strncmp(optarg, "cd", len) == 0 ||
158 strncmp(optarg, "internal-cd", len) == 0) 155 strncmp(optarg, "internal-cd", len) == 0)
159 port |= AUDIO_CD; 156 port |= AUDIO_CD;
160 else if (strncmp(optarg, "line", len) == 0) 157 else if (strncmp(optarg, "line", len) == 0)
161 port |= AUDIO_LINE_IN; 158 port |= AUDIO_LINE_IN;
162 else 159 else
163 errx(1, 160 errx(1,
164 "port must be `cd', `internal-cd', `mic', or `line'"); 161 "port must be `cd', `internal-cd', `mic', or `line'");
165 break; 162 break;
166 case 'q': 163 case 'q':
167 qflag++; 164 qflag++;
168 break; 165 break;
169 case 's': 166 case 's':
170 decode_int(optarg, &sample_rate); 167 decode_int(optarg, &sample_rate);
171 if (sample_rate < 0 || sample_rate > 48000 * 2) /* XXX */ 168 if (sample_rate < 0 || sample_rate > 48000 * 2) /* XXX */
172 errx(1, "sample rate must be between 0 and 96000"); 169 errx(1, "sample rate must be between 0 and 96000");
173 break; 170 break;
174 case 't': 171 case 't':
175 no_time_limit = 0; 172 no_time_limit = 0;
176 decode_time(optarg, &record_time); 173 decode_time(optarg, &record_time);
177 break; 174 break;
178 case 'V': 175 case 'V':
179 verbose++; 176 verbose++;
180 break; 177 break;
181 case 'v': 178 case 'v':
182 decode_int(optarg, &gain); 179 decode_int(optarg, &gain);
183 if (gain < 0 || gain > 255) 180 if (gain < 0 || gain > 255)
184 errx(1, "volume must be between 0 and 255"); 181 errx(1, "volume must be between 0 and 255");
185 break; 182 break;
186 /* case 'h': */ 183 /* case 'h': */
187 default: 184 default:
188 usage(); 185 usage();
189 /* NOTREACHED */ 186 /* NOTREACHED */
190 } 187 }
191 } 188 }
192 argc -= optind; 189 argc -= optind;
193 argv += optind; 190 argv += optind;
194 191
195 if (argc != 1) 192 if (argc != 1)
196 usage(); 193 usage();
197 194
198 /* 195 /*
199 * convert the encoding string into a value. 196 * convert the encoding string into a value.
200 */ 197 */
201 if (encoding_str) { 198 if (encoding_str) {
202 encoding = audio_enc_to_val(encoding_str); 199 encoding = audio_enc_to_val(encoding_str);
203 if (encoding == -1) 200 if (encoding == -1)
204 errx(1, "unknown encoding, bailing..."); 201 errx(1, "unknown encoding, bailing...");
205 } 202 }
206 203
207 /* 204 /*
208 * open the output file 205 * open the output file
209 */ 206 */
210 if (argv[0][0] != '-' || argv[0][1] != '\0') { 207 if (argv[0][0] != '-' || argv[0][1] != '\0') {
211 /* intuit the file type from the name */ 208 /* intuit the file type from the name */
212 if (format == AUDIO_FORMAT_DEFAULT) 209 if (format == AUDIO_FORMAT_DEFAULT)
213 { 210 {
214 size_t flen = strlen(*argv); 211 size_t flen = strlen(*argv);
215 const char *arg = *argv; 212 const char *arg = *argv;
216 213
217 if (strcasecmp(arg + flen - 3, ".au") == 0) 214 if (strcasecmp(arg + flen - 3, ".au") == 0)
218 format = AUDIO_FORMAT_SUN; 215 format = AUDIO_FORMAT_SUN;
219 else if (strcasecmp(arg + flen - 4, ".wav") == 0) 216 else if (strcasecmp(arg + flen - 4, ".wav") == 0)
220 format = AUDIO_FORMAT_WAV; 217 format = AUDIO_FORMAT_WAV;
221 } 218 }
222 outfd = open(*argv, O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY, 0666); 219 outfd = open(*argv, O_CREAT|(aflag ? O_APPEND : O_TRUNC)|O_WRONLY, 0666);
223 if (outfd < 0) 220 if (outfd < 0)
224 err(1, "could not open %s", *argv); 221 err(1, "could not open %s", *argv);
225 } else 222 } else
226 outfd = STDOUT_FILENO; 223 outfd = STDOUT_FILENO;
227 224
228 /* 225 /*
229 * open the audio device 226 * open the audio device
230 */ 227 */
231 if (device == NULL && (device = getenv("AUDIODEVICE")) == NULL && 228 if (device == NULL && (device = getenv("AUDIODEVICE")) == NULL &&
232 (device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */ 229 (device = getenv("AUDIODEV")) == NULL) /* Sun compatibility */
233 device = defdevice; 230 device = defdevice;
234 231
235 audiofd = open(device, O_RDONLY); 232 audiofd = open(device, O_RDONLY);
236 if (audiofd < 0 && device == defdevice) { 233 if (audiofd < 0 && device == defdevice) {
237 device = _PATH_SOUND0; 234 device = _PATH_SOUND0;
238 audiofd = open(device, O_RDONLY); 235 audiofd = open(device, O_RDONLY);
239 } 236 }
240 if (audiofd < 0) 237 if (audiofd < 0)
241 err(1, "failed to open %s", device); 238 err(1, "failed to open %s", device);
242 239
243 /* 240 /*
244 * work out the buffer size to use, and allocate it. also work out 241 * work out the buffer size to use, and allocate it. also work out
245 * what the old monitor gain value is, so that we can reset it later. 242 * what the old monitor gain value is, so that we can reset it later.
246 */ 243 */
247 if (ioctl(audiofd, AUDIO_GETINFO, &oinfo) < 0) 244 if (ioctl(audiofd, AUDIO_GETINFO, &oinfo) < 0)
248 err(1, "failed to get audio info"); 245 err(1, "failed to get audio info");
249 if (bufsize == 0) { 246 if (bufsize == 0) {
250 bufsize = oinfo.record.buffer_size; 247 bufsize = oinfo.record.buffer_size;
251 if (bufsize < 32 * 1024) 248 if (bufsize < 32 * 1024)
252 bufsize = 32 * 1024; 249 bufsize = 32 * 1024;
253 } 250 }
254 omonitor_gain = oinfo.monitor_gain; 251 omonitor_gain = oinfo.monitor_gain;
255 252
256 buffer = malloc(bufsize); 253 buffer = malloc(bufsize);
257 if (buffer == NULL) 254 if (buffer == NULL)
258 err(1, "couldn't malloc buffer of %d size", (int)bufsize); 255 err(1, "couldn't malloc buffer of %d size", (int)bufsize);
259 256
260 /* 257 /*
261 * set up audio device for recording with the speified parameters 258 * set up audio device for recording with the speified parameters
262 */ 259 */
263 AUDIO_INITINFO(&info); 260 AUDIO_INITINFO(&info);
264 261
265 /* 262 /*
266 * for these, get the current values for stuffing into the header 263 * for these, get the current values for stuffing into the header
267 */ 264 */
268#define SETINFO(x) if (x) \ 265#define SETINFO(x) if (x) \
269 info.record.x = x; \ 266 info.record.x = x; \
270 else \ 267 else \
271 info.record.x = x = oinfo.record.x; 268 info.record.x = x = oinfo.record.x;
272 SETINFO (sample_rate) 269 SETINFO (sample_rate)
273 SETINFO (channels) 270 SETINFO (channels)
274 SETINFO (precision) 271 SETINFO (precision)
275 SETINFO (encoding) 272 SETINFO (encoding)
276 SETINFO (gain) 273 SETINFO (gain)
277 SETINFO (port) 274 SETINFO (port)
278 SETINFO (balance) 275 SETINFO (balance)
279#undef SETINFO 276#undef SETINFO
280 277
281 if (monitor_gain) 278 if (monitor_gain)
282 info.monitor_gain = monitor_gain; 279 info.monitor_gain = monitor_gain;
283 else 280 else
284 monitor_gain = oinfo.monitor_gain; 281 monitor_gain = oinfo.monitor_gain;
285 282
286 info.mode = AUMODE_RECORD; 283 info.mode = AUMODE_RECORD;
287 if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) 284 if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0)
288 err(1, "failed to set audio info"); 285 err(1, "failed to set audio info");
289 286
290 signal(SIGINT, cleanup); 287 signal(SIGINT, cleanup);
291 write_header(); 288 write_header();
292 total_size = 0; 289 total_size = 0;
293 290
294 if (verbose && conv_func) { 291 if (verbose && conv_func) {
295 const char *s = NULL; 292 const char *s = NULL;
296 293
297 if (conv_func == swap_bytes) 294 if (conv_func == swap_bytes)
298 s = "swap bytes (16 bit)"; 295 s = "swap bytes (16 bit)";
299 else if (conv_func == swap_bytes32) 296 else if (conv_func == swap_bytes32)
300 s = "swap bytes (32 bit)"; 297 s = "swap bytes (32 bit)";
301 else if (conv_func == change_sign16_be) 298 else if (conv_func == change_sign16_be)
302 s = "change sign (big-endian, 16 bit)"; 299 s = "change sign (big-endian, 16 bit)";
303 else if (conv_func == change_sign16_le) 300 else if (conv_func == change_sign16_le)
304 s = "change sign (little-endian, 16 bit)"; 301 s = "change sign (little-endian, 16 bit)";
305 else if (conv_func == change_sign32_be) 302 else if (conv_func == change_sign32_be)
306 s = "change sign (big-endian, 32 bit)"; 303 s = "change sign (big-endian, 32 bit)";
307 else if (conv_func == change_sign32_le) 304 else if (conv_func == change_sign32_le)
308 s = "change sign (little-endian, 32 bit)"; 305 s = "change sign (little-endian, 32 bit)";
309 else if (conv_func == change_sign16_swap_bytes_be) 306 else if (conv_func == change_sign16_swap_bytes_be)
310 s = "change sign & swap bytes (big-endian, 16 bit)"; 307 s = "change sign & swap bytes (big-endian, 16 bit)";
311 else if (conv_func == change_sign16_swap_bytes_le) 308 else if (conv_func == change_sign16_swap_bytes_le)
312 s = "change sign & swap bytes (little-endian, 16 bit)"; 309 s = "change sign & swap bytes (little-endian, 16 bit)";
313 else if (conv_func == change_sign32_swap_bytes_be) 310 else if (conv_func == change_sign32_swap_bytes_be)
314 s = "change sign (big-endian, 32 bit)"; 311 s = "change sign (big-endian, 32 bit)";
315 else if (conv_func == change_sign32_swap_bytes_le) 312 else if (conv_func == change_sign32_swap_bytes_le)
316 s = "change sign & swap bytes (little-endian, 32 bit)"; 313 s = "change sign & swap bytes (little-endian, 32 bit)";
317  314
318 if (s) 315 if (s)
319 fprintf(stderr, "%s: converting, using function: %s\n", 316 fprintf(stderr, "%s: converting, using function: %s\n",
320 getprogname(), s); 317 getprogname(), s);
321 else 318 else
322 fprintf(stderr, "%s: using unnamed conversion " 319 fprintf(stderr, "%s: using unnamed conversion "
323 "function\n", getprogname()); 320 "function\n", getprogname());
324 } 321 }
325 322
326 if (verbose) 323 if (verbose)
327 fprintf(stderr, 324 fprintf(stderr,
328 "sample_rate=%d channels=%d precision=%d encoding=%s\n", 325 "sample_rate=%d channels=%d precision=%d encoding=%s\n",
329 info.record.sample_rate, info.record.channels, 326 info.record.sample_rate, info.record.channels,
330 info.record.precision, 327 info.record.precision,
331 audio_enc_from_val(info.record.encoding)); 328 audio_enc_from_val(info.record.encoding));
332 329
333 if (!no_time_limit && verbose) 330 if (!no_time_limit && verbose)
334 fprintf(stderr, "recording for %lu seconds, %lu microseconds\n", 331 fprintf(stderr, "recording for %lu seconds, %lu microseconds\n",
335 (u_long)record_time.tv_sec, (u_long)record_time.tv_usec); 332 (u_long)record_time.tv_sec, (u_long)record_time.tv_usec);
336 333
337 (void)gettimeofday(&start_time, NULL); 334 (void)gettimeofday(&start_time, NULL);
338 while (no_time_limit || timeleft(&start_time, &record_time)) { 335 while (no_time_limit || timeleft(&start_time, &record_time)) {
339 if ((size_t)read(audiofd, buffer, bufsize) != bufsize) 336 if ((size_t)read(audiofd, buffer, bufsize) != bufsize)
340 err(1, "read failed"); 337 err(1, "read failed");
341 if (conv_func) 338 if (conv_func)
342 (*conv_func)(buffer, bufsize); 339 (*conv_func)(buffer, bufsize);
343 if ((size_t)write(outfd, buffer, bufsize) != bufsize) 340 if ((size_t)write(outfd, buffer, bufsize) != bufsize)
344 err(1, "write failed"); 341 err(1, "write failed");
345 total_size += bufsize; 342 total_size += bufsize;
346 } 343 }
347 cleanup(0); 344 cleanup(0);
348} 345}
349 346
350int 347int
351timeleft(start_tvp, record_tvp) 348timeleft(struct timeval *start_tvp, struct timeval *record_tvp)
352 struct timeval *start_tvp; 
353 struct timeval *record_tvp; 
354{ 349{
355 struct timeval now, diff; 350 struct timeval now, diff;
356 351
357 (void)gettimeofday(&now, NULL); 352 (void)gettimeofday(&now, NULL);
358 timersub(&now, start_tvp, &diff); 353 timersub(&now, start_tvp, &diff);
359 timersub(record_tvp, &diff, &now); 354 timersub(record_tvp, &diff, &now);
360 355
361 return (now.tv_sec > 0 || (now.tv_sec == 0 && now.tv_usec > 0)); 356 return (now.tv_sec > 0 || (now.tv_sec == 0 && now.tv_usec > 0));
362} 357}
363 358
364void 359void
365cleanup(signo) 360cleanup(int signo)
366 int signo; 
367{ 361{
368 362
369 rewrite_header(); 363 rewrite_header();
370 close(outfd); 364 close(outfd);
371 if (omonitor_gain) { 365 if (omonitor_gain) {
372 AUDIO_INITINFO(&info); 366 AUDIO_INITINFO(&info);
373 info.monitor_gain = omonitor_gain; 367 info.monitor_gain = omonitor_gain;
374 if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0) 368 if (ioctl(audiofd, AUDIO_SETINFO, &info) < 0)
375 err(1, "failed to reset audio info"); 369 err(1, "failed to reset audio info");
376 } 370 }
377 close(audiofd); 371 close(audiofd);
378 if (signo != 0) { 372 if (signo != 0) {
379 (void)raise_default_signal(signo); 373 (void)raise_default_signal(signo);
380 } 374 }
381 exit(0); 375 exit(0);
382} 376}
383 377
384int 378static int
385write_header_sun(hdrp, lenp, leftp) 379write_header_sun(void **hdrp, size_t *lenp, int *leftp)
386 void **hdrp; 
387 size_t *lenp; 
388 int *leftp; 
389{ 380{
390 static int warned = 0; 381 static int warned = 0;
391 static sun_audioheader auh; 382 static sun_audioheader auh;
392 int sunenc, oencoding = encoding; 383 int sunenc, oencoding = encoding;
393 384
394 /* only perform conversions if we don't specify the encoding */ 385 /* only perform conversions if we don't specify the encoding */
395 switch (encoding) { 386 switch (encoding) {
396 case AUDIO_ENCODING_ULINEAR_LE: 387 case AUDIO_ENCODING_ULINEAR_LE:
397#if BYTE_ORDER == LITTLE_ENDIAN 388#if BYTE_ORDER == LITTLE_ENDIAN
398 case AUDIO_ENCODING_ULINEAR: 389 case AUDIO_ENCODING_ULINEAR:
399#endif 390#endif
400 if (precision == 16) 391 if (precision == 16)
401 conv_func = change_sign16_swap_bytes_le; 392 conv_func = change_sign16_swap_bytes_le;
402 else if (precision == 32) 393 else if (precision == 32)
403 conv_func = change_sign32_swap_bytes_le; 394 conv_func = change_sign32_swap_bytes_le;
404 if (conv_func) 395 if (conv_func)
405 encoding = AUDIO_ENCODING_SLINEAR_BE; 396 encoding = AUDIO_ENCODING_SLINEAR_BE;
406 break; 397 break;
407 398
408 case AUDIO_ENCODING_ULINEAR_BE: 399 case AUDIO_ENCODING_ULINEAR_BE:
409#if BYTE_ORDER == BIG_ENDIAN 400#if BYTE_ORDER == BIG_ENDIAN
410 case AUDIO_ENCODING_ULINEAR: 401 case AUDIO_ENCODING_ULINEAR:
411#endif 402#endif
412 if (precision == 16) 403 if (precision == 16)
413 conv_func = change_sign16_be; 404 conv_func = change_sign16_be;
414 else if (precision == 32) 405 else if (precision == 32)
415 conv_func = change_sign32_be; 406 conv_func = change_sign32_be;
416 if (conv_func) 407 if (conv_func)
417 encoding = AUDIO_ENCODING_SLINEAR_BE; 408 encoding = AUDIO_ENCODING_SLINEAR_BE;
418 break; 409 break;
419 410
420 case AUDIO_ENCODING_SLINEAR_LE: 411 case AUDIO_ENCODING_SLINEAR_LE:
421#if BYTE_ORDER == LITTLE_ENDIAN 412#if BYTE_ORDER == LITTLE_ENDIAN
422 case AUDIO_ENCODING_SLINEAR: 413 case AUDIO_ENCODING_SLINEAR:
423#endif 414#endif
424 if (precision == 16) 415 if (precision == 16)
425 conv_func = swap_bytes; 416 conv_func = swap_bytes;
426 else if (precision == 32) 417 else if (precision == 32)
427 conv_func = swap_bytes32; 418 conv_func = swap_bytes32;
428 if (conv_func) 419 if (conv_func)
429 encoding = AUDIO_ENCODING_SLINEAR_BE; 420 encoding = AUDIO_ENCODING_SLINEAR_BE;
430 break; 421 break;
431 422
432#if BYTE_ORDER == BIG_ENDIAN 423#if BYTE_ORDER == BIG_ENDIAN
433 case AUDIO_ENCODING_SLINEAR: 424 case AUDIO_ENCODING_SLINEAR:
434 encoding = AUDIO_ENCODING_SLINEAR_BE; 425 encoding = AUDIO_ENCODING_SLINEAR_BE;
435 break; 426 break;
436#endif 427#endif
437 } 428 }
438  429
439 /* if we can't express this as a Sun header, don't write any */ 430 /* if we can't express this as a Sun header, don't write any */
440 if (audio_encoding_to_sun(encoding, precision, &sunenc) != 0) { 431 if (audio_encoding_to_sun(encoding, precision, &sunenc) != 0) {
441 if (!qflag && !warned) { 432 if (!qflag && !warned) {
442 const char *s = audio_enc_from_val(oencoding); 433 const char *s = audio_enc_from_val(oencoding);
443 434
444 if (s == NULL) 435 if (s == NULL)
445 s = "(unknown)"; 436 s = "(unknown)";
446 warnx("failed to convert to sun encoding from %s " 437 warnx("failed to convert to sun encoding from %s "
447 "(precision %d);\nSun audio header not written", 438 "(precision %d);\nSun audio header not written",
448 s, precision); 439 s, precision);
449 } 440 }
450 format = AUDIO_FORMAT_NONE; 441 format = AUDIO_FORMAT_NONE;
451 conv_func = 0; 442 conv_func = 0;
452 warned = 1; 443 warned = 1;
453 return -1; 444 return -1;
454 } 445 }
455 446
456 auh.magic = htonl(AUDIO_FILE_MAGIC); 447 auh.magic = htonl(AUDIO_FILE_MAGIC);
457 if (outfd == STDOUT_FILENO) 448 if (outfd == STDOUT_FILENO)
458 auh.data_size = htonl(AUDIO_UNKNOWN_SIZE); 449 auh.data_size = htonl(AUDIO_UNKNOWN_SIZE);
459 else if (total_size != -1) 450 else if (total_size != -1)
460 auh.data_size = htonl(total_size); 451 auh.data_size = htonl(total_size);
461 else 452 else
462 auh.data_size = 0; 453 auh.data_size = 0;
463 auh.encoding = htonl(sunenc); 454 auh.encoding = htonl(sunenc);
464 auh.sample_rate = htonl(sample_rate); 455 auh.sample_rate = htonl(sample_rate);
465 auh.channels = htonl(channels); 456 auh.channels = htonl(channels);
466 if (header_info) { 457 if (header_info) {
467 int len, infolen; 458 int len, infolen;
468 459
469 infolen = ((len = strlen(header_info)) + 7) & 0xfffffff8; 460 infolen = ((len = strlen(header_info)) + 7) & 0xfffffff8;
470 *leftp = infolen - len; 461 *leftp = infolen - len;
471 auh.hdr_size = htonl(sizeof(auh) + infolen); 462 auh.hdr_size = htonl(sizeof(auh) + infolen);
472 } else { 463 } else {
473 *leftp = sizeof(default_info); 464 *leftp = sizeof(default_info);
474 auh.hdr_size = htonl(sizeof(auh) + *leftp); 465 auh.hdr_size = htonl(sizeof(auh) + *leftp);
475 } 466 }
476 *(sun_audioheader **)hdrp = &auh; 467 *(sun_audioheader **)hdrp = &auh;
477 *lenp = sizeof auh; 468 *lenp = sizeof auh;
478 return 0; 469 return 0;
479} 470}
480 471
481int 472static int
482write_header_wav(hdrp, lenp, leftp) 473write_header_wav(void **hdrp, size_t *lenp, int *leftp)
483 void **hdrp; 
484 size_t *lenp; 
485 int *leftp; 
486{ 474{
487 /* 475 /*
488 * WAV header we write looks like this: 476 * WAV header we write looks like this:
489 * 477 *
490 * bytes purpose 478 * bytes purpose
491 * 0-3 "RIFF" 479 * 0-3 "RIFF"
492 * 4-7 file length (minus 8) 480 * 4-7 file length (minus 8)
493 * 8-15 "WAVEfmt " 481 * 8-15 "WAVEfmt "
494 * 16-19 format size 482 * 16-19 format size
495 * 20-21 format tag 483 * 20-21 format tag
496 * 22-23 number of channels 484 * 22-23 number of channels
497 * 24-27 sample rate 485 * 24-27 sample rate
498 * 28-31 average bytes per second 486 * 28-31 average bytes per second
499 * 32-33 block alignment 487 * 32-33 block alignment
500 * 34-35 bits per sample 488 * 34-35 bits per sample
501 * 489 *
502 * then for ULAW and ALAW outputs, we have an extended chunk size 490 * then for ULAW and ALAW outputs, we have an extended chunk size
503 * and a WAV "fact" to add: 491 * and a WAV "fact" to add:
504 * 492 *
505 * 36-37 length of extension (== 0) 493 * 36-37 length of extension (== 0)
506 * 38-41 "fact" 494 * 38-41 "fact"
507 * 42-45 fact size 495 * 42-45 fact size
508 * 46-49 number of samples written 496 * 46-49 number of samples written
509 * 50-53 "data" 497 * 50-53 "data"
510 * 54-57 data length 498 * 54-57 data length
511 * 58- raw audio data 499 * 58- raw audio data
512 * 500 *
513 * for PCM outputs we have just the data remaining: 501 * for PCM outputs we have just the data remaining:
514 * 502 *
515 * 36-39 "data" 503 * 36-39 "data"
516 * 40-43 data length 504 * 40-43 data length
517 * 44- raw audio data 505 * 44- raw audio data
518 * 506 *
519 * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@ 507 * RIFF\^@^C^@WAVEfmt ^P^@^@^@^A^@^B^@D<AC>^@^@^P<B1>^B^@^D^@^P^@data^@^@^C^@^@^@^@^@^@^@^@^@^@
520 */ 508 */
521 char wavheaderbuf[64], *p = wavheaderbuf; 509 char wavheaderbuf[64], *p = wavheaderbuf;
522 const char *riff = "RIFF", 510 const char *riff = "RIFF",
523 *wavefmt = "WAVEfmt ", 511 *wavefmt = "WAVEfmt ",
524 *fact = "fact", 512 *fact = "fact",
525 *data = "data"; 513 *data = "data";
526 u_int32_t filelen, fmtsz, sps, abps, factsz = 4, nsample, datalen; 514 u_int32_t filelen, fmtsz, sps, abps, factsz = 4, nsample, datalen;
527 u_int16_t fmttag, nchan, align, bps, extln = 0; 515 u_int16_t fmttag, nchan, align, bps, extln = 0;
528 516
529 if (header_info) 517 if (header_info)
530 warnx("header information not supported for WAV"); 518 warnx("header information not supported for WAV");
531 *leftp = 0; 519 *leftp = 0;
532 520
533 switch (precision) { 521 switch (precision) {
534 case 8: 522 case 8:
535 bps = 8; 523 bps = 8;
536 break; 524 break;
537 case 16: 525 case 16:
538 bps = 16; 526 bps = 16;
539 break; 527 break;
540 case 32: 528 case 32:
541 bps = 32; 529 bps = 32;
542 break; 530 break;
543 default: 531 default:
544 { 532 {
545 static int warned = 0; 533 static int warned = 0;
546 534
547 if (warned == 0) { 535 if (warned == 0) {
548 warnx("can not support precision of %d", precision); 536 warnx("can not support precision of %d", precision);
549 warned = 1; 537 warned = 1;
550 } 538 }
551 } 539 }
552 return (-1); 540 return (-1);
553 } 541 }
554 542
555 switch (encoding) { 543 switch (encoding) {
556 case AUDIO_ENCODING_ULAW: 544 case AUDIO_ENCODING_ULAW:
557 fmttag = WAVE_FORMAT_MULAW; 545 fmttag = WAVE_FORMAT_MULAW;
558 fmtsz = 18; 546 fmtsz = 18;
559 align = channels; 547 align = channels;
560 break; 548 break;
561 549
562 case AUDIO_ENCODING_ALAW: 550 case AUDIO_ENCODING_ALAW:
563 fmttag = WAVE_FORMAT_ALAW; 551 fmttag = WAVE_FORMAT_ALAW;
564 fmtsz = 18; 552 fmtsz = 18;
565 align = channels; 553 align = channels;
566 break; 554 break;
567 555
568 /* 556 /*
569 * we could try to support RIFX but it seems to be more portable 557 * we could try to support RIFX but it seems to be more portable
570 * to output little-endian data for WAV files. 558 * to output little-endian data for WAV files.
571 */ 559 */
572 case AUDIO_ENCODING_ULINEAR_BE: 560 case AUDIO_ENCODING_ULINEAR_BE:
573#if BYTE_ORDER == BIG_ENDIAN 561#if BYTE_ORDER == BIG_ENDIAN
574 case AUDIO_ENCODING_ULINEAR: 562 case AUDIO_ENCODING_ULINEAR:
575#endif 563#endif
576 if (bps == 16) 564 if (bps == 16)
577 conv_func = change_sign16_swap_bytes_be; 565 conv_func = change_sign16_swap_bytes_be;
578 else if (bps == 32) 566 else if (bps == 32)
579 conv_func = change_sign32_swap_bytes_be; 567 conv_func = change_sign32_swap_bytes_be;
580 goto fmt_pcm; 568 goto fmt_pcm;
581 569
582 case AUDIO_ENCODING_SLINEAR_BE: 570 case AUDIO_ENCODING_SLINEAR_BE:
583#if BYTE_ORDER == BIG_ENDIAN 571#if BYTE_ORDER == BIG_ENDIAN
584 case AUDIO_ENCODING_SLINEAR: 572 case AUDIO_ENCODING_SLINEAR:
585#endif 573#endif
586 if (bps == 8) 574 if (bps == 8)
587 conv_func = change_sign8; 575 conv_func = change_sign8;
588 else if (bps == 16) 576 else if (bps == 16)
589 conv_func = swap_bytes; 577 conv_func = swap_bytes;
590 else if (bps == 32) 578 else if (bps == 32)
591 conv_func = swap_bytes32; 579 conv_func = swap_bytes32;
592 goto fmt_pcm; 580 goto fmt_pcm;
593 581
594 case AUDIO_ENCODING_ULINEAR_LE: 582 case AUDIO_ENCODING_ULINEAR_LE:
595#if BYTE_ORDER == LITTLE_ENDIAN 583#if BYTE_ORDER == LITTLE_ENDIAN
596 case AUDIO_ENCODING_ULINEAR: 584 case AUDIO_ENCODING_ULINEAR:
597#endif 585#endif
598 if (bps == 16) 586 if (bps == 16)
599 conv_func = change_sign16_le; 587 conv_func = change_sign16_le;
600 else if (bps == 32) 588 else if (bps == 32)
601 conv_func = change_sign32_le; 589 conv_func = change_sign32_le;
602 /* FALLTHROUGH */ 590 /* FALLTHROUGH */
603 591
604 case AUDIO_ENCODING_SLINEAR_LE: 592 case AUDIO_ENCODING_SLINEAR_LE:
605 case AUDIO_ENCODING_PCM16: 593 case AUDIO_ENCODING_PCM16:
606#if BYTE_ORDER == LITTLE_ENDIAN 594#if BYTE_ORDER == LITTLE_ENDIAN
607 case AUDIO_ENCODING_SLINEAR: 595 case AUDIO_ENCODING_SLINEAR:
608#endif 596#endif
609 if (bps == 8) 597 if (bps == 8)
610 conv_func = change_sign8; 598 conv_func = change_sign8;
611fmt_pcm: 599fmt_pcm:
612 fmttag = WAVE_FORMAT_PCM; 600 fmttag = WAVE_FORMAT_PCM;
613 fmtsz = 16; 601 fmtsz = 16;
614 align = channels * (bps / 8); 602 align = channels * (bps / 8);
615 break; 603 break;
616 604
617 default: 605 default:
618 { 606 {
619 static int warned = 0; 607 static int warned = 0;
620 608
621 if (warned == 0) { 609 if (warned == 0) {
622 const char *s = wav_enc_from_val(encoding); 610 const char *s = wav_enc_from_val(encoding);
623 611
624 if (s == NULL) 612 if (s == NULL)
625 warnx("can not support encoding of %s", s); 613 warnx("can not support encoding of %s", s);
626 else 614 else
627 warnx("can not support encoding of %d", encoding); 615 warnx("can not support encoding of %d", encoding);
628 warned = 1; 616 warned = 1;
629 } 617 }
630 } 618 }
631 format = AUDIO_FORMAT_NONE; 619 format = AUDIO_FORMAT_NONE;
632 return (-1); 620 return (-1);
633 } 621 }
634 622
635 nchan = channels; 623 nchan = channels;
636 sps = sample_rate; 624 sps = sample_rate;
637 625
638 /* data length */ 626 /* data length */
639 if (outfd == STDOUT_FILENO) 627 if (outfd == STDOUT_FILENO)
640 datalen = 0; 628 datalen = 0;
641 else if (total_size != -1) 629 else if (total_size != -1)
642 datalen = total_size; 630 datalen = total_size;
643 else 631 else
644 datalen = 0; 632 datalen = 0;
645 633
646 /* file length */ 634 /* file length */
647 filelen = 4 + (8 + fmtsz) + (8 + datalen); 635 filelen = 4 + (8 + fmtsz) + (8 + datalen);
648 if (fmttag != WAVE_FORMAT_PCM) 636 if (fmttag != WAVE_FORMAT_PCM)
649 filelen += 8 + factsz; 637 filelen += 8 + factsz;
650 638
651 abps = (double)align*sample_rate / (double)1 + 0.5; 639 abps = (double)align*sample_rate / (double)1 + 0.5;
652 640
653 nsample = (datalen / bps) / sample_rate; 641 nsample = (datalen / bps) / sample_rate;
654  642
655 /* 643 /*
656 * now we've calculated the info, write it out! 644 * now we've calculated the info, write it out!
657 */ 645 */
658#define put32(x) do { \ 646#define put32(x) do { \
659 u_int32_t _f; \ 647 u_int32_t _f; \
660 putle32(_f, (x)); \ 648 putle32(_f, (x)); \
661 memcpy(p, &_f, 4); \ 649 memcpy(p, &_f, 4); \
662} while (0) 650} while (0)
663#define put16(x) do { \ 651#define put16(x) do { \
664 u_int16_t _f; \ 652 u_int16_t _f; \
665 putle16(_f, (x)); \ 653 putle16(_f, (x)); \
666 memcpy(p, &_f, 2); \ 654 memcpy(p, &_f, 2); \
667} while (0) 655} while (0)
668 memcpy(p, riff, 4); 656 memcpy(p, riff, 4);
669 p += 4; /* 4 */ 657 p += 4; /* 4 */
670 put32(filelen); 658 put32(filelen);
671 p += 4; /* 8 */ 659 p += 4; /* 8 */
672 memcpy(p, wavefmt, 8); 660 memcpy(p, wavefmt, 8);
673 p += 8; /* 16 */ 661 p += 8; /* 16 */
674 put32(fmtsz); 662 put32(fmtsz);
675 p += 4; /* 20 */ 663 p += 4; /* 20 */
676 put16(fmttag); 664 put16(fmttag);
677 p += 2; /* 22 */ 665 p += 2; /* 22 */
678 put16(nchan); 666 put16(nchan);
679 p += 2; /* 24 */ 667 p += 2; /* 24 */
680 put32(sps); 668 put32(sps);
681 p += 4; /* 28 */ 669 p += 4; /* 28 */
682 put32(abps); 670 put32(abps);
683 p += 4; /* 32 */ 671 p += 4; /* 32 */
684 put16(align); 672 put16(align);
685 p += 2; /* 34 */ 673 p += 2; /* 34 */
686 put16(bps); 674 put16(bps);
687 p += 2; /* 36 */ 675 p += 2; /* 36 */
688 /* NON PCM formats have an extended chunk; write it */ 676 /* NON PCM formats have an extended chunk; write it */
689 if (fmttag != WAVE_FORMAT_PCM) { 677 if (fmttag != WAVE_FORMAT_PCM) {
690 put16(extln); 678 put16(extln);
691 p += 2; /* 38 */ 679 p += 2; /* 38 */
692 memcpy(p, fact, 4); 680 memcpy(p, fact, 4);
693 p += 4; /* 42 */ 681 p += 4; /* 42 */
694 put32(factsz); 682 put32(factsz);
695 p += 4; /* 46 */ 683 p += 4; /* 46 */
696 put32(nsample); 684 put32(nsample);
697 p += 4; /* 50 */ 685 p += 4; /* 50 */
698 } 686 }
699 memcpy(p, data, 4); 687 memcpy(p, data, 4);
700 p += 4; /* 40/54 */ 688 p += 4; /* 40/54 */
701 put32(datalen); 689 put32(datalen);
702 p += 4; /* 44/58 */ 690 p += 4; /* 44/58 */
703#undef put32 691#undef put32
704#undef put16 692#undef put16
705 693
706 *hdrp = wavheaderbuf; 694 *hdrp = wavheaderbuf;
707 *lenp = (p - wavheaderbuf); 695 *lenp = (p - wavheaderbuf);
708 696
709 return 0; 697 return 0;
710} 698}
711 699
712void 700static void
713write_header() 701write_header(void)
714{ 702{
715 struct iovec iv[3]; 703 struct iovec iv[3];
716 int veclen, left, tlen; 704 int veclen, left, tlen;
717 void *hdr; 705 void *hdr;
718 size_t hdrlen; 706 size_t hdrlen;
719 707
720 switch (format) { 708 switch (format) {
721 case AUDIO_FORMAT_DEFAULT: 709 case AUDIO_FORMAT_DEFAULT:
722 case AUDIO_FORMAT_SUN: 710 case AUDIO_FORMAT_SUN:
723 if (write_header_sun(&hdr, &hdrlen, &left) != 0) 711 if (write_header_sun(&hdr, &hdrlen, &left) != 0)
724 return; 712 return;
725 break; 713 break;
726 case AUDIO_FORMAT_WAV: 714 case AUDIO_FORMAT_WAV:
727 if (write_header_wav(&hdr, &hdrlen, &left) != 0) 715 if (write_header_wav(&hdr, &hdrlen, &left) != 0)
728 return; 716 return;
729 break; 717 break;
730 case AUDIO_FORMAT_NONE: 718 case AUDIO_FORMAT_NONE:
731 return; 719 return;
732 default: 720 default:
733 errx(1, "unknown audio format"); 721 errx(1, "unknown audio format");
734 } 722 }
735 723
736 veclen = 0; 724 veclen = 0;
737 tlen = 0; 725 tlen = 0;
738  726
739 if (hdrlen != 0) { 727 if (hdrlen != 0) {
740 iv[veclen].iov_base = hdr; 728 iv[veclen].iov_base = hdr;
741 iv[veclen].iov_len = hdrlen; 729 iv[veclen].iov_len = hdrlen;
742 tlen += iv[veclen++].iov_len; 730 tlen += iv[veclen++].iov_len;
743 } 731 }
744 if (header_info) { 732 if (header_info) {
745 iv[veclen].iov_base = header_info; 733 iv[veclen].iov_base = header_info;
746 iv[veclen].iov_len = (int)strlen(header_info) + 1; 734 iv[veclen].iov_len = (int)strlen(header_info) + 1;
747 tlen += iv[veclen++].iov_len; 735 tlen += iv[veclen++].iov_len;
748 } 736 }
749 if (left) { 737 if (left) {
750 iv[veclen].iov_base = default_info; 738 iv[veclen].iov_base = default_info;
751 iv[veclen].iov_len = left; 739 iv[veclen].iov_len = left;
752 tlen += iv[veclen++].iov_len; 740 tlen += iv[veclen++].iov_len;
753 } 741 }
754 742
755 if (tlen == 0) 743 if (tlen == 0)
756 return; 744 return;
757 745
758 if (writev(outfd, iv, veclen) != tlen) 746 if (writev(outfd, iv, veclen) != tlen)
759 err(1, "could not write audio header"); 747 err(1, "could not write audio header");
760} 748}
761 749
762void 750static void
763rewrite_header() 751rewrite_header(void)
764{ 752{
765 753
766 /* can't do this here! */ 754 /* can't do this here! */
767 if (outfd == STDOUT_FILENO) 755 if (outfd == STDOUT_FILENO)
768 return; 756 return;
769 757
770 if (lseek(outfd, SEEK_SET, 0) < 0) 758 if (lseek(outfd, SEEK_SET, 0) < 0)
771 err(1, "could not seek to start of file for header rewrite"); 759 err(1, "could not seek to start of file for header rewrite");
772 write_header(); 760 write_header();
773} 761}
774 762
775void 763static void
776usage() 764usage(void)
777{ 765{
778 766
779 fprintf(stderr, "Usage: %s [-afhqV] [options] {files ...|-}\n", 767 fprintf(stderr, "Usage: %s [-afhqV] [options] {files ...|-}\n",
780 getprogname()); 768 getprogname());
781 fprintf(stderr, "Options:\n\t" 769 fprintf(stderr, "Options:\n\t"
782 "-B buffer size\n\t" 770 "-B buffer size\n\t"
783 "-b balance (0-63)\n\t" 771 "-b balance (0-63)\n\t"
784 "-c channels\n\t" 772 "-c channels\n\t"
785 "-d audio device\n\t" 773 "-d audio device\n\t"
786 "-e encoding\n\t" 774 "-e encoding\n\t"
787 "-F format\n\t" 775 "-F format\n\t"
788 "-i header information\n\t" 776 "-i header information\n\t"
789 "-m monitor volume\n\t" 777 "-m monitor volume\n\t"
790 "-P precision (4, 8, 16, 24, or 32 bits)\n\t" 778 "-P precision (4, 8, 16, 24, or 32 bits)\n\t"
791 "-p input port\n\t" 779 "-p input port\n\t"
792 "-s sample rate\n\t" 780 "-s sample rate\n\t"
793 "-t recording time\n\t" 781 "-t recording time\n\t"
794 "-v volume\n"); 782 "-v volume\n");
795 exit(EXIT_FAILURE); 783 exit(EXIT_FAILURE);
796} 784}