2 * Copyright 2004-2005 Timo Hirvonen
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #if defined(__OpenBSD__)
26 #include <soundcard.h>
28 #include <sys/soundcard.h>
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
36 static sample_format_t oss_sf
;
37 static int oss_fd
= -1;
40 static char *oss_dsp_device
= NULL
;
42 static int oss_close(void);
44 static int oss_reset(void)
46 if (fcntl(oss_fd
, SNDCTL_DSP_RESET
, 0) == -1) {
52 static int oss_set_sf(sample_format_t sf
)
54 int tmp
, log2_fragment_size
, nr_fragments
, bytes_per_second
;
58 tmp
= sf_get_channels(oss_sf
) - 1;
59 if (ioctl(oss_fd
, SNDCTL_DSP_STEREO
, &tmp
) == -1) {
60 d_print("SNDCTL_DSP_STEREO failed: %s\n", strerror(errno
));
63 if (sf_get_bits(oss_sf
) == 16) {
64 if (sf_get_signed(oss_sf
)) {
65 if (sf_get_bigendian(oss_sf
)) {
71 if (sf_get_bigendian(oss_sf
)) {
77 } else if (sf_get_bits(oss_sf
) == 8) {
78 if (sf_get_signed(oss_sf
)) {
84 d_print("bits is neither 8 nor 16\n");
87 if (ioctl(oss_fd
, SNDCTL_DSP_SAMPLESIZE
, &tmp
) == -1) {
88 d_print("SNDCTL_DSP_SAMPLESIZE failed: %s\n", strerror(errno
));
91 tmp
= sf_get_rate(oss_sf
);
92 if (ioctl(oss_fd
, SNDCTL_DSP_SPEED
, &tmp
) == -1) {
93 d_print("SNDCTL_DSP_SPEED failed: %s\n", strerror(errno
));
97 bytes_per_second
= sf_get_second_size(oss_sf
);
98 log2_fragment_size
= 0;
99 while (1 << log2_fragment_size
< bytes_per_second
/ 25)
100 log2_fragment_size
++;
101 log2_fragment_size
--;
103 /* device_buffer_size = (1 << log2_fragment_size) * (nr_fragments + 1); */
104 /* bits 0..15 = size of fragment, 16..31 = log2(number of fragments) */
105 tmp
= (nr_fragments
<< 16) + log2_fragment_size
;
106 d_print("fragment: %d\n", tmp
);
107 if (ioctl(oss_fd
, SNDCTL_DSP_SETFRAGMENT
, &tmp
) == -1) {
108 d_print("fragment: %d\n", tmp
);
109 d_print("SNDCTL_DSP_SETFRAGMENT failed: %s\n", strerror(errno
));
116 static int oss_device_exists(const char *device
)
120 if (stat(device
, &s
) == 0) {
121 d_print("device %s exists\n", device
);
124 d_print("device %s does not exist\n", device
);
128 static int oss_init(void)
130 const char *new_dsp_dev
= "/dev/sound/dsp";
131 const char *dsp_dev
= "/dev/dsp";
133 if (oss_dsp_device
) {
134 if (oss_device_exists(oss_dsp_device
))
136 free(oss_dsp_device
);
137 oss_dsp_device
= NULL
;
140 if (oss_device_exists(new_dsp_dev
)) {
141 oss_dsp_device
= xstrdup(new_dsp_dev
);
144 if (oss_device_exists(dsp_dev
)) {
145 oss_dsp_device
= xstrdup(dsp_dev
);
151 static int oss_exit(void)
153 free(oss_dsp_device
);
154 oss_dsp_device
= NULL
;
158 static int oss_open(sample_format_t sf
)
160 oss_fd
= open(oss_dsp_device
, O_WRONLY
);
163 if (oss_set_sf(sf
) == -1) {
170 static int oss_close(void)
177 static int oss_write(const char *buffer
, int count
)
183 rc
= write(oss_fd
, buffer
, count
);
187 static int oss_pause(void)
189 if (ioctl(oss_fd
, SNDCTL_DSP_POST
, NULL
) == -1)
194 static int oss_unpause(void)
199 static int oss_buffer_space(void)
204 if (ioctl(oss_fd
, SNDCTL_DSP_GETOSPACE
, &info
) == -1)
207 /* d_print("%d\n", space); */
211 static int op_oss_set_option(int key
, const char *val
)
215 free(oss_dsp_device
);
216 oss_dsp_device
= xstrdup(val
);
219 return -OP_ERROR_NOT_OPTION
;
224 static int op_oss_get_option(int key
, char **val
)
229 *val
= xstrdup(oss_dsp_device
);
232 return -OP_ERROR_NOT_OPTION
;
237 const struct output_plugin_ops op_pcm_ops
= {
244 .unpause
= oss_unpause
,
245 .buffer_space
= oss_buffer_space
,
246 .set_option
= op_oss_set_option
,
247 .get_option
= op_oss_get_option
250 const char * const op_pcm_options
[] = {
255 const int op_priority
= 1;