label lossless WMA as WMA3/Lossless
[soepkiptng.git] / src / soepkiptng_play / output_oss.c
blobb336ea0131aae99ccfc08f3588218cbb3615f403
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/ioctl.h>
9 #include <sys/soundcard.h>
10 #include <sys/stat.h>
12 #include "debug.h"
13 #include "buffer.h"
14 #include "polllib.h"
15 #include "output_oss.h"
17 #define BLKSIZE 4096
19 #ifndef AFMT_S32_LE
20 #define AFMT_S32_LE 0x00001000
21 #endif
22 #ifndef AFMT_S32_BE
23 #define AFMT_S32_BE 0x00002000
24 #endif
26 static char *oss_dev;
27 static int oss_fd;
28 static int oss_do_init;
29 static int oss_samplefreq;
30 static int oss_fmt;
31 int oss_intercept_resume;
33 static int ischardev(int fd)
35 struct stat st;
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)) {
48 set_fd_mask(fd, 0);
49 return;
52 if(oss_do_init) {
53 char buf[4096];
55 DEBUG("oss_do_init\n");
57 memset(buf, 0, sizeof(buf));
58 write(fd, buf, sizeof(buf));
60 oss_do_init = 0;
63 set_fd_mask(fd, POLLOUT);
66 static void output_oss_post(int fd, short events, long cookie)
68 int l;
70 l = buffer_length;
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);
78 if(l > 0) {
79 if((l = write(fd, buffer + buffer_start, l)) == -1) {
80 if(errno == EINTR || errno == EAGAIN) return;
81 perror("write");
82 exit(1);
85 buffer_length -= l;
86 buffer_start += l;
87 if(buffer_start >= buffer_size) {
88 buffer_start -= buffer_size;
90 byte_counter += l;
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;
96 song_counter++;
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) {
115 oss_dev = NULL;
116 } else {
117 oss_dev = dev;
119 oss_fd = -1;
120 oss_samplefreq = samplefreq;
121 switch(fmt_bits) {
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);
126 return 0;
129 int output_oss_start()
131 int i, retval;
132 audio_buf_info bi;
134 DEBUG("output_oss_start: oss_dev=%s\n", oss_dev);
136 if(oss_fd != -1) {
137 /* already started */
138 return 0;
141 if(oss_intercept_resume) {
142 oss_intercept_resume = 0;
143 return 0;
146 if(oss_dev) {
147 oss_fd = open(oss_dev, O_WRONLY | O_CREAT | O_TRUNC, 0666);
148 if(oss_fd < 0) {
149 perror(oss_dev);
150 return -1;
152 } else {
153 oss_fd = 1;
156 retval = ioctl(oss_fd, SNDCTL_DSP_SYNC, 0);
157 i = oss_fmt;
158 if(retval != -1) retval = ioctl(oss_fd, SNDCTL_DSP_SETFMT, &i);
159 i = 1;
160 if(retval != -1) retval = ioctl(oss_fd, SNDCTL_DSP_STEREO, &i);
161 i = oss_samplefreq;
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);
176 oss_do_init = 1;
178 return register_fd(oss_fd, output_oss_pre, output_oss_post, 0);
181 void output_oss_stop()
183 static char buf[8];
185 DEBUG("output_oss_stop\n");
187 output_oss_reset();
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));
191 close(oss_fd);
193 unregister_fd(oss_fd);
194 oss_fd = -1;
197 int output_oss_running()
199 return oss_fd != -1;
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()
216 int delay;
217 return ioctl(oss_fd, SNDCTL_DSP_GETODELAY, &delay) == 0? delay : 0;