ANSIfy. Add static. Add __dead.diff -r1.19 -r1.20 src/usr.bin/audio/common/audio.c
(joerg)
--- 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 | |||
54 | struct { | 54 | static 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 | |||
69 | int | 69 | int | |
70 | audio_format_from_str(str) | 70 | audio_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 */ | |
84 | struct { | 83 | static 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 | |||
112 | const char * | 111 | const char * | |
113 | audio_enc_from_val(val) | 112 | audio_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 | |||
124 | int | 122 | int | |
125 | audio_enc_to_val(enc) | 123 | audio_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 | |||
139 | void | 136 | void | |
140 | decode_int(arg, intp) | 137 | decode_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 | |||
156 | void | 151 | void | |
157 | decode_time(arg, tvp) | 152 | decode_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 | */ | |
208 | void | 201 | void | |
209 | decode_encoding(arg, encp) | 202 | decode_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 | |||
225 | const char *const audio_errlist[] = { | 216 | static 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 | |||
235 | const char * | 226 | const char * | |
236 | audio_errstring(errval) | 227 | audio_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 | } |
--- 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 | |||
37 | int audio_format_from_str (char *); | 37 | int 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 | |||
63 | typedef struct { | 63 | typedef 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 | |||
91 | const char *audio_enc_from_val (int); | 91 | const char *audio_enc_from_val (int); | |
92 | int audio_enc_to_val (const char *); | 92 | int audio_enc_to_val (const char *); | |
93 | 93 | |||
94 | int audio_sun_to_encoding (int, u_int *, u_int *); | 94 | int audio_sun_to_encoding (int, u_int *, u_int *); | |
95 | int audio_encoding_to_sun (int, int, int *); | 95 | int 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 | |||
135 | const char *wav_enc_from_val (int); | 135 | const char *wav_enc_from_val (int); | |
136 | 136 | |||
137 | typedef struct { | 137 | typedef 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 | |||
142 | typedef struct { | 142 | typedef 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 | |||
151 | typedef struct { | 151 | typedef 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 */ | |
160 | ssize_t audio_wav_parse_hdr (void *, size_t, u_int *, u_int *, u_int *, u_int *, size_t *); | 160 | ssize_t audio_wav_parse_hdr (void *, size_t, u_int *, u_int *, u_int *, u_int *, size_t *); | |
161 | 161 | |||
162 | extern 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 */ | |
175 | const char *audio_errstring (int); | 177 | const char *audio_errstring (int); | |
176 | 178 | |||
177 | /* | 179 | /* | |
178 | * generic routines? | 180 | * generic routines? | |
179 | */ | 181 | */ | |
180 | void decode_int (const char *, int *); | 182 | void decode_int (const char *, int *); | |
181 | void decode_time (const char *, struct timeval *); | 183 | void decode_time (const char *, struct timeval *); | |
182 | void decode_encoding (const char *, int *); | 184 | void 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 |
--- 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 | */ | |
55 | struct { | 55 | static 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 | |||
82 | int | 82 | int | |
83 | audio_sun_to_encoding(sun_encoding, encp, precp) | 83 | audio_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 | |||
99 | int | 96 | int | |
100 | audio_encoding_to_sun(encoding, precision, sunep) | 97 | audio_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 | } |
--- 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 | |||
54 | struct { | 54 | static 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 | |||
69 | const char * | 69 | const char * | |
70 | wav_enc_from_val(int encoding) | 70 | wav_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 | |||
80 | extern 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 | */ | |
94 | ssize_t | 92 | ssize_t | |
95 | audio_wav_parse_hdr(hdr, sz, enc, prec, sample, channels, datasize) | 93 | audio_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 | } |
--- 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 | |||
54 | struct field *findfield (const char *name); | 54 | static struct field *findfield(const char *name); | |
55 | void prfield (struct field *p, const char *sep); | 55 | static void prfield(const struct field *p, const char *sep); | |
56 | void rdfield (struct field *p, char *q); | 56 | static void rdfield(struct field *p, char *q); | |
57 | void getinfo (int fd); | 57 | static void getinfo(int fd); | |
58 | void audioctl_write (int, int, char *[]); | 58 | static void audioctl_write(int, int, char *[]); | |
59 | void usage (void); | 59 | __dead static void usage(void); | |
60 | int main (int argc, char **argv); | |||
61 | 60 | |||
62 | audio_device_t adev; | 61 | static audio_device_t adev; | |
63 | 62 | |||
64 | audio_info_t info; | 63 | static audio_info_t info; | |
65 | 64 | |||
66 | char encbuf[1000]; | 65 | static char encbuf[1000]; | |
67 | 66 | |||
68 | int properties, fullduplex, rerror; | 67 | static int properties, fullduplex, rerror; | |
69 | 68 | |||
70 | struct field { | 69 | static 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 | |||
143 | static struct { | 142 | static 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 | |||
153 | struct field * | 152 | static struct field * | |
154 | findfield(name) | 153 | findfield(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 | |||
164 | void | 162 | static void | |
165 | prfield(p, sep) | 163 | prfield(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 | |||
238 | void | 234 | static void | |
239 | rdfield(p, q) | 235 | rdfield(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 | |||
292 | void | 286 | static void | |
293 | getinfo(fd) | 287 | getinfo(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 | |||
325 | void | 318 | static void | |
326 | usage() | 319 | usage(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 | |||
336 | int | 329 | int | |
337 | main(argc, argv) | 330 | main(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 | |||
431 | void | 422 | static void | |
432 | audioctl_write(fd, argc, argv) | 423 | audioctl_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 | } |
--- 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 | |||
54 | int main(int, char *[]); | 54 | static void usage(void) __dead; | |
55 | void usage(void); | 55 | static void play(char *); | |
56 | void play(char *); | 56 | static void play_fd(const char *, int); | |
57 | void play_fd(const char *, int); | 57 | static ssize_t audioctl_write_fromhdr(void *, size_t, int, size_t *, const char *); | |
58 | ssize_t audioctl_write_fromhdr(void *, size_t, int, size_t *, const char *); | 58 | static void cleanup(int) __dead; | |
59 | void cleanup(int) __dead; | 59 | ||
60 | 60 | static audio_info_t info; | ||
61 | audio_info_t info; | 61 | static int volume; | |
62 | int volume; | 62 | static int balance; | |
63 | int balance; | 63 | static int port; | |
64 | int port; | 64 | static int fflag; | |
65 | int fflag; | 65 | static int qflag; | |
66 | int qflag; | |||
67 | int verbose; | 66 | int verbose; | |
68 | int sample_rate; | 67 | static int sample_rate; | |
69 | int encoding; | 68 | static int encoding; | |
70 | char *encoding_str; | 69 | static char *encoding_str; | |
71 | int precision; | 70 | static int precision; | |
72 | int channels; | 71 | static int channels; | |
73 | 72 | |||
74 | char const *play_errstring = NULL; | 73 | static char const *play_errstring = NULL; | |
75 | size_t bufsize; | 74 | static size_t bufsize; | |
76 | int audiofd; | 75 | static int audiofd; | |
77 | int exitstatus = EXIT_SUCCESS; | 76 | static int exitstatus = EXIT_SUCCESS; | |
78 | 77 | |||
79 | int | 78 | int | |
80 | main(argc, argv) | 79 | main(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 | |||
207 | void | 204 | static void | |
208 | cleanup(signo) | 205 | cleanup(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 | |||
221 | void | 217 | static void | |
222 | play(file) | 218 | play(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 | */ | |
310 | void | 305 | static void | |
311 | play_fd(file, fd) | 306 | play_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; | |
364 | read_error: | 357 | read_error: | |
365 | err(1, "read of standard input failed"); | 358 | err(1, "read of standard input failed"); | |
366 | write_error: | 359 | write_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 | */ | |
376 | ssize_t | 369 | static ssize_t | |
377 | audioctl_write_fromhdr(hdr, fsz, fd, datasize, file) | 370 | audioctl_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); | |
431 | set_audio_mode: | 419 | set_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 | |||
471 | void | 459 | static void | |
472 | usage() | 460 | usage(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 | } |
--- 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 | |||
58 | audio_info_t info, oinfo; | 58 | static audio_info_t info, oinfo; | |
59 | ssize_t total_size = -1; | 59 | static ssize_t total_size = -1; | |
60 | const char *device; | 60 | static const char *device; | |
61 | int format = AUDIO_FORMAT_DEFAULT; | 61 | static int format = AUDIO_FORMAT_DEFAULT; | |
62 | char *header_info; | 62 | static char *header_info; | |
63 | char default_info[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; | 63 | static char default_info[8] = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; | |
64 | int audiofd, outfd; | 64 | static int audiofd, outfd; | |
65 | int qflag, aflag, fflag; | 65 | static int qflag, aflag, fflag; | |
66 | int verbose; | 66 | int verbose; | |
67 | int monitor_gain, omonitor_gain; | 67 | static int monitor_gain, omonitor_gain; | |
68 | int gain; | 68 | static int gain; | |
69 | int balance; | 69 | static int balance; | |
70 | int port; | 70 | static int port; | |
71 | int encoding; | 71 | static int encoding; | |
72 | char *encoding_str; | 72 | static char *encoding_str; | |
73 | int precision; | 73 | static int precision; | |
74 | int sample_rate; | 74 | static int sample_rate; | |
75 | int channels; | 75 | static int channels; | |
76 | struct timeval record_time; | 76 | static struct timeval record_time; | |
77 | struct timeval start_time; | 77 | static struct timeval start_time; | |
78 | 78 | |||
79 | void (*conv_func) (u_char *, int); | 79 | static void (*conv_func) (u_char *, int); | |
80 | 80 | |||
81 | void usage (void); | 81 | static void usage (void) __dead; | |
82 | int main (int, char *[]); | 82 | static int timeleft (struct timeval *, struct timeval *); | |
83 | int timeleft (struct timeval *, struct timeval *); | 83 | static void cleanup (int) __dead; | |
84 | void cleanup (int) __dead; | 84 | static int write_header_sun (void **, size_t *, int *); | |
85 | int write_header_sun (void **, size_t *, int *); | 85 | static int write_header_wav (void **, size_t *, int *); | |
86 | int write_header_wav (void **, size_t *, int *); | 86 | static void write_header (void); | |
87 | void write_header (void); | 87 | static void rewrite_header (void); | |
88 | void rewrite_header (void); | |||
89 | 88 | |||
90 | int | 89 | int | |
91 | main(argc, argv) | 90 | main(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 | |||
350 | int | 347 | int | |
351 | timeleft(start_tvp, record_tvp) | 348 | timeleft(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 | |||
364 | void | 359 | void | |
365 | cleanup(signo) | 360 | cleanup(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 | |||
384 | int | 378 | static int | |
385 | write_header_sun(hdrp, lenp, leftp) | 379 | write_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 | |||
481 | int | 472 | static int | |
482 | write_header_wav(hdrp, lenp, leftp) | 473 | write_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; | |
611 | fmt_pcm: | 599 | fmt_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 | |||
712 | void | 700 | static void | |
713 | write_header() | 701 | write_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 | |||
762 | void | 750 | static void | |
763 | rewrite_header() | 751 | rewrite_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 | |||
775 | void | 763 | static void | |
776 | usage() | 764 | usage(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 | } |