Annotation of src/usr.bin/aucat/legacy.c, Revision 1.11
1.11 ! jakemsr 1: /* $OpenBSD: legacy.c,v 1.10 2010/04/03 17:59:17 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 1997 Kenneth Stailey. All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by Kenneth Stailey.
16: * 4. The name of the author may not be used to endorse or promote products
17: * derived from this software without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
1.5 jakemsr 31: #include <sndio.h>
1.2 ratchov 32:
1.7 ratchov 33: #include <err.h>
34: #include <fcntl.h>
1.4 ratchov 35: #include <stdlib.h>
1.2 ratchov 36: #include <string.h>
1.1 ratchov 37: #include <unistd.h>
38:
1.3 ratchov 39: #include "wav.h"
1.1 ratchov 40:
1.7 ratchov 41: /*
42: * Headerless data files. Played at /dev/audio's defaults.
1.1 ratchov 43: */
44: #define FMT_RAW 0
45:
1.7 ratchov 46: /*
47: * Sun/NeXT .au files. Header is skipped and /dev/audio is configured
1.1 ratchov 48: * for monaural 8-bit ulaw @ 8kHz, the de facto format for .au files,
49: * as well as the historical default configuration for /dev/audio.
50: */
51: #define FMT_AU 1
52:
1.7 ratchov 53: /*
54: * RIFF WAV files. Header is parsed for format details which are
1.1 ratchov 55: * applied to /dev/audio.
56: */
57: #define FMT_WAV 2
58:
1.3 ratchov 59:
1.1 ratchov 60: int
61: legacy_play(char *dev, char *aufile)
62: {
1.5 jakemsr 63: struct sio_hdl *hdl;
64: struct sio_par spar, par;
65: struct aparams apar;
1.1 ratchov 66: ssize_t rd;
1.10 ratchov 67: off_t datasz;
1.1 ratchov 68: char buf[5120];
1.5 jakemsr 69: size_t readsz;
70: int fd, fmt = FMT_RAW;
71: u_int32_t pos = 0, snd_fmt = 1, rate = 8000, chan = 1;
1.1 ratchov 72: char magic[4];
1.6 ratchov 73: short *map;
1.1 ratchov 74:
75: if ((fd = open(aufile, O_RDONLY)) < 0) {
76: warn("cannot open %s", aufile);
77: return(1);
78: }
79:
80: if (read(fd, magic, sizeof(magic)) != sizeof(magic)) {
1.7 ratchov 81: /*
82: * read() error, or the file is smaller than sizeof(magic).
1.1 ratchov 83: * treat as a raw file, like previous versions of aucat.
84: */
85: } else if (!strncmp(magic, ".snd", 4)) {
86: fmt = FMT_AU;
87: if (read(fd, &pos, sizeof(pos)) == sizeof(pos))
88: pos = ntohl(pos);
1.5 jakemsr 89: /* data size */
90: if (lseek(fd, 4, SEEK_CUR) == -1)
91: warn("lseek hdr");
92: if (read(fd, &snd_fmt, sizeof(snd_fmt)) == sizeof(snd_fmt))
93: snd_fmt = ntohl(snd_fmt);
94: if (read(fd, &rate, sizeof(rate)) == sizeof(rate))
95: rate = ntohl(rate);
96: if (read(fd, &chan, sizeof(chan)) == sizeof(chan))
97: chan = ntohl(chan);
1.1 ratchov 98: } else if (!strncmp(magic, "RIFF", 4) &&
1.10 ratchov 99: wav_readhdr(fd, &apar, &datasz, &map)) {
1.1 ratchov 100: fmt = FMT_WAV;
101: }
102:
1.7 ratchov 103: /*
104: * Seek to start of audio data. wav_readhdr already took care
1.1 ratchov 105: * of this for FMT_WAV.
106: */
107: if (fmt == FMT_RAW || fmt == FMT_AU)
108: if (lseek(fd, (off_t)pos, SEEK_SET) == -1)
109: warn("lseek");
1.5 jakemsr 110:
1.8 ratchov 111: if ((hdl = sio_open(dev, SIO_PLAY, 0)) == NULL) {
1.5 jakemsr 112: warnx("can't get sndio handle");
1.1 ratchov 113: return(1);
114: }
115:
1.5 jakemsr 116: sio_initpar(&par);
1.1 ratchov 117: switch(fmt) {
118: case FMT_WAV:
1.5 jakemsr 119: par.rate = apar.rate;
120: par.pchan = apar.cmax - apar.cmin + 1;
121: par.sig = apar.sig;
122: par.bits = apar.bits;
123: par.le = apar.le;
1.1 ratchov 124: break;
125: case FMT_AU:
1.5 jakemsr 126: par.rate = rate;
127: par.pchan = chan;
128: par.sig = 1;
129: par.bits = 16;
1.11 ! jakemsr 130: par.le = SIO_LE_NATIVE;
1.6 ratchov 131: map = wav_ulawmap;
1.5 jakemsr 132: if (snd_fmt == 27)
1.6 ratchov 133: map = wav_alawmap;
1.1 ratchov 134: break;
135: case FMT_RAW:
136: default:
137: break;
138: }
1.5 jakemsr 139: spar = par;
1.1 ratchov 140:
1.5 jakemsr 141: if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
142: warnx("can't set audio parameters");
1.7 ratchov 143: /*
144: * Only WAV could fail in previous aucat versions (unless
1.1 ratchov 145: * the parameters returned by AUDIO_GETINFO would fail,
1.7 ratchov 146: * which is unlikely).
1.1 ratchov 147: */
148: if (fmt == FMT_WAV)
149: return(1);
150: }
151:
1.7 ratchov 152: /*
153: * Parameters may be silently modified. See audio(9)'s
154: * description of set_params. For compatability with previous
1.1 ratchov 155: * aucat versions, continue running if something doesn't match.
156: */
1.5 jakemsr 157: if (par.bits != spar.bits ||
158: par.sig != par.sig ||
159: par.le != spar.le ||
160: par.pchan != spar.pchan ||
1.7 ratchov 161: /*
162: * Devices may return a very close rate, such as 44099 when
163: * 44100 was requested. The difference is inaudible. Allow
1.1 ratchov 164: * 2% deviation as an example of how to cope.
165: */
1.5 jakemsr 166: (par.rate > spar.rate * 1.02 || par.rate < spar.rate * 0.98)) {
167: warnx("format not supported");
168: }
169: if (!sio_start(hdl)) {
170: warnx("could not start sndio");
171: exit(1);
1.1 ratchov 172: }
173:
1.5 jakemsr 174: readsz = sizeof(buf);
1.6 ratchov 175: if (map)
1.5 jakemsr 176: readsz /= 2;
177: while ((rd = read(fd, buf, readsz)) > 0) {
1.6 ratchov 178: if (map) {
179: wav_conv(buf, rd, map);
1.5 jakemsr 180: rd *= 2;
181: }
182: if (sio_write(hdl, buf, rd) != rd)
183: warnx("sio_write: short write");
184: }
1.1 ratchov 185: if (rd == -1)
186: warn("read");
187:
1.5 jakemsr 188: sio_close(hdl);
1.7 ratchov 189: close(fd);
1.1 ratchov 190:
191: return(0);
192: }