summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2001-08-18 19:33:31 +0000
committerBrad Smith <brad@cvs.openbsd.org>2001-08-18 19:33:31 +0000
commitb728c67f4a10e177d3abd254bc75e4faf89b6de9 (patch)
treea721d3706d295016f4b217d5f1a9f998a7bc86fe /lib
parent6b0d83b161631a1d2b11af80ce91dad16accf085 (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.39
-rw-r--r--lib/libossaudio/ossaudio.c190
-rw-r--r--lib/libossaudio/soundcard.h43
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_ */