Line 0
Link Here
|
|
|
1 |
--- libsndio/sio_oss.c.orig 2016-11-06 11:21:59 UTC |
2 |
+++ libsndio/sio_oss.c |
3 |
@@ -108,6 +108,8 @@ static int sio_oss_xrun(struct sio_oss_h |
4 |
static size_t sio_oss_read(struct sio_hdl *, void *, size_t); |
5 |
static size_t sio_oss_write(struct sio_hdl *, const void *, size_t); |
6 |
static void sio_oss_close(struct sio_hdl *); |
7 |
+static int sio_oss_setvol(struct sio_hdl *, unsigned int); |
8 |
+static void sio_oss_getvol(struct sio_hdl *); |
9 |
|
10 |
static struct sio_ops sio_oss_ops = { |
11 |
sio_oss_close, |
12 |
@@ -121,8 +123,8 @@ static struct sio_ops sio_oss_ops = { |
13 |
sio_oss_nfds, |
14 |
sio_oss_pollfd, |
15 |
sio_oss_revents, |
16 |
- NULL, /* setvol */ |
17 |
- NULL, /* getvol */ |
18 |
+ sio_oss_setvol, |
19 |
+ sio_oss_getvol, |
20 |
}; |
21 |
|
22 |
/* |
23 |
@@ -228,12 +230,10 @@ sio_oss_getcap(struct sio_hdl *sh, struc |
24 |
} |
25 |
|
26 |
static int |
27 |
-sio_oss_getfd(const char *str, unsigned int mode, int nbio) |
28 |
+_sio_oss_getdev(const char *str, char *path, size_t len) |
29 |
{ |
30 |
const char *p; |
31 |
- char path[DEVPATH_MAX]; |
32 |
unsigned int devnum; |
33 |
- int fd, flags, val; |
34 |
|
35 |
p = _sndio_parsetype(str, "rsnd"); |
36 |
if (p == NULL) { |
37 |
@@ -253,7 +253,24 @@ sio_oss_getfd(const char *str, unsigned |
38 |
DPRINTF("sio_oss_getfd: %s: number expected after '/'\n", str); |
39 |
return -1; |
40 |
} |
41 |
- snprintf(path, sizeof(path), DEVPATH_PREFIX "%u", devnum); |
42 |
+ snprintf(path, len, DEVPATH_PREFIX "%u", devnum); |
43 |
+ return 0; |
44 |
+} |
45 |
+ |
46 |
+static int |
47 |
+sio_oss_getfd(const char *str, unsigned int mode, int nbio) |
48 |
+{ |
49 |
+ char path[DEVPATH_MAX]; |
50 |
+ int fd, flags, val; |
51 |
+ audio_buf_info bi; |
52 |
+ |
53 |
+ if (strcmp(str, SIO_DEVANY) == 0) { |
54 |
+ /* Use /dev/dsp (the default device) directly */ |
55 |
+ snprintf(path, sizeof(path), DEVPATH_PREFIX); |
56 |
+ } else if (_sio_oss_getdev(str, path, sizeof(path)) < 0) { |
57 |
+ return -1; |
58 |
+ } |
59 |
+ |
60 |
if (mode == (SIO_PLAY | SIO_REC)) |
61 |
flags = O_RDWR; |
62 |
else |
63 |
@@ -264,6 +281,19 @@ sio_oss_getfd(const char *str, unsigned |
64 |
DPERROR(path); |
65 |
return -1; |
66 |
} |
67 |
+ /* |
68 |
+ * Check if the device supports playing/recording. |
69 |
+ * Unfortunately, it's possible for devices to be opened RDWR |
70 |
+ * even when they don't support playing/recording. |
71 |
+ */ |
72 |
+ if (mode & SIO_PLAY && ioctl(fd, SNDCTL_DSP_GETOSPACE, &bi) < 0) { |
73 |
+ close(fd); |
74 |
+ return -1; |
75 |
+ } |
76 |
+ if (mode & SIO_REC && ioctl(fd, SNDCTL_DSP_GETISPACE, &bi) < 0) { |
77 |
+ close(fd); |
78 |
+ return -1; |
79 |
+ } |
80 |
val = 1; |
81 |
if (ioctl(fd, SNDCTL_DSP_LOW_WATER, &val) < 0) { |
82 |
DPERROR("sio_oss_start: LOW_WATER"); |
83 |
@@ -736,4 +766,40 @@ sio_oss_revents(struct sio_hdl *sh, stru |
84 |
return revents; |
85 |
} |
86 |
|
87 |
+static int |
88 |
+sio_oss_setvol(struct sio_hdl *sh, unsigned int vol) |
89 |
+{ |
90 |
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; |
91 |
+ int newvol; |
92 |
+ |
93 |
+ /* Scale to 0..100 */ |
94 |
+ newvol = 1.0 * 100 * vol / SIO_MAXVOL; |
95 |
+ newvol = newvol | (newvol << 8); |
96 |
+ |
97 |
+ if (ioctl(hdl->fd, SNDCTL_DSP_SETPLAYVOL, &newvol) < 0) { |
98 |
+ DPERROR("sio_oss_setvol"); |
99 |
+ hdl->sio.eof = 1; |
100 |
+ return 0; |
101 |
+ } |
102 |
+ |
103 |
+ return 1; |
104 |
+} |
105 |
+ |
106 |
+static void |
107 |
+sio_oss_getvol(struct sio_hdl *sh) |
108 |
+{ |
109 |
+ struct sio_oss_hdl *hdl = (struct sio_oss_hdl *)sh; |
110 |
+ int vol; |
111 |
+ |
112 |
+ if (ioctl(hdl->fd, SNDCTL_DSP_GETPLAYVOL, &vol) < 0) { |
113 |
+ DPERROR("sio_oss_getvol"); |
114 |
+ hdl->sio.eof = 1; |
115 |
+ return; |
116 |
+ } |
117 |
+ |
118 |
+ /* Use left channel volume and scale to SIO_MAXVOL */ |
119 |
+ vol = SIO_MAXVOL * 1.0 * (vol & 0x7f) / 100; |
120 |
+ _sio_onvol_cb(&hdl->sio, vol); |
121 |
+} |
122 |
+ |
123 |
#endif /* defined USE_OSS */ |