9 #include <sys/soundcard.h>
15 #include "output_oss.h"
20 #define AFMT_S32_LE 0x00001000
23 #define AFMT_S32_BE 0x00002000
28 static int oss_do_init
;
29 static int oss_samplefreq
;
31 int oss_intercept_resume
;
33 static int ischardev(int fd
)
37 if(fstat(fd
, &st
) == -1) return 0;
38 return S_ISCHR(st
.st_mode
);
41 static void output_oss_post(int fd
, short events
, long cookie
);
43 static void output_oss_pre(int fd
, long cookie
)
45 DDEBUG("output_oss_pre: length=%d oss_do_init=%d\n", buffer_length
, oss_do_init
);
47 if(buffer_length
< (oss_do_init
? oss_samplefreq
* 4 : 1)) {
55 DEBUG("oss_do_init\n");
57 memset(buf
, 0, sizeof(buf
));
58 write(fd
, buf
, sizeof(buf
));
63 set_fd_mask(fd
, POLLOUT
);
66 static void output_oss_post(int fd
, short events
, long cookie
)
71 if(l
> BLKSIZE
) l
= BLKSIZE
;
72 if(l
+ buffer_start
> buffer_size
) {
73 l
= buffer_size
- buffer_start
;
76 DDEBUG("output_oss_post: start=%6d lenght=%d, writing %d bytes\n", buffer_start
, buffer_length
, l
);
79 if((l
= write(fd
, buffer
+ buffer_start
, l
)) == -1) {
80 if(errno
== EINTR
|| errno
== EAGAIN
) return;
87 if(buffer_start
>= buffer_size
) {
88 buffer_start
-= buffer_size
;
91 if(byte_counter_resetcountdown
) {
92 byte_counter_resetcountdown
-= l
;
93 if(byte_counter_resetcountdown
<= 0) {
94 byte_counter
= -byte_counter_resetcountdown
;
95 byte_counter_resetcountdown
= 0;
101 DDEBUG("output_oss_post: start=%6d length=%d\n", buffer_start
, buffer_length
);
103 /* flush data in soundcard driver if we are out of data */
104 if(buffer_length
== 0) {
105 DEBUG("output_oss_post: DSP_POST\n");
106 ioctl(fd
, SNDCTL_DSP_POST
, 0);
110 int output_oss_init(char *dev
, int samplefreq
, int fmt_bits
)
112 DEBUG("output_oss_init: dev=%s\n", dev
);
114 if(strcmp(dev
, "-") == 0) {
120 oss_samplefreq
= samplefreq
;
122 case 16: oss_fmt
= AFMT_S16_LE
; break;
123 case 32: oss_fmt
= AFMT_S32_LE
; break;
124 default: fprintf(stderr
, "oss: %d bits not supported\n", fmt_bits
); exit(1);
129 int output_oss_start()
134 DEBUG("output_oss_start: oss_dev=%s\n", oss_dev
);
137 /* already started */
141 if(oss_intercept_resume
) {
142 oss_intercept_resume
= 0;
147 oss_fd
= open(oss_dev
, O_WRONLY
| O_CREAT
| O_TRUNC
, 0666);
156 retval
= ioctl(oss_fd
, SNDCTL_DSP_SYNC
, 0);
158 if(retval
!= -1) retval
= ioctl(oss_fd
, SNDCTL_DSP_SETFMT
, &i
);
160 if(retval
!= -1) retval
= ioctl(oss_fd
, SNDCTL_DSP_STEREO
, &i
);
162 if(retval
!= -1) retval
= ioctl(oss_fd
, SNDCTL_DSP_SPEED
, &i
);
164 if(retval
== -1 && ischardev(oss_fd
)) {
165 fprintf(stderr
, "warning: sound ioctls failed\n");
168 if(i
!= oss_samplefreq
)
169 fprintf(stderr
, "WARNING: wanted samplefreq %d, got %d\n", oss_samplefreq
, i
);
171 if(ioctl(oss_fd
, SNDCTL_DSP_GETOSPACE
, &bi
) == 0) {
172 fprintf(stderr
, "ospace: frags=%d fragstotal=%d fragsize=%d bytes=%d\n",
173 bi
.fragments
, bi
.fragstotal
, bi
.fragsize
, bi
.bytes
);
178 return register_fd(oss_fd
, output_oss_pre
, output_oss_post
, 0);
181 void output_oss_stop()
185 DEBUG("output_oss_stop\n");
189 /* write 1 or 2 samples to prevent badly designed cards to keep the DC value of the last sample */
190 write(oss_fd
, buf
, sizeof(buf
));
193 unregister_fd(oss_fd
);
197 int output_oss_running()
202 int output_oss_bytespersecond()
204 return oss_samplefreq
* ((oss_fmt
== AFMT_S32_LE
)? 8 : 4);
207 void output_oss_reset()
209 if(ioctl(oss_fd
, SNDCTL_DSP_RESET
, NULL
) < 0) {
210 perror("SNDCTL_DSP_RESET");
214 int output_oss_get_odelay()
217 return ioctl(oss_fd
, SNDCTL_DSP_GETODELAY
, &delay
) == 0? delay
: 0;