diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2001-08-18 19:33:31 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2001-08-18 19:33:31 +0000 |
commit | b728c67f4a10e177d3abd254bc75e4faf89b6de9 (patch) | |
tree | a721d3706d295016f4b217d5f1a9f998a7bc86fe /lib | |
parent | 6b0d83b161631a1d2b11af80ce91dad16accf085 (diff) |
sync up libossaudio with NetBSD changes.
--
- Add __BEGIN_DECLS & __END_DECLS for C++
- Make protection against multiple inclusion non-invasive wrt. name space
- Use EAGAIN instead of EWOULDBLOCK. The actual numeric value is
same, but EAGAIN is the posixly correct name
- Remove white space
- Change the behaviour to report emulated encodings, too
- Implement SOUND_MIXER_INFO
- Implement OSS_GETVERSION
- Accept mixer values above max (100)
- Handle the info from AUDIO_MIXER_DEVINFO properly, parts of it is opaque
- Use accurate rounding in conversion between OSS and OpenBSD volume values
- Map OSS mixer device "line1" to native mixer device "aux"
--
Some testing by pvalchev@, no response from other testers in over a month
and a half.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libossaudio/ossaudio.3 | 9 | ||||
-rw-r--r-- | lib/libossaudio/ossaudio.c | 190 | ||||
-rw-r--r-- | lib/libossaudio/soundcard.h | 43 |
3 files changed, 173 insertions, 69 deletions
diff --git a/lib/libossaudio/ossaudio.3 b/lib/libossaudio/ossaudio.3 index c2f53d174dc..127487a9457 100644 --- a/lib/libossaudio/ossaudio.3 +++ b/lib/libossaudio/ossaudio.3 @@ -1,9 +1,12 @@ -.\" $OpenBSD: ossaudio.3,v 1.4 1999/07/09 13:35:28 aaron Exp $ -.\" $NetBSD: ossaudio.3,v 1.6 1998/02/05 18:52:19 perry Exp $ +.\" $OpenBSD: ossaudio.3,v 1.5 2001/08/18 19:33:30 brad Exp $ +.\" $NetBSD: ossaudio.3,v 1.12 2001/05/19 17:23:39 jdolecek Exp $ .\" .\" Copyright (c) 1997 The NetBSD Foundation, Inc. .\" All rights reserved. .\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Lennart Augustsson, +.\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: @@ -68,7 +71,7 @@ that would block in non-blocking mode Linux returns whereas .Ox 2.3 returns -.Dv EWOULDBLOCK . +.Dv EAGAIN . .Sh HISTORY The .Nm diff --git a/lib/libossaudio/ossaudio.c b/lib/libossaudio/ossaudio.c index bb58068c067..1e2b9356c4e 100644 --- a/lib/libossaudio/ossaudio.c +++ b/lib/libossaudio/ossaudio.c @@ -1,7 +1,7 @@ -/* $OpenBSD: ossaudio.c,v 1.3 2001/05/24 04:21:03 aaron Exp $ */ -/* $NetBSD: ossaudio.c,v 1.5 1998/03/23 00:39:18 augustss Exp $ */ +/* $OpenBSD: ossaudio.c,v 1.4 2001/08/18 19:33:30 brad Exp $ */ +/* $NetBSD: ossaudio.c,v 1.14 2001/05/10 01:53:48 augustss Exp $ */ -/* +/*- * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * @@ -55,8 +55,8 @@ #define GET_DEV(com) ((com) & 0xff) -#define TO_OSSVOL(x) ((x) * 100 / 255) -#define FROM_OSSVOL(x) ((x) * 255 / 100) +#define TO_OSSVOL(x) (((x) * 100 + 127) / 255) +#define FROM_OSSVOL(x) ((((x) > 100 ? 100 : (x)) * 255 + 50) / 100) static struct audiodevinfo *getdevinfo(int); @@ -64,6 +64,9 @@ static void setblocksize(int, struct audio_info *); static int audio_ioctl(int, unsigned long, void *); static int mixer_ioctl(int, unsigned long, void *); +static int opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq); +static int enum_to_ord(struct audiodevinfo *di, int enm); +static int enum_to_mask(struct audiodevinfo *di, int enm); #define INTARG (*(int*)argp) @@ -81,7 +84,7 @@ _oss_ioctl(int fd, unsigned long com, void *argp) static int audio_ioctl(int fd, unsigned long com, void *argp) { - + struct audio_info tmpinfo; struct audio_offset tmpoffs; struct audio_buf_info bufinfo; @@ -108,7 +111,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) tmpinfo.play.sample_rate = tmpinfo.record.sample_rate = INTARG; (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); - /* fall into ... */ + /* FALLTHRU */ case SOUND_PCM_READ_RATE: retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) @@ -187,7 +190,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) return EINVAL; } (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); - /* fall into ... */ + /* FALLTHRU */ case SOUND_PCM_READ_BITS: retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) @@ -234,7 +237,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) tmpinfo.play.channels = tmpinfo.record.channels = INTARG; (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); - /* fall into ... */ + /* FALLTHRU */ case SOUND_PCM_READ_CHANNELS: retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) @@ -267,7 +270,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) if ((idat & 0xffff) < 4 || (idat & 0xffff) > 17) return EINVAL; tmpinfo.blocksize = 1 << (idat & 0xffff); - tmpinfo.hiwat = (idat >> 16) & 0x7fff; + tmpinfo.hiwat = ((unsigned)idat >> 16) & 0x7fff; if (tmpinfo.hiwat == 0) /* 0 means set to max */ tmpinfo.hiwat = 65536; (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); @@ -275,17 +278,15 @@ audio_ioctl(int fd, unsigned long com, void *argp) if (retval < 0) return retval; u = tmpinfo.blocksize; - for(idat = 0; u>1; idat++, u >>= 1) + for(idat = 0; u > 1; idat++, u >>= 1) ; idat |= (tmpinfo.hiwat & 0x7fff) << 16; INTARG = idat; break; case SNDCTL_DSP_GETFMTS: - for(idat = 0, tmpenc.index = 0; - ioctl(fd, AUDIO_GETENC, &tmpenc) == 0; + for(idat = 0, tmpenc.index = 0; + ioctl(fd, AUDIO_GETENC, &tmpenc) == 0; tmpenc.index++) { - if (tmpenc.flags & AUDIO_ENCODINGFLAG_EMULATED) - continue; /* Don't report emulated modes */ switch(tmpenc.encoding) { case AUDIO_ENCODING_ULAW: idat |= AFMT_MU_LAW; @@ -339,19 +340,19 @@ audio_ioctl(int fd, unsigned long com, void *argp) setblocksize(fd, &tmpinfo); bufinfo.fragsize = tmpinfo.blocksize; bufinfo.fragments = tmpinfo.hiwat - - (tmpinfo.play.seek + tmpinfo.blocksize - 1)/tmpinfo.blocksize; + (tmpinfo.play.seek + tmpinfo.blocksize - 1)/tmpinfo.blocksize; bufinfo.fragstotal = tmpinfo.hiwat; bufinfo.bytes = tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.play.seek; *(struct audio_buf_info *)argp = bufinfo; break; case SNDCTL_DSP_GETISPACE: - retval = ioctl(fd, AUDIO_GETINFO, (caddr_t)&tmpinfo); + retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) return retval; setblocksize(fd, &tmpinfo); bufinfo.fragsize = tmpinfo.blocksize; bufinfo.fragments = tmpinfo.hiwat - - (tmpinfo.record.seek + tmpinfo.blocksize - 1)/tmpinfo.blocksize; + (tmpinfo.record.seek + tmpinfo.blocksize - 1)/tmpinfo.blocksize; bufinfo.fragstotal = tmpinfo.hiwat; bufinfo.bytes = tmpinfo.hiwat * tmpinfo.blocksize - tmpinfo.record.seek; *(struct audio_buf_info *)argp = bufinfo; @@ -363,7 +364,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) return retval; break; case SNDCTL_DSP_GETCAPS: - retval = ioctl(fd, AUDIO_GETPROPS, (caddr_t)&idata); + retval = ioctl(fd, AUDIO_GETPROPS, &idata); if (retval < 0) return retval; idat = DSP_CAP_TRIGGER; /* pretend we have trigger */ @@ -375,7 +376,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) break; #if 0 case SNDCTL_DSP_GETTRIGGER: - retval = ioctl(fd, AUDIO_GETINFO, (caddr_t)&tmpinfo); + retval = ioctl(fd, AUDIO_GETINFO, &tmpinfo); if (retval < 0) return retval; idat = (tmpinfo.play.pause ? 0 : PCM_ENABLE_OUTPUT) | @@ -391,7 +392,7 @@ audio_ioctl(int fd, unsigned long com, void *argp) return retval; tmpinfo.play.pause = (idat & PCM_ENABLE_OUTPUT) == 0; tmpinfo.record.pause = (idat & PCM_ENABLE_INPUT) == 0; - (void) ioctl(fd, AUDIO_SETINFO, (caddr_t)&tmpinfo); + (void) ioctl(fd, AUDIO_SETINFO, &tmpinfo); retval = copyout(&idat, SCARG(uap, data), sizeof idat); if (retval < 0) return retval; @@ -437,19 +438,66 @@ audio_ioctl(int fd, unsigned long com, void *argp) } -/* If the NetBSD mixer device should have more than 32 devices +/* If the NetBSD mixer device should have more than NETBSD_MAXDEVS devices * some will not be available to Linux */ -#define NETBSD_MAXDEVS 32 +#define NETBSD_MAXDEVS 64 struct audiodevinfo { int done; dev_t dev; - int16_t devmap[SOUND_MIXER_NRDEVICES], + int16_t devmap[SOUND_MIXER_NRDEVICES], rdevmap[NETBSD_MAXDEVS]; + char names[NETBSD_MAXDEVS][MAX_AUDIO_DEV_LEN]; + int enum2opaque[NETBSD_MAXDEVS]; u_long devmask, recmask, stereomask; u_long caps, source; }; -/* +static int +opaque_to_enum(struct audiodevinfo *di, audio_mixer_name_t *label, int opq) +{ + int i, o; + + for (i = 0; i < NETBSD_MAXDEVS; i++) { + o = di->enum2opaque[i]; + if (o == opq) + break; + if (o == -1 && label != NULL && + !strncmp(di->names[i], label->name, sizeof di->names[i])) { + di->enum2opaque[i] = opq; + break; + } + } + if (i >= NETBSD_MAXDEVS) + i = -1; + /*printf("opq_to_enum %s %d -> %d\n", label->name, opq, i);*/ + return (i); +} + +static int +enum_to_ord(struct audiodevinfo *di, int enm) +{ + if (enm >= NETBSD_MAXDEVS) + return (-1); + + /*printf("enum_to_ord %d -> %d\n", enm, di->enum2opaque[enm]);*/ + return (di->enum2opaque[enm]); +} + +static int +enum_to_mask(struct audiodevinfo *di, int enm) +{ + int m; + if (enm >= NETBSD_MAXDEVS) + return (0); + + m = di->enum2opaque[enm]; + if (m == -1) + m = 0; + /*printf("enum_to_mask %d -> %d\n", enm, di->enum2opaque[enm]);*/ + return (m); +} + +/* * Collect the audio device information to allow faster * emulation of the Linux mixer ioctls. Cache the information * to eliminate the overhead of repeating all the ioctls needed @@ -459,7 +507,7 @@ static struct audiodevinfo * getdevinfo(int fd) { mixer_devinfo_t mi; - int i; + int i, j, e; static struct { char *name; int code; @@ -468,6 +516,7 @@ getdevinfo(int fd) { AudioNline, SOUND_MIXER_LINE }, { AudioNcd, SOUND_MIXER_CD }, { AudioNdac, SOUND_MIXER_PCM }, + { AudioNaux, SOUND_MIXER_LINE1 }, { AudioNrecord, SOUND_MIXER_IMIX }, { AudioNmaster, SOUND_MIXER_VOLUME }, { AudioNtreble, SOUND_MIXER_TREBLE }, @@ -502,12 +551,15 @@ getdevinfo(int fd) di->devmask = 0; di->recmask = 0; di->stereomask = 0; - di->source = -1; + di->source = ~0; di->caps = 0; for(i = 0; i < SOUND_MIXER_NRDEVICES; i++) di->devmap[i] = -1; - for(i = 0; i < NETBSD_MAXDEVS; i++) + for(i = 0; i < NETBSD_MAXDEVS; i++) { di->rdevmap[i] = -1; + di->names[i][0] = '\0'; + di->enum2opaque[i] = -1; + } for(i = 0; i < NETBSD_MAXDEVS; i++) { mi.index = i; if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0) @@ -523,29 +575,37 @@ getdevinfo(int fd) di->devmask |= 1 << dp->code; if (mi.un.v.num_channels == 2) di->stereomask |= 1 << dp->code; + strncpy(di->names[i], mi.label.name, + sizeof di->names[i]); } break; + } + } + for(i = 0; i < NETBSD_MAXDEVS; i++) { + mi.index = i; + if (ioctl(fd, AUDIO_MIXER_DEVINFO, &mi) < 0) + break; + if (strcmp(mi.label.name, AudioNsource) != 0) + continue; + di->source = i; + switch(mi.type) { case AUDIO_MIXER_ENUM: - if (strcmp(mi.label.name, AudioNsource) == 0) { - int j; - di->source = i; - for(j = 0; j < mi.un.e.num_mem; j++) - di->recmask |= 1 << di->rdevmap[mi.un.e.member[j].ord]; - di->caps = SOUND_CAP_EXCL_INPUT; + for(j = 0; j < mi.un.e.num_mem; j++) { + e = opaque_to_enum(di, + &mi.un.e.member[j].label, + mi.un.e.member[j].ord); + if (e >= 0) + di->recmask |= 1 << di->rdevmap[e]; } + di->caps = SOUND_CAP_EXCL_INPUT; break; case AUDIO_MIXER_SET: - if (strcmp(mi.label.name, AudioNsource) == 0) { - int j; - di->source = i; - for(j = 0; j < mi.un.s.num_mem; j++) { - int k, mask = mi.un.s.member[j].mask; - if (mask) { - for(k = 0; !(mask & 1); mask >>= 1, k++) - ; - di->recmask |= 1 << di->rdevmap[k]; - } - } + for(j = 0; j < mi.un.s.num_mem; j++) { + e = opaque_to_enum(di, + &mi.un.s.member[j].label, + mi.un.s.member[j].mask); + if (e >= 0) + di->recmask |= 1 << di->rdevmap[e]; } break; } @@ -555,19 +615,35 @@ getdevinfo(int fd) int mixer_ioctl(int fd, unsigned long com, void *argp) -{ +{ struct audiodevinfo *di; + struct mixer_info *omi; + struct audio_device adev; mixer_ctrl_t mc; int idat; int i; int retval; - int l, r, n; + int l, r, n, error, e; di = getdevinfo(fd); if (di == 0) return -1; switch (com) { + case OSS_GETVERSION: + idat = SOUND_VERSION; + break; + case SOUND_MIXER_INFO: + case SOUND_OLD_MIXER_INFO: + error = ioctl(fd, AUDIO_GETDEV, &adev); + if (error) + return (error); + omi = argp; + if (com == SOUND_MIXER_INFO) + omi->modify_counter = 1; + strncpy(omi->id, adev.name, sizeof omi->id); + strncpy(omi->name, adev.name, sizeof omi->name); + return 0; case SOUND_MIXER_READ_RECSRC: if (di->source == -1) return EINVAL; @@ -577,18 +653,17 @@ mixer_ioctl(int fd, unsigned long com, void *argp) retval = ioctl(fd, AUDIO_MIXER_READ, &mc); if (retval < 0) return retval; - idat = 1 << di->rdevmap[mc.un.ord]; + e = opaque_to_enum(di, NULL, mc.un.ord); + if (e >= 0) + idat = 1 << di->rdevmap[e]; } else { - int k; - unsigned int mask; mc.type = AUDIO_MIXER_SET; retval = ioctl(fd, AUDIO_MIXER_READ, &mc); if (retval < 0) return retval; - idat = 0; - for(mask = mc.un.mask, k = 0; mask; mask >>= 1, k++) - if (mask & 1) - idat |= 1 << di->rdevmap[k]; + e = opaque_to_enum(di, NULL, mc.un.mask); + if (e >= 0) + idat = 1 << di->rdevmap[e]; } break; case SOUND_MIXER_READ_DEVMASK: @@ -617,7 +692,7 @@ mixer_ioctl(int fd, unsigned long com, void *argp) if (i >= SOUND_MIXER_NRDEVICES || di->devmap[i] == -1) return EINVAL; - mc.un.ord = di->devmap[i]; + mc.un.ord = enum_to_ord(di, di->devmap[i]); } else { mc.type = AUDIO_MIXER_SET; mc.un.mask = 0; @@ -625,7 +700,7 @@ mixer_ioctl(int fd, unsigned long com, void *argp) if (idat & (1 << i)) { if (di->devmap[i] == -1) return EINVAL; - mc.un.mask |= 1 << di->devmap[i]; + mc.un.mask |= enum_to_mask(di, di->devmap[i]); } } } @@ -693,7 +768,7 @@ mixer_ioctl(int fd, unsigned long com, void *argp) * Check that the blocksize is a power of 2 as OSS wants. * If not, set it to be. */ -static void +static void setblocksize(int fd, struct audio_info *info) { struct audio_info set; @@ -708,4 +783,3 @@ setblocksize(int fd, struct audio_info *info) ioctl(fd, AUDIO_GETINFO, info); } } - diff --git a/lib/libossaudio/soundcard.h b/lib/libossaudio/soundcard.h index 746bd04a59c..c88823d7897 100644 --- a/lib/libossaudio/soundcard.h +++ b/lib/libossaudio/soundcard.h @@ -1,10 +1,13 @@ -/* $OpenBSD: soundcard.h,v 1.5 2001/05/24 04:21:03 aaron Exp $ */ -/* $NetBSD: soundcard.h,v 1.4 1997/10/29 20:23:27 augustss Exp $ */ +/* $OpenBSD: soundcard.h,v 1.6 2001/08/18 19:33:30 brad Exp $ */ +/* $NetBSD: soundcard.h,v 1.11 2001/05/09 21:49:58 augustss Exp $ */ -/* +/*- * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * + * This code is derived from software contributed to The NetBSD Foundation + * by Lennart Augustsson. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -41,8 +44,8 @@ * only for compiling Linux programs. */ -#ifndef _soundcard_h_ -#define _soundcard_h_ +#ifndef _SOUNDCARD_H_ +#define _SOUNDCARD_H_ #ifndef _IOWR #include <sys/ioccom.h> @@ -266,6 +269,21 @@ #define SOUND_MASK_LINE2 (1 << SOUND_MIXER_LINE2) #define SOUND_MASK_LINE3 (1 << SOUND_MIXER_LINE3) +typedef struct mixer_info { + char id[16]; + char name[32]; + int modify_counter; + int fillers[10]; +} mixer_info; + +typedef struct _old_mixer_info { + char id[16]; + char name[32]; +} _old_mixer_info; + +#define SOUND_MIXER_INFO _IOR ('M', 101, mixer_info) +#define SOUND_OLD_MIXER_INFO _IOR ('M', 101, _old_mixer_info) + #define OSS_GETVERSION _IOR ('M', 118, int) typedef struct audio_buf_info { @@ -286,8 +304,17 @@ typedef struct buffmem_desc { int size; } buffmem_desc; -#define ioctl(fd, com, argp) _oss_ioctl(fd, com, argp) +#if 0 +/* This is what we'd like to have, but it causes prototype conflicts. */ +#define ioctl _oss_ioctl +#else +#define ioctl(x,y,z) _oss_ioctl(x,y,z) +#endif -int _oss_ioctl(int fd, unsigned long com, void *argp); +#include <sys/cdefs.h> -#endif +__BEGIN_DECLS +int _oss_ioctl __P((int fd, unsigned long com, void *argp)); +__END_DECLS + +#endif /* !_SOUNDCARD_H_ */ |