View | Details | Raw Unified | Return to bug 214210 | Differences between
and this patch

Collapse All | Expand All

(-)b/audio/sndio/Makefile (-1 / +1 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	sndio
4
PORTNAME=	sndio
5
PORTVERSION=	1.1.0
5
PORTVERSION=	1.1.0
6
PORTREVISION=	1
6
PORTREVISION=	2
7
CATEGORIES=	audio
7
CATEGORIES=	audio
8
MASTER_SITES=	http://www.sndio.org/
8
MASTER_SITES=	http://www.sndio.org/
9
9
(-)b/audio/sndio/files/patch-configure (-8 / +49 lines)
Lines 1-30 Link Here
1
--- configure.orig	2015-12-15 05:28:04 UTC
1
--- configure.orig	2015-12-15 05:28:04 UTC
2
+++ configure
2
+++ configure
3
@@ -32,6 +32,7 @@ prefix=/usr/local			# where to install s
3
@@ -20,6 +20,8 @@ Usage: configure [options]
4
 --disable-sun			disable sun audio backend
5
 --enable-rmidi			enable character device midi backend [$rmidi]
6
 --disable-rmidi			disable character device midi backend
7
+--enable-umidi			enable character device midi backend [$umidi]
8
+--disable-umidi			disable character device midi backend
9
 --with-libbsd			use the libbsd rather than bsd-compat/*
10
 --without-libbsd		don't use libbsd
11
 END
12
@@ -32,7 +34,9 @@ prefix=/usr/local			# where to install s
4
 so="libsndio.so.\${MAJ}.\${MIN}"	# shared libs to build
13
 so="libsndio.so.\${MAJ}.\${MIN}"	# shared libs to build
5
 alsa=no					# do we want alsa support ?
14
 alsa=no					# do we want alsa support ?
6
 sun=no					# do we want sun support ?
15
 sun=no					# do we want sun support ?
7
+oss=no					# do we want oss support ?
16
+oss=no					# do we want oss support ?
8
 rmidi=no				# do we want support for raw char dev ?
17
 rmidi=no				# do we want support for raw char dev ?
18
+umidi=no				# do we want support for raw char dev ?
9
 precision=16				# aucat/sndiod arithmetic precision
19
 precision=16				# aucat/sndiod arithmetic precision
10
 user=_sndio				# non-privileged user for sndio daemon
20
 user=_sndio				# non-privileged user for sndio daemon
11
@@ -71,6 +72,15 @@ case `uname` in
21
 libbsd=no				# use libbsd?
22
@@ -71,6 +75,15 @@ case `uname` in
12
 		defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
23
 		defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
13
 		-DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM'
24
 		-DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM'
14
 		;;
25
 		;;
15
+	FreeBSD)
26
+	DragonFly|FreeBSD)
16
+		user=_sndio
27
+		user=_sndio
17
+		so="$so libsndio.so"
28
+		so="$so libsndio.so"
18
+		defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
29
+		defs='-DHAVE_ARC4RANDOM -DHAVE_ISSETUGID \\\
19
+		-DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM \\\
30
+		-DHAVE_STRLCAT -DHAVE_STRLCPY -DHAVE_STRTONUM'
20
+		-DDEFAULT_DEV=\\"fallback\\"'
21
+		oss=yes
31
+		oss=yes
32
+		umidi=yes
22
+		mandir=${prefix}/man
33
+		mandir=${prefix}/man
23
+		;;
34
+		;;
24
 esac
35
 esac
25
 
36
 
26
 # shell word separator (none)
37
 # shell word separator (none)
27
@@ -106,6 +116,12 @@ for i; do
38
@@ -106,6 +119,12 @@ for i; do
28
 	--disable-alsa)
39
 	--disable-alsa)
29
 		alsa=no
40
 		alsa=no
30
 		shift;;
41
 		shift;;
Lines 37-43 Link Here
37
 	--enable-sun)
48
 	--enable-sun)
38
 		sun=yes
49
 		sun=yes
39
 		shift;;
50
 		shift;;
40
@@ -162,6 +178,13 @@ if [ $alsa = yes ]; then
51
@@ -118,6 +137,12 @@ for i; do
52
 	--disable-rmidi)
53
 		rmidi=no
54
 		shift;;
55
+	--enable-umidi)
56
+		umidi=yes
57
+		shift;;
58
+	--disable-umidi)
59
+		umidi=no
60
+		shift;;
61
 	--privsep-user=*)
62
 		user="${i#--privsep-user=}"
63
 		shift;;
64
@@ -162,6 +187,13 @@ if [ $alsa = yes ]; then
41
 fi
65
 fi
42
 
66
 
43
 #
67
 #
Lines 51-61 Link Here
51
 # if using Sun API, add corresponding parameters
75
 # if using Sun API, add corresponding parameters
52
 #
76
 #
53
 if [ $sun = yes ]; then
77
 if [ $sun = yes ]; then
54
@@ -215,6 +238,7 @@ user..................... $user
78
@@ -176,6 +208,13 @@ if [ $rmidi = yes ]; then
79
 fi
80
 
81
 #
82
+# if using raw character devices for midi, add corresponding parameters
83
+#
84
+if [ $umidi = yes ]; then
85
+	defs="$defs -DUSE_UMIDI"
86
+fi
87
+
88
+#
89
 # if using libbsd, add corresponding parameters
90
 #
91
 if [ $libbsd = yes ]; then
92
@@ -215,8 +254,10 @@ user..................... $user
55
 libbsd................... $libbsd
93
 libbsd................... $libbsd
56
 precision................ $precision
94
 precision................ $precision
57
 alsa..................... $alsa
95
 alsa..................... $alsa
58
+oss...................... $oss
96
+oss...................... $oss
59
 sun...................... $sun
97
 sun...................... $sun
60
 rmidi.................... $rmidi
98
 rmidi.................... $rmidi
99
+umidi.................... $umidi
100
 
101
 Do "make && make install" to compile and install sndio
61
 
102
 
(-)b/audio/sndio/files/patch-libsndio_Makefile.in (-3 / +13 lines)
Lines 1-15 Link Here
1
--- libsndio/Makefile.in.orig	2015-12-30 11:54:40 UTC
1
--- libsndio/Makefile.in.orig	2015-12-30 11:54:40 UTC
2
+++ libsndio/Makefile.in
2
+++ libsndio/Makefile.in
3
@@ -99,7 +99,7 @@ clean:
3
@@ -98,8 +98,8 @@ clean:
4
 # loader to determine dependencies in a single pass
4
 #
5
 #
5
 OBJS = debug.o aucat.o \
6
 OBJS = debug.o aucat.o \
6
 mio.o mio_rmidi.o mio_alsa.o mio_aucat.o \
7
-mio.o mio_rmidi.o mio_alsa.o mio_aucat.o \
7
-sio.o sio_alsa.o sio_aucat.o sio_sun.o \
8
-sio.o sio_alsa.o sio_aucat.o sio_sun.o \
9
+mio.o mio_rmidi.o mio_umidi.o mio_alsa.o mio_aucat.o \
8
+sio.o sio_alsa.o sio_aucat.o sio_oss.o sio_sun.o \
10
+sio.o sio_alsa.o sio_aucat.o sio_oss.o sio_sun.o \
9
 issetugid.o strlcat.o strlcpy.o strtonum.o
11
 issetugid.o strlcat.o strlcpy.o strtonum.o
10
 
12
 
11
 .c.o:
13
 .c.o:
12
@@ -140,3 +140,5 @@ sio_aucat.o:	sio_aucat.c aucat.h amsg.h 
14
@@ -132,6 +132,7 @@ mio_alsa.o:	mio_alsa.c debug.h mio_priv.
15
 mio_aucat.o:	mio_aucat.c aucat.h amsg.h debug.h mio_priv.h sndio.h \
16
 		../bsd-compat/bsd-compat.h
17
 mio_rmidi.o:	mio_rmidi.c debug.h mio_priv.h sndio.h
18
+mio_umidi.o:	mio_umidi.c debug.h mio_priv.h sndio.h
19
 sio.o:		sio.c debug.h sio_priv.h sndio.h \
20
 		../bsd-compat/bsd-compat.h
21
 sio_alsa.o:	sio_alsa.c debug.h sio_priv.h sndio.h \
22
@@ -140,3 +141,5 @@ sio_aucat.o:	sio_aucat.c aucat.h amsg.h 
13
 		../bsd-compat/bsd-compat.h
23
 		../bsd-compat/bsd-compat.h
14
 sio_sun.o:	sio_sun.c debug.h sio_priv.h sndio.h \
24
 sio_sun.o:	sio_sun.c debug.h sio_priv.h sndio.h \
15
 		../bsd-compat/bsd-compat.h
25
 		../bsd-compat/bsd-compat.h
(-)b/audio/sndio/files/patch-libsndio_mio.c (+20 lines)
Added Link Here
1
--- libsndio/mio.c.orig	2015-12-09 10:13:10 UTC
2
+++ libsndio/mio.c
3
@@ -55,6 +55,8 @@ mio_open(const char *str, unsigned int m
4
 			return hdl;
5
 #if defined(USE_RMIDI)
6
 		return _mio_rmidi_open("rmidi/0", mode, nbio);
7
+#elif defined(USE_UMIDI)
8
+		return _mio_umidi_open("rmidi/0", mode, nbio);
9
 #elif defined(USE_ALSA)
10
 		return _mio_alsa_open("rmidi/0", mode, nbio);
11
 #else
12
@@ -68,6 +70,8 @@ mio_open(const char *str, unsigned int m
13
 	if (_sndio_parsetype(str, "rmidi"))
14
 #if defined(USE_RMIDI)
15
 		return _mio_rmidi_open(str, mode, nbio);
16
+#elif defined(USE_UMIDI)
17
+		return _mio_umidi_open(str, mode, nbio);
18
 #elif defined(USE_ALSA)
19
 		return _mio_alsa_open(str, mode, nbio);
20
 #else
(-)b/audio/sndio/files/patch-libsndio_mio__priv.h (+12 lines)
Added Link Here
1
--- libsndio/mio_priv.h.orig	2015-12-09 10:13:10 UTC
2
+++ libsndio/mio_priv.h
3
@@ -44,6 +44,9 @@ struct mio_ops {
4
 };
5
 
6
 struct mio_hdl *_mio_rmidi_open(const char *, unsigned, int);
7
+#ifdef USE_UMIDI
8
+struct mio_hdl *_mio_umidi_open(const char *, unsigned, int);
9
+#endif
10
 #ifdef USE_ALSA
11
 struct mio_hdl *_mio_alsa_open(const char *, unsigned, int);
12
 #endif
(-)b/audio/sndio/files/patch-libsndio_mio__umidi.c (+222 lines)
Added Link Here
1
--- libsndio/mio_umidi.c.orig	2016-11-04 12:06:45 UTC
2
+++ libsndio/mio_umidi.c
3
@@ -0,0 +1,219 @@
4
+/*	$OpenBSD$	*/
5
+/*
6
+ * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
7
+ * Copyright (c) 2016 Tobias Kortkamp <t@tobik.me>
8
+ *
9
+ * Permission to use, copy, modify, and distribute this software for any
10
+ * purpose with or without fee is hereby granted, provided that the above
11
+ * copyright notice and this permission notice appear in all copies.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
+ */
21
+
22
+#ifdef USE_UMIDI
23
+#include <sys/types.h>
24
+#include <sys/stat.h>
25
+
26
+#include <errno.h>
27
+#include <fcntl.h>
28
+#include <limits.h>
29
+#include <poll.h>
30
+#include <stdio.h>
31
+#include <stdlib.h>
32
+#include <string.h>
33
+#include <unistd.h>
34
+
35
+#include "debug.h"
36
+#include "mio_priv.h"
37
+
38
+#define DEVPATH_PREFIX	"/dev/umidi"
39
+#define DEVPATH_MAX 	(1 +		\
40
+	sizeof(DEVPATH_PREFIX) - 1 +	\
41
+	sizeof(int) * 3)
42
+
43
+struct mio_umidi_hdl {
44
+	struct mio_hdl mio;
45
+	int fd;
46
+};
47
+
48
+static void mio_umidi_close(struct mio_hdl *);
49
+static size_t mio_umidi_read(struct mio_hdl *, void *, size_t);
50
+static size_t mio_umidi_write(struct mio_hdl *, const void *, size_t);
51
+static int mio_umidi_nfds(struct mio_hdl *);
52
+static int mio_umidi_pollfd(struct mio_hdl *, struct pollfd *, int);
53
+static int mio_umidi_revents(struct mio_hdl *, struct pollfd *);
54
+
55
+static struct mio_ops mio_umidi_ops = {
56
+	mio_umidi_close,
57
+	mio_umidi_write,
58
+	mio_umidi_read,
59
+	mio_umidi_nfds,
60
+	mio_umidi_pollfd,
61
+	mio_umidi_revents
62
+};
63
+
64
+static int
65
+mio_umidi_getfd(const char *str, unsigned int mode, int nbio)
66
+{
67
+	const char *p;
68
+	char path[DEVPATH_MAX];
69
+	unsigned int devnum;
70
+	unsigned int subdevnum;
71
+	int fd, flags;
72
+
73
+	p = _sndio_parsetype(str, "rmidi");
74
+	if (p == NULL) {
75
+		DPRINTF("mio_umidi_getfd: %s: \"rsnd\" expected\n", str);
76
+		return -1;
77
+	}
78
+	switch (*p) {
79
+	case '/':
80
+		p++;
81
+		break;
82
+	default:
83
+		DPRINTF("mio_umidi_getfd: %s: '/' expected\n", str);
84
+		return -1;
85
+	}
86
+	p = _sndio_parsenum(p, &devnum, 255);
87
+	if (p == NULL) {
88
+		DPRINTF("mio_umidi_getfd: %s: number expected after '/'\n", str);
89
+		return -1;
90
+	}
91
+	switch (*p) {
92
+	case '.':
93
+		p++;
94
+		p = _sndio_parsenum(p, &subdevnum, 255);
95
+		if (p == NULL || *p != '\0') {
96
+			DPRINTF("mio_umidi_getfd: %s: number expected after '.'\n",
97
+				str);
98
+			return -1;
99
+		}
100
+		break;
101
+	default:
102
+		subdevnum = 0;
103
+	}
104
+	snprintf(path, sizeof(path), DEVPATH_PREFIX "%u.%u", devnum, subdevnum);
105
+	if (mode == (MIO_IN | MIO_OUT))
106
+		flags = O_RDWR;
107
+	else
108
+		flags = (mode & MIO_OUT) ? O_WRONLY : O_RDONLY;
109
+	while ((fd = open(path, flags | O_NONBLOCK | O_CLOEXEC)) < 0) {
110
+		if (errno == EINTR)
111
+			continue;
112
+		DPERROR(path);
113
+		return -1;
114
+	}
115
+	return fd;
116
+}
117
+
118
+static struct mio_hdl *
119
+mio_umidi_fdopen(int fd, unsigned int mode, int nbio)
120
+{
121
+	struct mio_umidi_hdl *hdl;
122
+
123
+	hdl = malloc(sizeof(struct mio_umidi_hdl));
124
+	if (hdl == NULL)
125
+		return NULL;
126
+	_mio_create(&hdl->mio, &mio_umidi_ops, mode, nbio);
127
+	hdl->fd = fd;
128
+	return (struct mio_hdl *)hdl;
129
+}
130
+
131
+struct mio_hdl *
132
+_mio_umidi_open(const char *str, unsigned int mode, int nbio)
133
+{
134
+	struct mio_hdl *hdl;
135
+	int fd;
136
+
137
+	fd = mio_umidi_getfd(str, mode, nbio);
138
+	if (fd < 0)
139
+		return NULL;
140
+	hdl = mio_umidi_fdopen(fd, mode, nbio);
141
+	if (hdl != NULL)
142
+		return hdl;
143
+	while (close(fd) < 0 && errno == EINTR)
144
+		; /* retry */
145
+	return NULL;
146
+}
147
+
148
+static void
149
+mio_umidi_close(struct mio_hdl *sh)
150
+{
151
+	struct mio_umidi_hdl *hdl = (struct mio_umidi_hdl *)sh;
152
+	int rc;
153
+
154
+	do {
155
+		rc = close(hdl->fd);
156
+	} while (rc < 0 && errno == EINTR);
157
+	free(hdl);
158
+}
159
+
160
+static size_t
161
+mio_umidi_read(struct mio_hdl *sh, void *buf, size_t len)
162
+{
163
+	struct mio_umidi_hdl *hdl = (struct mio_umidi_hdl *)sh;
164
+	ssize_t n;
165
+
166
+	while ((n = read(hdl->fd, buf, len)) < 0) {
167
+		if (errno == EINTR)
168
+			continue;
169
+		if (errno != EAGAIN) {
170
+			DPERROR("mio_umidi_read: read");
171
+			hdl->mio.eof = 1;
172
+		}
173
+		return 0;
174
+	}
175
+	if (n == 0) {
176
+		DPRINTF("mio_umidi_read: eof\n");
177
+		hdl->mio.eof = 1;
178
+		return 0;
179
+	}
180
+	return n;
181
+}
182
+
183
+static size_t
184
+mio_umidi_write(struct mio_hdl *sh, const void *buf, size_t len)
185
+{
186
+	struct mio_umidi_hdl *hdl = (struct mio_umidi_hdl *)sh;
187
+	ssize_t n;
188
+
189
+	while ((n = write(hdl->fd, buf, len)) < 0) {
190
+		if (errno == EINTR)
191
+			continue;
192
+		if (errno != EAGAIN) {
193
+			DPERROR("mio_umidi_write: write");
194
+			hdl->mio.eof = 1;
195
+		}
196
+		return 0;
197
+	}
198
+	return n;
199
+}
200
+
201
+static int
202
+mio_umidi_nfds(struct mio_hdl *sh)
203
+{
204
+	return 1;
205
+}
206
+
207
+static int
208
+mio_umidi_pollfd(struct mio_hdl *sh, struct pollfd *pfd, int events)
209
+{
210
+	struct mio_umidi_hdl *hdl = (struct mio_umidi_hdl *)sh;
211
+
212
+	pfd->fd = hdl->fd;
213
+	pfd->events = events;
214
+	return 1;
215
+}
216
+
217
+static int
218
+mio_umidi_revents(struct mio_hdl *sh, struct pollfd *pfd)
219
+{
220
+	return pfd->revents;
221
+}
222
+#endif /* defined USE_UMIDI */
(-)b/audio/sndio/files/patch-libsndio_sio.c (-11 / +3 lines)
Lines 1-23 Link Here
1
--- libsndio/sio.c.orig	2016-01-08 20:51:12 UTC
1
--- libsndio/sio.c.orig	2016-01-08 20:51:12 UTC
2
+++ libsndio/sio.c
2
+++ libsndio/sio.c
3
@@ -64,17 +64,25 @@ sio_open(const char *str, unsigned int m
3
@@ -64,6 +64,8 @@ sio_open(const char *str, unsigned int m
4
 			return hdl;
4
 			return hdl;
5
 #if defined(USE_SUN)
5
 #if defined(USE_SUN)
6
 		return _sio_sun_open("rsnd/0", mode, nbio);
6
 		return _sio_sun_open("rsnd/0", mode, nbio);
7
+#elif defined(USE_OSS)
7
+#elif defined(USE_OSS)
8
+		return _sio_oss_open("fallback", mode, nbio);
8
+		return _sio_oss_open("rsnd/0", mode, nbio);
9
 #elif defined(USE_ALSA)
9
 #elif defined(USE_ALSA)
10
 		return _sio_alsa_open("rsnd/0", mode, nbio);
10
 		return _sio_alsa_open("rsnd/0", mode, nbio);
11
 #else
11
 #else
12
 		return NULL;
12
@@ -75,6 +77,8 @@ sio_open(const char *str, unsigned int m
13
 #endif
14
 	}
15
+#if defined(USE_OSS)
16
+	if (strcmp(str, "fallback") == 0)
17
+		return _sio_oss_open(str, mode, nbio);
18
+#endif
19
 	if (_sndio_parsetype(str, "snd"))
20
 		return _sio_aucat_open(str, mode, nbio);
21
 	if (_sndio_parsetype(str, "rsnd"))
13
 	if (_sndio_parsetype(str, "rsnd"))
22
 #if defined(USE_SUN)
14
 #if defined(USE_SUN)
23
 		return _sio_sun_open(str, mode, nbio);
15
 		return _sio_sun_open(str, mode, nbio);
(-)b/audio/sndio/files/patch-libsndio_sio__oss.c (-481 / +287 lines)
Lines 1-6 Link Here
1
--- libsndio/sio_oss.c.orig	2016-08-20 02:30:22 UTC
1
--- libsndio/sio_oss.c.orig	2016-11-04 12:06:45 UTC
2
+++ libsndio/sio_oss.c
2
+++ libsndio/sio_oss.c
3
@@ -0,0 +1,838 @@
3
@@ -0,0 +1,644 @@
4
+/*	$OpenBSD$	*/
4
+/*	$OpenBSD$	*/
5
+/*
5
+/*
6
+ * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
6
+ * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
Lines 20-34 Link Here
20
+ */
20
+ */
21
+
21
+
22
+#ifdef USE_OSS
22
+#ifdef USE_OSS
23
+#include <sys/types.h>
24
+#include <sys/ioctl.h>
23
+#include <sys/ioctl.h>
25
+#include <sys/param.h>
26
+#include <sys/soundcard.h>
24
+#include <sys/soundcard.h>
27
+#include <sys/stat.h>
28
+
25
+
29
+#include <errno.h>
26
+#include <errno.h>
30
+#include <fcntl.h>
27
+#include <fcntl.h>
31
+#include <limits.h>
32
+#include <poll.h>
28
+#include <poll.h>
33
+#include <stdio.h>
29
+#include <stdio.h>
34
+#include <stdlib.h>
30
+#include <stdlib.h>
Lines 44-101 Link Here
44
+	sizeof(DEVPATH_PREFIX) - 1 +	\
40
+	sizeof(DEVPATH_PREFIX) - 1 +	\
45
+	sizeof(int) * 3)
41
+	sizeof(int) * 3)
46
+
42
+
47
+#define AUDIO_INITPAR(p)						\
43
+struct sio_oss_fmt {
48
+	(void)memset((void *)(p), 0xff, sizeof(struct audio_swpar))
44
+	int fmt;
45
+	unsigned int bits;
46
+	unsigned int bps;
47
+	unsigned int sig;
48
+	unsigned int le;
49
+	unsigned int msb;
50
+};
51
+static struct sio_oss_fmt formats[] = {
52
+	/* See http://manuals.opensound.com/developer/formats.html.
53
+	 * AFMT_{S8,U16}_* are marked as obsolete so are missing here.
54
+	 */
49
+
55
+
50
+/*
56
+	/* le+msb not important */
51
+ * argument to AUDIO_SETPAR and AUDIO_GETPAR ioctls
57
+	{ AFMT_U8,      8, 1, 0, 0, 0 },
52
+ */
58
+	{ AFMT_U8,      8, 1, 0, 1, 0 },
53
+struct audio_swpar {
59
+	{ AFMT_U8,      8, 1, 0, 0, 1 },
54
+	unsigned int sig;		/* if 1, encoding is signed */
60
+	{ AFMT_U8,      8, 1, 0, 1, 1 },
55
+	unsigned int le;		/* if 1, encoding is little-endian */
61
+
56
+	unsigned int bits;		/* bits per sample */
62
+	/* msb not important */
57
+	unsigned int bps;		/* bytes per sample */
63
+	{ AFMT_S16_BE, 16, 2, 1, 0, 0 },
58
+	unsigned int msb;		/* if 1, bits are msb-aligned */
64
+	{ AFMT_S16_BE, 16, 2, 1, 0, 1 },
59
+	unsigned int rate;		/* common play & rec sample rate */
65
+	{ AFMT_S16_LE, 16, 2, 1, 1, 0 },
60
+	unsigned int pchan;		/* play channels */
66
+	{ AFMT_S16_LE, 16, 2, 1, 1, 1 },
61
+	unsigned int rchan;		/* rec channels */
67
+	{ AFMT_S24_BE, 24, 3, 1, 0, 0 },
62
+	unsigned int nblks;		/* number of blocks in play buffer */
68
+	{ AFMT_S24_BE, 24, 3, 1, 0, 1 },
63
+	unsigned int round;		/* common frames per block */
69
+	{ AFMT_S24_LE, 24, 3, 1, 1, 0 },
64
+	unsigned int _spare[6];
70
+	{ AFMT_S24_LE, 24, 3, 1, 1, 1 },
71
+	{ AFMT_U24_BE, 24, 3, 0, 0, 0 },
72
+	{ AFMT_U24_BE, 24, 3, 0, 0, 1 },
73
+	{ AFMT_U24_LE, 24, 3, 0, 1, 0 },
74
+	{ AFMT_U24_LE, 24, 3, 0, 1, 1 },
75
+
76
+	{ AFMT_S32_BE, 32, 4, 1, 0, 1 },
77
+	{ AFMT_S32_LE, 32, 4, 1, 1, 1 },
78
+	{ AFMT_U32_BE, 32, 4, 0, 0, 1 },
79
+	{ AFMT_U32_LE, 32, 4, 0, 1, 1 },
65
+};
80
+};
66
+
81
+
67
+struct sio_oss_hdl {
82
+struct sio_oss_hdl {
68
+	struct sio_hdl sio;
83
+	struct sio_hdl sio;
69
+	int fd;
84
+	int fd;
70
+	unsigned int ibpf, obpf;	/* bytes per frame */
71
+	unsigned int isamples;
85
+	unsigned int isamples;
72
+	unsigned int osamples;
86
+	unsigned int osamples;
73
+	int idelta, odelta;		/* position reported to client */
87
+	int idelta, odelta;
74
+
75
+	char *devstr;
76
+
88
+
77
+	/* OSS doesn't have an API to ask for device parameters
89
+	int fmt;
78
+	 * without setting them, so we keep track of them ourselves.
90
+	unsigned int rate;
79
+	 */
91
+	unsigned int chan;
80
+	struct audio_swpar swpar;
92
+	unsigned int appbufsz;
93
+	unsigned int round;
81
+};
94
+};
82
+
95
+
83
+static void sio_oss_close(struct sio_hdl *);
96
+static struct sio_hdl *sio_oss_fdopen(const char *, int, unsigned int, int);
84
+static int sio_oss_start(struct sio_hdl *);
85
+static int sio_oss_stop(struct sio_hdl *);
86
+static int sio_oss_setpar(struct sio_hdl *, struct sio_par *);
87
+static int sio_oss_getpar(struct sio_hdl *, struct sio_par *);
88
+static int sio_oss_getcap(struct sio_hdl *, struct sio_cap *);
97
+static int sio_oss_getcap(struct sio_hdl *, struct sio_cap *);
89
+static size_t sio_oss_read(struct sio_hdl *, void *, size_t);
98
+static int sio_oss_getfd(const char *, unsigned int, int);
90
+static size_t sio_oss_write(struct sio_hdl *, const void *, size_t);
99
+static int sio_oss_getpar(struct sio_hdl *, struct sio_par *);
91
+static int sio_oss_nfds(struct sio_hdl *);
100
+static int sio_oss_nfds(struct sio_hdl *);
92
+static int sio_oss_pollfd(struct sio_hdl *, struct pollfd *, int);
101
+static int sio_oss_pollfd(struct sio_hdl *, struct pollfd *, int);
93
+static int sio_oss_revents(struct sio_hdl *, struct pollfd *);
102
+static int sio_oss_revents(struct sio_hdl *, struct pollfd *);
94
+
103
+static int sio_oss_setpar(struct sio_hdl *, struct sio_par *);
95
+static void sio_oss_fmt_to_swpar(int, struct audio_swpar *);
104
+static int sio_oss_start(struct sio_hdl *);
96
+static int sio_oss_audio_getpar(struct sio_oss_hdl *, struct audio_swpar *);
105
+static int sio_oss_stop(struct sio_hdl *);
97
+static int sio_oss_audio_setpar(struct sio_oss_hdl *, struct audio_swpar *);
106
+static int sio_oss_xrun(struct sio_oss_hdl *);
98
+static int sio_oss_reopen(struct sio_oss_hdl *);
107
+static size_t sio_oss_read(struct sio_hdl *, void *, size_t);
108
+static size_t sio_oss_write(struct sio_hdl *, const void *, size_t);
109
+static void sio_oss_close(struct sio_hdl *);
99
+
110
+
100
+static struct sio_ops sio_oss_ops = {
111
+static struct sio_ops sio_oss_ops = {
101
+	sio_oss_close,
112
+	sio_oss_close,
Lines 113-209 Link Here
113
+	NULL, /* getvol */
124
+	NULL, /* getvol */
114
+};
125
+};
115
+
126
+
116
+static int
117
+sio_oss_adjpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap)
118
+{
119
+	if (hdl->sio.eof)
120
+		return 0;
121
+	if (sio_oss_audio_setpar(hdl, ap)) {
122
+		DPERROR("AUDIO_SETPAR");
123
+		hdl->sio.eof = 1;
124
+		return 0;
125
+	}
126
+	if (sio_oss_audio_getpar(hdl, ap)) {
127
+		DPERROR("AUDIO_GETPAR");
128
+		hdl->sio.eof = 1;
129
+		return 0;
130
+	}
131
+	return 1;
132
+}
133
+
134
+/*
135
+ * try to set the device to the given parameters and check that the
136
+ * device can use them; return 1 on success, 0 on failure or error
137
+ */
138
+static int
139
+sio_oss_testpar(struct sio_oss_hdl *hdl, struct sio_enc *enc,
140
+    unsigned int pchan, unsigned int rchan, unsigned int rate)
141
+{
142
+	struct audio_swpar ap;
143
+
144
+	AUDIO_INITPAR(&ap);
145
+	if (enc != NULL) {
146
+		ap.sig = enc->sig;
147
+		ap.bits = enc->bits;
148
+		ap.bps = enc->bps;
149
+		if (ap.bps > 1)
150
+			ap.le = enc->le;
151
+		if (ap.bps * 8 > ap.bits)
152
+			ap.msb = enc->msb;
153
+	}
154
+	if (rate)
155
+		ap.rate = rate;
156
+	if (pchan && (hdl->sio.mode & SIO_PLAY))
157
+		ap.pchan = pchan;
158
+	if (rchan && (hdl->sio.mode & SIO_REC))
159
+		ap.rchan = rchan;
160
+	if (!sio_oss_adjpar(hdl, &ap))
161
+		return 0;
162
+	if (pchan && ap.pchan != pchan)
163
+		return 0;
164
+	if (rchan && ap.rchan != rchan)
165
+		return 0;
166
+	if (rate && ap.rate != rate)
167
+		return 0;
168
+	if (enc) {
169
+		if (ap.sig != enc->sig)
170
+			return 0;
171
+		if (ap.bits != enc->bits)
172
+			return 0;
173
+		if (ap.bps != enc->bps)
174
+			return 0;
175
+		if (ap.bps > 1 && ap.le != enc->le)
176
+			return 0;
177
+		if (ap.bits < ap.bps * 8 && ap.msb != enc->msb)
178
+			return 0;
179
+	}
180
+	return 1;
181
+}
182
+
183
+/*
127
+/*
184
+ * guess device capabilities
128
+ * guess device capabilities
185
+ */
129
+ */
186
+static int
130
+static int
187
+sio_oss_getcap(struct sio_hdl *sh, struct sio_cap *cap)
131
+sio_oss_getcap(struct sio_hdl *sh, struct sio_cap *cap)
188
+{
132
+{
133
+	/* From sound(4):
134
+	 * The FreeBSD multichannel matrix processor supports up to 18
135
+	 * interleaved channels, but the limit is currently set to 8
136
+	 * channels (as commonly used for 7.1 surround sound).
137
+	 */
189
+	static unsigned int chans[] = {
138
+	static unsigned int chans[] = {
190
+		1, 2, 4, 6, 8, 10, 12
139
+		1, 2, 4, 6, 8
191
+	};
140
+	};
192
+	static unsigned int rates[] = {
141
+	static unsigned int rates[] = {
193
+		8000, 11025, 12000, 16000, 22050, 24000,
142
+		8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100,
194
+		32000, 44100, 48000, 64000, 88200, 96000
143
+		48000, 64000, 88200, 96000, 192000
195
+	};
144
+	};
196
+	static unsigned int encs[] = {
145
+	static int afmts[] = {
197
+		8, 16, 24, 32
146
+		AFMT_U8, AFMT_S16_LE, AFMT_S16_BE, AFMT_S24_LE, AFMT_U24_LE,
147
+		AFMT_S32_LE, AFMT_U32_LE
198
+	};
148
+	};
199
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
149
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
200
+	struct audio_swpar savepar, ap;
201
+	unsigned int nconf = 0;
150
+	unsigned int nconf = 0;
202
+	unsigned int enc_map = 0, rchan_map = 0, pchan_map = 0, rate_map;
151
+	unsigned int enc_map = 0, rchan_map = 0, pchan_map = 0, rate_map;
203
+	unsigned int i, j, conf;
152
+	unsigned int i, j, k, conf;
153
+	int fmts;
204
+
154
+
205
+	if (sio_oss_audio_getpar(hdl, &savepar)) {
155
+	if (ioctl(hdl->fd, SNDCTL_DSP_GETFMTS, &fmts) < 0) {
206
+		DPERROR("AUDIO_GETPAR");
156
+		DPERROR("sio_oss_getcap: GETFMTS");
207
+		hdl->sio.eof = 1;
157
+		hdl->sio.eof = 1;
208
+		return 0;
158
+		return 0;
209
+	}
159
+	}
Lines 211-281 Link Here
211
+	/*
161
+	/*
212
+	 * get a subset of supported encodings
162
+	 * get a subset of supported encodings
213
+	 */
163
+	 */
214
+	for (i = 0; i < sizeof(encs) / sizeof(encs[0]); i++) {
164
+	for (j = 0, i = 0; i < sizeof(afmts) / sizeof(afmts[0]); i++) {
215
+		AUDIO_INITPAR(&ap);
165
+		if (fmts & afmts[i]) {
216
+		ap.bits = encs[i];
166
+			for (k = 0; k < sizeof(formats) / sizeof(formats[0]); k++) {
217
+		ap.sig = (ap.bits > 8) ? 1 : 0;
167
+				if (formats[k].fmt == afmts[i]) {
218
+		if (!sio_oss_adjpar(hdl, &ap))
168
+					cap->enc[j].sig = formats[k].sig;
219
+			return 0;
169
+					cap->enc[j].bits = formats[k].bits;
220
+		if (ap.bits == encs[i]) {
170
+					cap->enc[j].bps = formats[k].bps;
221
+			cap->enc[i].sig = ap.sig;
171
+					cap->enc[j].le = formats[k].le;
222
+			cap->enc[i].bits = ap.bits;
172
+					cap->enc[j].msb = formats[k].msb;
223
+			cap->enc[i].le = ap.le;
173
+					enc_map |= 1 << j;
224
+			cap->enc[i].bps = ap.bps;
174
+					j++;
225
+			cap->enc[i].msb = ap.msb;
175
+					break;
226
+			enc_map |= 1 << i;
176
+				}
177
+			}
227
+		}
178
+		}
228
+	}
179
+	}
229
+
180
+
230
+	/*
181
+	/*
231
+	 * fill channels
182
+	 * fill channels
232
+	 *
233
+	 * for now we're lucky: all kernel devices assume that the
234
+	 * number of channels and the encoding are independent so we can
235
+	 * use the current encoding and try various channels.
236
+	 */
183
+	 */
237
+	if (hdl->sio.mode & SIO_PLAY) {
184
+	if (hdl->sio.mode & SIO_PLAY) {
238
+		for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) {
185
+		for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) {
239
+			AUDIO_INITPAR(&ap);
186
+			cap->pchan[i] = chans[i];
240
+			ap.pchan = chans[i];
187
+			pchan_map |= (1 << i);
241
+			if (!sio_oss_adjpar(hdl, &ap))
242
+				return 0;
243
+			if (ap.pchan == chans[i]) {
244
+				cap->pchan[i] = chans[i];
245
+				pchan_map |= (1 << i);
246
+			}
247
+		}
188
+		}
248
+	}
189
+	}
249
+	if (hdl->sio.mode & SIO_REC) {
190
+	if (hdl->sio.mode & SIO_REC) {
250
+		for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) {
191
+		for (i = 0; i < sizeof(chans) / sizeof(chans[0]); i++) {
251
+			AUDIO_INITPAR(&ap);
192
+			cap->rchan[i] = chans[i];
252
+			ap.pchan = chans[i];
193
+			rchan_map |= (1 << i);
253
+			if (!sio_oss_adjpar(hdl, &ap))
254
+				return 0;
255
+			if (ap.rchan == chans[i]) {
256
+				cap->rchan[i] = chans[i];
257
+				rchan_map |= (1 << i);
258
+			}
259
+		}
194
+		}
260
+	}
195
+	}
261
+
196
+
262
+	/*
197
+	/*
263
+	 * fill rates
198
+	 * fill rates
264
+	 *
265
+	 * rates are not independent from other parameters (eg. on
266
+	 * uaudio devices), so certain rates may not be allowed with
267
+	 * certain encodings. We have to check rates for all encodings
268
+	 */
199
+	 */
269
+	for (j = 0; j < sizeof(encs) / sizeof(encs[0]); j++) {
200
+	for (j = 0; j < sizeof(formats) / sizeof(formats[0]); j++) {
270
+		rate_map = 0;
201
+		rate_map = 0;
271
+		if ((enc_map & (1 << j)) == 0)
202
+		if ((enc_map & (1 << j)) == 0)
272
+			continue;
203
+			continue;
273
+		for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) {
204
+		for (i = 0; i < sizeof(rates) / sizeof(rates[0]); i++) {
274
+			if (sio_oss_testpar(hdl,
205
+			cap->rate[i] = rates[i];
275
+				&cap->enc[j], 0, 0, rates[i])) {
206
+			rate_map |= (1 << i);
276
+				cap->rate[i] = rates[i];
277
+				rate_map |= (1 << i);
278
+			}
279
+		}
207
+		}
280
+		for (conf = 0; conf < nconf; conf++) {
208
+		for (conf = 0; conf < nconf; conf++) {
281
+			if (cap->confs[conf].rate == rate_map) {
209
+			if (cap->confs[conf].rate == rate_map) {
Lines 295-305 Link Here
295
+	}
223
+	}
296
+	cap->nconf = nconf;
224
+	cap->nconf = nconf;
297
+
225
+
298
+	if (sio_oss_audio_setpar(hdl, &savepar)) {
299
+		DPERROR("AUDIO_SETPAR");
300
+		hdl->sio.eof = 1;
301
+		return 0;
302
+	}
303
+	return 1;
226
+	return 1;
304
+}
227
+}
305
+
228
+
Lines 311-343 Link Here
311
+	unsigned int devnum;
234
+	unsigned int devnum;
312
+	int fd, flags;
235
+	int fd, flags;
313
+
236
+
314
+	if (strcmp(str, "fallback") == 0) {
237
+	p = _sndio_parsetype(str, "rsnd");
315
+		/* On FreeBSD /dev/dsp points to the default unit
238
+	if (p == NULL) {
316
+		 * selectable with the hw.snd.default_unit sysctl.
239
+		DPRINTF("sio_oss_getfd: %s: \"rsnd\" expected\n", str);
317
+		 * Use it as fallback device.
240
+		return -1;
318
+		 */
241
+	}
319
+		snprintf(path, sizeof(path), DEVPATH_PREFIX);
242
+	switch (*p) {
320
+	} else {
243
+	case '/':
321
+		p = _sndio_parsetype(str, "rsnd");
244
+		p++;
322
+		if (p == NULL) {
245
+		break;
323
+			DPRINTF("sio_oss_getfd: %s: \"rsnd\" expected\n", str);
246
+	default:
324
+			return -1;
247
+		DPRINTF("sio_oss_getfd: %s: '/' expected\n", str);
325
+		}
248
+		return -1;
326
+		switch (*p) {
249
+	}
327
+		case '/':
250
+	p = _sndio_parsenum(p, &devnum, 255);
328
+			p++;
251
+	if (p == NULL || *p != '\0') {
329
+			break;
252
+		DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str);
330
+		default:
253
+		return -1;
331
+			DPRINTF("sio_oss_getfd: %s: '/' expected\n", str);
332
+			return -1;
333
+		}
334
+		p = _sndio_parsenum(p, &devnum, 255);
335
+		if (p == NULL || *p != '\0') {
336
+			DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str);
337
+			return -1;
338
+		}
339
+		snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum);
340
+	}
254
+	}
255
+	snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum);
341
+	if (mode == (SIO_PLAY | SIO_REC))
256
+	if (mode == (SIO_PLAY | SIO_REC))
342
+		flags = O_RDWR;
257
+		flags = O_RDWR;
343
+	else
258
+	else
Lines 351-358 Link Here
351
+	return fd;
266
+	return fd;
352
+}
267
+}
353
+
268
+
354
+static struct sio_oss_hdl *
269
+static struct sio_hdl *
355
+sio_oss_fdopen(int fd, unsigned int mode, int nbio)
270
+sio_oss_fdopen(const char *str, int fd, unsigned int mode, int nbio)
356
+{
271
+{
357
+	struct sio_oss_hdl *hdl;
272
+	struct sio_oss_hdl *hdl;
358
+
273
+
Lines 362-376 Link Here
362
+	_sio_create(&hdl->sio, &sio_oss_ops, mode, nbio);
277
+	_sio_create(&hdl->sio, &sio_oss_ops, mode, nbio);
363
+
278
+
364
+	/* Set default device parameters */
279
+	/* Set default device parameters */
365
+	sio_oss_fmt_to_swpar(AFMT_S16_LE, &hdl->swpar);
280
+	hdl->fmt = AFMT_S16_LE;
366
+	hdl->swpar.msb = 1;
281
+	hdl->rate = 48000;
367
+	hdl->swpar.rate = 48000;
282
+	hdl->chan = 2;
368
+	hdl->swpar.bps = SIO_BPS(hdl->swpar.bits);
283
+	hdl->round = 960;
369
+	hdl->swpar.pchan = hdl->swpar.rchan = 2;
284
+	hdl->appbufsz = 8 * 960;
370
+
285
+
371
+	hdl->fd = fd;
286
+	hdl->fd = fd;
372
+
287
+
373
+	return hdl;
288
+	return (struct sio_hdl *)hdl;
374
+}
289
+}
375
+
290
+
376
+struct sio_hdl *
291
+struct sio_hdl *
Lines 383-393 Link Here
383
+	if (fd < 0)
298
+	if (fd < 0)
384
+		return NULL;
299
+		return NULL;
385
+
300
+
386
+	hdl = sio_oss_fdopen(fd, mode, nbio);
301
+	hdl = (struct sio_oss_hdl *)sio_oss_fdopen(str, fd, mode, nbio);
387
+	if (hdl != NULL) {
302
+	if (hdl != NULL)
388
+		hdl->devstr = strdup(str);
389
+		return (struct sio_hdl*)hdl;
303
+		return (struct sio_hdl*)hdl;
390
+        }
304
+
391
+	while (close(fd) < 0 && errno == EINTR)
305
+	while (close(fd) < 0 && errno == EINTR)
392
+		; /* retry */
306
+		; /* retry */
393
+
307
+
Lines 401-407 Link Here
401
+
315
+
402
+	while (close(hdl->fd) < 0 && errno == EINTR)
316
+	while (close(hdl->fd) < 0 && errno == EINTR)
403
+		; /* retry */
317
+		; /* retry */
404
+	free(hdl->devstr);
405
+	free(hdl);
318
+	free(hdl);
406
+}
319
+}
407
+
320
+
Lines 409-426 Link Here
409
+sio_oss_start(struct sio_hdl *sh)
322
+sio_oss_start(struct sio_hdl *sh)
410
+{
323
+{
411
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
324
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
412
+	int low;
413
+
325
+
414
+	hdl->obpf = hdl->sio.par.pchan * hdl->sio.par.bps;
415
+	hdl->ibpf = hdl->sio.par.rchan * hdl->sio.par.bps;
416
+	hdl->isamples = 0;
326
+	hdl->isamples = 0;
417
+	hdl->osamples = 0;
327
+	hdl->osamples = 0;
418
+	hdl->idelta = 0;
328
+	hdl->idelta = 0;
419
+	hdl->odelta = 0;
329
+	hdl->odelta = 0;
420
+
330
+
421
+	/* Nothing else to do here, device was just (re-)opened in
331
+	/* Nothing else to do here.  OSS starts playing/recording
422
+	 * sio_setpar and OSS starts playing/recording on first
332
+	 * on first write/read.
423
+	 * write/read.
424
+	 */
333
+	 */
425
+	_sio_onmove_cb(&hdl->sio, 0);
334
+	_sio_onmove_cb(&hdl->sio, 0);
426
+
335
+
Lines 431-475 Link Here
431
+sio_oss_stop(struct sio_hdl *sh)
340
+sio_oss_stop(struct sio_hdl *sh)
432
+{
341
+{
433
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh;
342
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl*)sh;
434
+	/* Close and reopen device.  This resets CURRENT_IPTR which
343
+
435
+	 * allows us to get a semi-accurate recording position */
344
+        if (ioctl(hdl->fd, SNDCTL_DSP_SYNC, NULL) < 0) {
436
+        if (sio_oss_audio_setpar(hdl, &hdl->swpar) < 0)
345
+            DPERROR("sio_oss_stop: SYNC");
437
+		return 0;
346
+            hdl->sio.eof = 1;
438
+	return 1;
347
+            return 0;
348
+        }
349
+        if (ioctl(hdl->fd, SNDCTL_DSP_HALT, NULL) < 0) {
350
+            DPERROR("sio_oss_stop: HALT");
351
+            hdl->sio.eof = 1;
352
+            return 0;
353
+        }
354
+
355
+        /* Reset device parameters.  When we do not do this, resuming
356
+         * playback/recording will trigger poll with revents=POLLIN
357
+         * too often, which leads to sndiod using 100 % CPU.
358
+         */
359
+        return sio_oss_setpar(sh, &hdl->sio.par);
439
+}
360
+}
440
+
361
+
441
+static int
362
+static int
442
+sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
363
+sio_oss_setpar(struct sio_hdl *sh, struct sio_par *par)
443
+{
364
+{
444
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
365
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
445
+	struct audio_swpar ap;
366
+	unsigned int i;
446
+
367
+	int policy;
447
+	AUDIO_INITPAR(&ap);
368
+
448
+	ap.sig = par->sig;
369
+	hdl->fmt = AFMT_S16_LE;
449
+	ap.le = par->le;
370
+	for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
450
+	ap.bits = par->bits;
371
+		if (formats[i].bits == par->bits
451
+	ap.bps = par->bps;
372
+		    && formats[i].le == par->le
452
+	ap.msb = par->msb;
373
+		    && formats[i].sig == par->sig
453
+	ap.rate = par->rate;
374
+		    && formats[i].msb == par->msb) {
375
+			hdl->fmt = formats[i].fmt;
376
+			break;
377
+		}
378
+	}
379
+
380
+	if (par->rate != ~0U)
381
+		hdl->rate = par->rate;
382
+	if (hdl->rate < 8000)
383
+		hdl->rate = 8000;
384
+	if (hdl->rate > 192000)
385
+		hdl->rate = 192000;
386
+
454
+	if (hdl->sio.mode & SIO_PLAY)
387
+	if (hdl->sio.mode & SIO_PLAY)
455
+		ap.pchan = par->pchan;
388
+		hdl->chan = par->pchan;
456
+	if (hdl->sio.mode & SIO_REC)
389
+	else if (hdl->sio.mode & SIO_REC)
457
+		ap.rchan = par->rchan;
390
+		hdl->chan = par->rchan;
391
+
458
+	if (par->round != ~0U && par->appbufsz != ~0U) {
392
+	if (par->round != ~0U && par->appbufsz != ~0U) {
459
+		ap.round = par->round;
393
+		hdl->round = par->round;
460
+		ap.nblks = par->appbufsz / par->round;
394
+		hdl->appbufsz = par->appbufsz;
461
+	} else if (par->round != ~0U) {
395
+	} else if (par->round != ~0U) {
462
+		ap.round = par->round;
396
+		hdl->round = par->round;
463
+		ap.nblks = 2;
397
+		hdl->appbufsz = 2 * par->round;
464
+	} else if (par->appbufsz != ~0U) {
398
+	} else if (par->appbufsz != ~0U) {
465
+		ap.round = par->appbufsz / 2;
399
+		hdl->round = par->appbufsz / 2;
466
+		ap.nblks = 2;
400
+		hdl->appbufsz = par->appbufsz;
401
+	}
402
+
403
+	/* Set timing policy to 5 which is OSS' default.  The
404
+	 * user-settable hw.snd.latency sysctl influences the default
405
+	 * policy.
406
+	 */
407
+	policy = 5;
408
+	if (ioctl(hdl->fd, SNDCTL_DSP_POLICY, &policy) < 0) {
409
+		DPERROR("sio_oss_setpar: POLICY");
410
+		hdl->sio.eof = 1;
411
+		return 0;
412
+	}
413
+
414
+	if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &hdl->fmt) < 0) {
415
+		DPERROR("sio_oss_setpar: SETFMT");
416
+		hdl->sio.eof = 1;
417
+		return 0;
418
+	}
419
+
420
+	if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &hdl->rate) < 0) {
421
+		DPERROR("sio_oss_setpar: SPEED");
422
+		hdl->sio.eof = 1;
423
+		return 0;
467
+	}
424
+	}
468
+	if (sio_oss_audio_setpar(hdl, &ap) < 0) {
425
+
469
+		DPERROR("AUDIO_SETPAR");
426
+	if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &hdl->chan) < 0) {
427
+		DPERROR("sio_oss_setpar: CHANNELS");
470
+		hdl->sio.eof = 1;
428
+		hdl->sio.eof = 1;
471
+		return 0;
429
+		return 0;
472
+	}
430
+	}
431
+
473
+	return 1;
432
+	return 1;
474
+}
433
+}
475
+
434
+
Lines 477-500 Link Here
477
+sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par)
436
+sio_oss_getpar(struct sio_hdl *sh, struct sio_par *par)
478
+{
437
+{
479
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
438
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
480
+	struct audio_swpar ap;
439
+	unsigned int i, found = 0;
481
+
440
+
482
+	if (sio_oss_audio_getpar(hdl, &ap) < 0) {
441
+	for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
483
+		DPERROR("AUDIO_GETPAR");
442
+		if (formats[i].fmt == hdl->fmt) {
443
+			par->sig = formats[i].sig;
444
+			par->le = formats[i].le;
445
+			par->bits = formats[i].bits;
446
+			par->bps = formats[i].bps;
447
+			par->msb = formats[i].msb;
448
+			found = 1;
449
+			break;
450
+		}
451
+	}
452
+	if (!found) {
453
+		DPRINTF("sio_oss_getpar: unknown format %d\n", hdl->fmt);
484
+		hdl->sio.eof = 1;
454
+		hdl->sio.eof = 1;
485
+		return 0;
455
+		return 0;
486
+	}
456
+	}
487
+	par->sig = ap.sig;
457
+
488
+	par->le = ap.le;
458
+	par->rate = hdl->rate;
489
+	par->bits = ap.bits;
459
+	par->pchan = hdl->chan;
490
+	par->bps = ap.bps;
460
+	par->rchan = hdl->chan;
491
+	par->msb = ap.msb;
461
+	par->round = hdl->round;
492
+	par->rate = ap.rate;
462
+	par->appbufsz = par->bufsz = hdl->appbufsz;
493
+	par->pchan = ap.pchan;
494
+	par->rchan = ap.rchan;
495
+	par->round = ap.round;
496
+	par->appbufsz = par->bufsz = ap.round * ap.nblks;
497
+	par->xrun = SIO_IGNORE;
463
+	par->xrun = SIO_IGNORE;
464
+
498
+	return 1;
465
+	return 1;
499
+}
466
+}
500
+
467
+
Lines 560-569 Link Here
560
+	return 1;
527
+	return 1;
561
+}
528
+}
562
+
529
+
563
+int
530
+static int
531
+sio_oss_xrun(struct sio_oss_hdl *hdl)
532
+{
533
+	int clk;
534
+	int wsil, rdrop, cmove;
535
+	int rbpf, rround;
536
+	int wbpf;
537
+
538
+	DPRINTFN(2, "sio_oss_xrun:\n");
539
+	if (_sndio_debug >= 2)
540
+		_sio_printpos(&hdl->sio);
541
+
542
+	/*
543
+	 * we assume rused/wused are zero if rec/play modes are not
544
+	 * selected. This allows us to keep the same formula for all
545
+	 * modes, provided we set rbpf/wbpf to 1 to avoid division by
546
+	 * zero.
547
+	 *
548
+	 * to understand the formula, draw a picture :)
549
+	 */
550
+	rbpf = (hdl->sio.mode & SIO_REC) ?
551
+	    hdl->sio.par.bps * hdl->sio.par.rchan : 1;
552
+	wbpf = (hdl->sio.mode & SIO_PLAY) ?
553
+	    hdl->sio.par.bps * hdl->sio.par.pchan : 1;
554
+	rround = hdl->sio.par.round * rbpf;
555
+
556
+	clk = hdl->sio.cpos % hdl->sio.par.round;
557
+	rdrop = (clk * rbpf - hdl->sio.rused) % rround;
558
+	if (rdrop < 0)
559
+		rdrop += rround;
560
+	cmove = (rdrop + hdl->sio.rused) / rbpf;
561
+	wsil = cmove * wbpf + hdl->sio.wused;
562
+
563
+	DPRINTFN(2, "wsil = %d, cmove = %d, rdrop = %d\n", wsil, cmove, rdrop);
564
+
565
+	if (!sio_oss_stop(&hdl->sio))
566
+		return 0;
567
+	if (!sio_oss_start(&hdl->sio))
568
+		return 0;
569
+	if (hdl->sio.mode & SIO_PLAY) {
570
+		hdl->odelta -= cmove;
571
+		hdl->sio.wsil = wsil;
572
+	}
573
+	if (hdl->sio.mode & SIO_REC) {
574
+		hdl->idelta -= cmove;
575
+		hdl->sio.rdrop = rdrop;
576
+	}
577
+	DPRINTFN(2, "xrun: corrected\n");
578
+	DPRINTFN(2, "wsil = %d, rdrop = %d, odelta = %d, idelta = %d\n",
579
+	    wsil, rdrop, hdl->odelta, hdl->idelta);
580
+	return 1;
581
+}
582
+
583
+static int
564
+sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd)
584
+sio_oss_revents(struct sio_hdl *sh, struct pollfd *pfd)
565
+{
585
+{
566
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
586
+	struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh;
587
+	audio_errinfo ei;
567
+	int delta;
588
+	int delta;
568
+	int revents = pfd->revents;
589
+	int revents = pfd->revents;
569
+	long long play_pos, rec_pos;
590
+	long long play_pos, rec_pos;
Lines 573-581 Link Here
573
+	    (pfd->revents & (POLLIN | POLLOUT)) == 0)
594
+	    (pfd->revents & (POLLIN | POLLOUT)) == 0)
574
+		return pfd->revents;
595
+		return pfd->revents;
575
+
596
+
597
+	/* Hide xruns from clients */
598
+	if (ioctl(hdl->fd, SNDCTL_DSP_GETERROR, &ei) < 0) {
599
+		DPERROR("sio_oss_revents: GETERROR");
600
+		hdl->sio.eof = 1;
601
+		return POLLHUP;
602
+	}
603
+	if (ei.play_underruns > 0 || ei.rec_overruns > 0) {
604
+		if (!sio_oss_xrun(hdl))
605
+			return POLLHUP;
606
+		return 0;
607
+	}
608
+
576
+	if (hdl->sio.mode & SIO_PLAY) {
609
+	if (hdl->sio.mode & SIO_PLAY) {
577
+		if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_OPTR, &optr) < 0) {
610
+		if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_OPTR, &optr) < 0) {
578
+			DPERROR("sio_oss_revents: ");
611
+			DPERROR("sio_oss_revents: CURRENT_OPTR");
579
+			hdl->sio.eof = 1;
612
+			hdl->sio.eof = 1;
580
+			return POLLHUP;
613
+			return POLLHUP;
581
+		}
614
+		}
Lines 589-595 Link Here
589
+	}
622
+	}
590
+	if (hdl->sio.mode & SIO_REC) {
623
+	if (hdl->sio.mode & SIO_REC) {
591
+		if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_IPTR, &iptr) < 0) {
624
+		if (ioctl(hdl->fd, SNDCTL_DSP_CURRENT_IPTR, &iptr) < 0) {
592
+			DPERROR("sio_oss_revents: ");
625
+			DPERROR("sio_oss_revents: CURRENT_IPTR");
593
+			hdl->sio.eof = 1;
626
+			hdl->sio.eof = 1;
594
+			return POLLHUP;
627
+			return POLLHUP;
595
+		}
628
+		}
Lines 611-841 Link Here
611
+	return revents;
644
+	return revents;
612
+}
645
+}
613
+
646
+
614
+static void
615
+sio_oss_fmt_to_swpar(int fmt, struct audio_swpar *ap) {
616
+	switch(fmt) {
617
+	case AFMT_S8:
618
+		ap->le = 1;
619
+		ap->sig = 1;
620
+		ap->bits = 8;
621
+		break;
622
+	case AFMT_U8:
623
+		ap->le = 1;
624
+		ap->sig = 0;
625
+		ap->bits = 8;
626
+		break;
627
+	case AFMT_S16_LE:
628
+		ap->le = 1;
629
+		ap->sig = 1;
630
+		ap->bits = 16;
631
+		break;
632
+	case AFMT_S16_BE:
633
+		ap->le = 0;
634
+		ap->sig = 1;
635
+		ap->bits = 16;
636
+		break;
637
+	case AFMT_U16_LE:
638
+		ap->le = 1;
639
+		ap->sig = 0;
640
+		ap->bits = 16;
641
+		break;
642
+	case AFMT_U16_BE:
643
+		ap->le = 0;
644
+		ap->sig = 0;
645
+		ap->bits = 16;
646
+		break;
647
+	case AFMT_S24_LE:
648
+		ap->le = 1;
649
+		ap->sig = 1;
650
+		ap->bits = 24;
651
+		break;
652
+	case AFMT_S24_BE:
653
+		ap->le = 0;
654
+		ap->sig = 1;
655
+		ap->bits = 24;
656
+		break;
657
+	case AFMT_U24_LE:
658
+		ap->le = 1;
659
+		ap->sig = 0;
660
+		ap->bits = 24;
661
+		break;
662
+	case AFMT_U24_BE:
663
+		ap->le = 0;
664
+		ap->sig = 0;
665
+		ap->bits = 24;
666
+		break;
667
+	case AFMT_S32_LE:
668
+		ap->le = 1;
669
+		ap->sig = 1;
670
+		ap->bits = 32;
671
+		break;
672
+	case AFMT_S32_BE:
673
+		ap->le = 0;
674
+		ap->sig = 1;
675
+		ap->bits = 32;
676
+		break;
677
+	case AFMT_U32_LE:
678
+		ap->le = 1;
679
+		ap->sig = 0;
680
+		ap->bits = 32;
681
+		break;
682
+	case AFMT_U32_BE:
683
+		ap->le = 0;
684
+		ap->sig = 0;
685
+		ap->bits = 32;
686
+		break;
687
+	}
688
+}
689
+
690
+static int
691
+sio_oss_swpar_to_fmt(struct audio_swpar *ap)
692
+{
693
+	unsigned int bits = ap->bits;
694
+	unsigned int sig = ap->sig;
695
+	unsigned int le = ap->le;
696
+
697
+	switch(bits) {
698
+	case 8:
699
+		if (sig)
700
+			return AFMT_S8;
701
+		else
702
+			return AFMT_U8;
703
+		break;
704
+	case 16:
705
+		if (sig)
706
+			if (le)
707
+				return AFMT_S16_LE;
708
+			else
709
+				return AFMT_S16_BE;
710
+		else
711
+			if (le)
712
+				return AFMT_U16_LE;
713
+			else
714
+				return AFMT_U16_BE;
715
+		break;
716
+		break;
717
+	case 24:
718
+		if (sig)
719
+			if (le)
720
+				return AFMT_S24_LE;
721
+			else
722
+				return AFMT_S24_BE;
723
+		else
724
+			if (le)
725
+				return AFMT_U24_LE;
726
+			else
727
+				return AFMT_U24_BE;
728
+		break;
729
+		break;
730
+	case 32:
731
+		if (sig)
732
+			if (le)
733
+				return AFMT_S32_LE;
734
+			else
735
+				return AFMT_S32_BE;
736
+		else
737
+			if (le)
738
+				return AFMT_U32_LE;
739
+			else
740
+				return AFMT_U32_BE;
741
+		break;
742
+	default:
743
+		if (sig)
744
+			if (SIO_LE_NATIVE)
745
+				return AFMT_S16_LE;
746
+			else
747
+				return AFMT_S16_BE;
748
+		else
749
+			if (SIO_LE_NATIVE)
750
+				return AFMT_U16_LE;
751
+			else
752
+				return AFMT_U16_BE;
753
+	}
754
+}
755
+
756
+static int sio_oss_audio_getpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap)
757
+{
758
+	audio_buf_info bi;
759
+
760
+	*ap = hdl->swpar;
761
+
762
+	return 0;
763
+}
764
+
765
+static int sio_oss_audio_setpar(struct sio_oss_hdl *hdl, struct audio_swpar *ap)
766
+{
767
+	audio_buf_info bi;
768
+	int bufsz;
769
+	int chan;
770
+	int fmt;
771
+	int rate;
772
+
773
+	if (sio_oss_reopen(hdl) < 0) {
774
+		DPERROR("sio_oss_audio_setpar: reopen");
775
+		return -1;
776
+	}
777
+
778
+	ap->msb = ap->msb == -1 ? 0 : ap->msb;
779
+	ap->sig = ap->sig == -1 ? 1 : ap->sig;
780
+	ap->bits = ap->bits == -1 ? ap->bps == -1 ? 16 : ap->bps*8 : ap->bits;
781
+	ap->le = ap->le == -1 ? SIO_LE_NATIVE : ap->le;
782
+	ap->bps = ap->bps == -1 ? SIO_BPS(ap->bits) : ap->bps;
783
+	ap->msb = 0;
784
+	ap->rate = ap->rate == -1 ? 48000 : ap->rate;
785
+
786
+	if (ap->bits < 8)
787
+		ap->bits = 8;
788
+	if (ap->bits > 32)
789
+		ap->bits = 32;
790
+	if (ap->bps < 1)
791
+		ap->bps = 1;
792
+	if (ap->bps > 4)
793
+		ap->bps = 4;
794
+	if (ap->rate < 4000)
795
+		ap->rate = 4000;
796
+	if (ap->rate > 192000)
797
+		ap->rate = 192000;
798
+
799
+	fmt = sio_oss_swpar_to_fmt(ap);
800
+	if (fmt < 0)
801
+		return -1;
802
+	if (ioctl(hdl->fd, SNDCTL_DSP_SETFMT, &fmt) < 0) {
803
+		DPERROR("sio_oss_audio_setpar: SETFMT");
804
+		return -1;
805
+	}
806
+	sio_oss_fmt_to_swpar(fmt, ap);
807
+
808
+	if (ioctl(hdl->fd, SNDCTL_DSP_SPEED, &ap->rate) < 0) {
809
+		DPERROR("sio_oss_audio_setpar: SPEED");
810
+		return -1;
811
+	}
812
+
813
+	chan = ap->pchan == ~0U ? ap->pchan : ap->rchan;
814
+	chan = chan == -1 ? 2 : chan;
815
+	if (ioctl(hdl->fd, SNDCTL_DSP_CHANNELS, &chan) < 0) {
816
+		DPERROR("sio_oss_audio_setpar: CHANNELS");
817
+		return -1;
818
+	}
819
+	ap->pchan = ap->rchan = chan;
820
+
821
+	ap->nblks = ap->nblks <= 0 ? 8 : ap->nblks;
822
+	ap->round = ap->round <= 0 ? 960 : ap->round;
823
+
824
+	hdl->swpar = *ap;
825
+
826
+	return 0;
827
+}
828
+
829
+static int sio_oss_reopen(struct sio_oss_hdl *hdl) {
830
+	/* Reopen device */
831
+	while (close(hdl->fd) < 0 && errno == EINTR)
832
+		; /* retry */
833
+	hdl->fd = sio_oss_getfd(hdl->devstr, hdl->sio.mode, 1);
834
+	if (hdl->fd < 0) {
835
+		DPERROR("sio_oss_audio_setpar: reopen");
836
+		return -1;
837
+	}
838
+	return 0;
839
+}
840
+
841
+#endif /* defined USE_OSS */
647
+#endif /* defined USE_OSS */
(-)b/audio/sndio/files/sndiod.in (-11 / +3 lines)
Lines 3-21 Link Here
3
# $FreeBSD$
3
# $FreeBSD$
4
#
4
#
5
# PROVIDE: sndiod
5
# PROVIDE: sndiod
6
# REQUIRE: NETWORKING
6
# REQUIRE: NETWORKING sysctl
7
# BEFORE:  DAEMON
7
# BEFORE:  DAEMON
8
# KEYWORD: shutdown
8
# KEYWORD: shutdown
9
9
10
# By default sndiod will use the audio device from
11
# hw.snd.default_unit.  You can override this by setting sndiod_flags.
12
#
13
# To connect to a remote sndiod use e.g.
14
# sndiod_flags="-f snd@remotehost/0"
15
#
16
# To use /dev/dsp5
17
# sndiod_flags="-f rsnd/5"
18
19
. /etc/rc.subr
10
. /etc/rc.subr
20
11
21
name=sndiod
12
name=sndiod
Lines 23-30 rcvar=sndiod_enable Link Here
23
14
24
load_rc_config $name
15
load_rc_config $name
25
16
17
: ${sndiod_dev="rsnd/$($SYSCTL -n hw.snd.default_unit)"}
26
: ${sndiod_enable="NO"}
18
: ${sndiod_enable="NO"}
27
: ${sndiod_flags="-s default -m mon -s monitor"}
19
: ${sndiod_flags="-f ${sndiod_dev} -c 0:7 -j off -s default -m mon -s monitor"}
28
20
29
command="%%PREFIX%%/bin/sndiod"
21
command="%%PREFIX%%/bin/sndiod"
30
22
(-)b/audio/sndio/pkg-message (-16 / +5 lines)
Lines 1-7 Link Here
1
Sndio's OSS support (i.e. local playback/recording support) is highly
2
experimental.  If you run into problems please file a bug at
3
https://github.com/t6/sndio or send an email to t+sndio@tobik.me.
4
5
Enable the sndiod server with:
1
Enable the sndiod server with:
6
2
7
    sysrc sndiod_enable=YES
3
    sysrc sndiod_enable=YES
Lines 13-31 plays through sndiod: Link Here
13
9
14
    aucat -f snd/0.monitor -o recording.wav
10
    aucat -f snd/0.monitor -o recording.wav
15
11
16
Make sure you override sndiod_flags if this is not wanted:
12
Make sure you override sndiod_flags if this is not wanted.
17
18
    sysrc sndiod_flags=""
19
20
If you want clients to auto-play to your remote sndio server set
21
sndiod_flags accordingly:
22
23
    sysrc sndiod_flags="-f snd@remotehost/0"
24
25
Alternatively you can always set the AUDIODEVICE environment variable
26
so clients know where to stream to:
27
13
28
    export AUDIODEVICE=snd@remotehost/0
14
By default the rc.d script passes '-c 0:7 -j off' to sndiod, so that
15
it uses all 8 virtual channels provided by OSS.  If you override
16
sndiod_flags consider keeping these options, so that multi-channel
17
audio works as you'd expect.
29
18
30
There is little sndio support in the FreeBSD ports tree right now.  If
19
There is little sndio support in the FreeBSD ports tree right now.  If
31
your favourite port is missing support please take a look at the fork
20
your favourite port is missing support please take a look at the fork

Return to bug 214210