Mercurial > mplayer.hg
annotate libao2/ao_oss.c @ 3639:64ee21b3bd09
Modified the sync code once again, commented out hardware pts sync (I'll likely burn in hell before understanding how to get this bastard to sync well)
Added automagic setup of aspect ratio, will remove the "aspect-bug" (I hope). As well as please you rich 16:9 doods ;)
author | mswitch |
---|---|
date | Thu, 20 Dec 2001 20:50:35 +0000 |
parents | 921a78c7b4aa |
children | f648f699eda6 |
rev | line source |
---|---|
954 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 | |
4 #include <sys/ioctl.h> | |
5 #include <unistd.h> | |
6 #include <sys/time.h> | |
7 #include <sys/types.h> | |
8 #include <sys/stat.h> | |
9 #include <fcntl.h> | |
1532 | 10 //#include <sys/soundcard.h> |
954 | 11 |
12 #include "../config.h" | |
13 | |
1532 | 14 #include "afmt.h" |
15 | |
954 | 16 #include "audio_out.h" |
17 #include "audio_out_internal.h" | |
18 | |
1191 | 19 extern int verbose; |
20 | |
954 | 21 static ao_info_t info = |
22 { | |
23 "OSS/ioctl audio output", | |
956
a6cecd9a1bad
'-ao' switch (including '-ao help'), fixing Arpi's bug (short name 'null' for both of oss and null driver ;)
lgb
parents:
954
diff
changeset
|
24 "oss", |
954 | 25 "A'rpi", |
26 "" | |
27 }; | |
28 | |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
29 /* Support for >2 output channels added 2001-11-25 - Steve Davies <steve@daviesfam.org> */ |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
30 |
954 | 31 LIBAO_EXTERN(oss) |
32 | |
1020
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
33 static char *dsp="/dev/dsp"; |
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
34 static audio_buf_info zz; |
954 | 35 static int audio_fd=-1; |
36 | |
1191 | 37 char *oss_mixer_device = "/dev/mixer"; |
38 int oss_mixer_usemaster = 0; | |
39 | |
954 | 40 // to set/get/query special features/parameters |
41 static int control(int cmd,int arg){ | |
42 switch(cmd){ | |
43 case AOCONTROL_SET_DEVICE: | |
44 dsp=(char*)arg; | |
45 return CONTROL_OK; | |
46 case AOCONTROL_QUERY_FORMAT: | |
47 return CONTROL_TRUE; | |
1191 | 48 case AOCONTROL_GET_VOLUME: |
49 case AOCONTROL_SET_VOLUME: | |
50 { | |
51 ao_control_vol_t *vol = (ao_control_vol_t *)arg; | |
52 int fd, v, mcmd, devs; | |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
53 |
3095 | 54 if(ao_data.format == AFMT_AC3) |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
55 return CONTROL_TRUE; |
1191 | 56 |
57 if ((fd = open("/dev/mixer", O_RDONLY)) > 0) | |
58 { | |
59 ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devs); | |
60 if ((devs & SOUND_MASK_PCM) && (oss_mixer_usemaster == 0)) | |
61 if (cmd == AOCONTROL_GET_VOLUME) | |
62 mcmd = SOUND_MIXER_READ_PCM; | |
63 else | |
64 mcmd = SOUND_MIXER_WRITE_PCM; | |
65 else if ((devs & SOUND_MASK_VOLUME) && (oss_mixer_usemaster == 1)) | |
66 if (cmd == AOCONTROL_GET_VOLUME) | |
67 mcmd = SOUND_MIXER_READ_VOLUME; | |
68 else | |
69 mcmd = SOUND_MIXER_WRITE_VOLUME; | |
70 else | |
71 { | |
72 close(fd); | |
73 return CONTROL_ERROR; | |
74 } | |
75 | |
76 if (cmd == AOCONTROL_GET_VOLUME) | |
77 { | |
78 ioctl(fd, cmd, &v); | |
79 vol->right = (v & 0xFF00) >> 8; | |
80 vol->left = v & 0x00FF; | |
81 } | |
82 else | |
83 { | |
84 v = ((int)vol->right << 8) | (int)vol->left; | |
85 ioctl(fd, cmd, &v); | |
86 } | |
87 close(fd); | |
88 return CONTROL_OK; | |
89 } | |
90 } | |
91 return CONTROL_ERROR; | |
954 | 92 } |
93 return CONTROL_UNKNOWN; | |
94 } | |
95 | |
96 // open & setup audio device | |
97 // return: 1=success 0=fail | |
98 static int init(int rate,int channels,int format,int flags){ | |
99 | |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
100 printf("ao2: %d Hz %d chans %s\n",rate,channels, |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
101 audio_out_format_name(format)); |
954 | 102 |
1191 | 103 if (ao_subdevice) |
104 dsp = ao_subdevice; | |
105 | |
106 if (verbose) | |
107 printf("audio_setup: using '%s' dsp device\n", dsp); | |
108 | |
954 | 109 audio_fd=open(dsp, O_WRONLY); |
110 if(audio_fd<0){ | |
111 printf("Can't open audio device %s -> nosound\n",dsp); | |
112 return 0; | |
113 } | |
114 | |
3137 | 115 ao_data.bps=channels*rate; |
3095 | 116 if(format != AFMT_U8 && format != AFMT_S8) |
117 ao_data.bps*=2; | |
118 | |
119 ao_data.format=format; | |
120 ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_data.format); | |
121 if(format == AFMT_AC3 && ao_data.format != AFMT_AC3) { | |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
122 printf("Can't set audio device %s to AC3 output\n", dsp); |
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
123 return 0; |
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
124 } |
1079 | 125 printf("audio_setup: sample format: %s (requested: %s)\n", |
3095 | 126 audio_out_format_name(ao_data.format), audio_out_format_name(format)); |
954 | 127 |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
128 if(format != AFMT_AC3) { |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
129 // We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
130 ao_data.channels = channels; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
131 if (ao_data.channels > 2) { |
3319
66134af21278
fixed to check that SNDCTL_DSP_CHANNELS actually grants the requested number of channels
steve
parents:
3181
diff
changeset
|
132 if ( ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &ao_data.channels) == -1 || |
66134af21278
fixed to check that SNDCTL_DSP_CHANNELS actually grants the requested number of channels
steve
parents:
3181
diff
changeset
|
133 ao_data.channels != channels ) { |
66134af21278
fixed to check that SNDCTL_DSP_CHANNELS actually grants the requested number of channels
steve
parents:
3181
diff
changeset
|
134 printf("audio_setup: Failed to set audio device to %d channels\n", channels); |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
135 return 0; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
136 } |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
137 } |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
138 else { |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
139 int c = ao_data.channels-1; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
140 if (ioctl (audio_fd, SNDCTL_DSP_STEREO, &c) == -1) { |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
141 printf("audio_setup: Failed to set audio device to %d channels\n", ao_data.channels); |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
142 return 0; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
143 } |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
144 } |
3319
66134af21278
fixed to check that SNDCTL_DSP_CHANNELS actually grants the requested number of channels
steve
parents:
3181
diff
changeset
|
145 printf("audio_setup: using %d channels (requested: %d)\n", ao_data.channels, channels); |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
146 // set rate |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
147 ao_data.samplerate=rate; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
148 ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate); |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
149 printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_data.samplerate,rate); |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
150 } |
954 | 151 |
152 if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){ | |
153 int r=0; | |
154 printf("audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n"); | |
155 if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r)==-1){ | |
3095 | 156 printf("audio_setup: %d bytes/frag (config.h)\n",ao_data.outburst); |
954 | 157 } else { |
3095 | 158 ao_data.outburst=r; |
159 printf("audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_data.outburst); | |
954 | 160 } |
161 } else { | |
162 printf("audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n", | |
163 zz.fragments, zz.fragstotal, zz.fragsize, zz.bytes); | |
3095 | 164 if(ao_data.buffersize==-1) ao_data.buffersize=zz.bytes; |
165 ao_data.outburst=zz.fragsize; | |
954 | 166 } |
167 | |
3095 | 168 if(ao_data.buffersize==-1){ |
954 | 169 // Measuring buffer size: |
170 void* data; | |
3095 | 171 ao_data.buffersize=0; |
954 | 172 #ifdef HAVE_AUDIO_SELECT |
3095 | 173 data=malloc(ao_data.outburst); memset(data,0,ao_data.outburst); |
174 while(ao_data.buffersize<0x40000){ | |
954 | 175 fd_set rfds; |
176 struct timeval tv; | |
177 FD_ZERO(&rfds); FD_SET(audio_fd,&rfds); | |
178 tv.tv_sec=0; tv.tv_usec = 0; | |
179 if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break; | |
3095 | 180 write(audio_fd,data,ao_data.outburst); |
181 ao_data.buffersize+=ao_data.outburst; | |
954 | 182 } |
183 free(data); | |
3095 | 184 if(ao_data.buffersize==0){ |
954 | 185 printf("\n *** Your audio driver DOES NOT support select() ***\n"); |
186 printf("Recompile mplayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n"); | |
187 return 0; | |
188 } | |
189 #endif | |
190 } | |
191 | |
192 return 1; | |
193 } | |
194 | |
195 // close audio device | |
196 static void uninit(){ | |
1020
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
197 #ifdef SNDCTL_DSP_RESET |
954 | 198 ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); |
1020
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
199 #endif |
954 | 200 close(audio_fd); |
201 } | |
202 | |
203 // stop playing and empty buffers (for seeking/pause) | |
204 static void reset(){ | |
205 uninit(); | |
206 audio_fd=open(dsp, O_WRONLY); | |
207 if(audio_fd<0){ | |
208 printf("\nFatal error: *** CANNOT RE-OPEN / RESET AUDIO DEVICE ***\n"); | |
209 return; | |
210 } | |
211 | |
3095 | 212 ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_data.format); |
213 if(ao_data.format != AFMT_AC3) { | |
3181
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
214 if (ao_data.channels > 2) |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
215 ioctl (audio_fd, SNDCTL_DSP_CHANNELS, &ao_data.channels); |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
216 else { |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
217 int c = ao_data.channels-1; |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
218 ioctl (audio_fd, SNDCTL_DSP_STEREO, &c); |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
219 } |
c8edb0691f09
Extended oss output driver and libac3 to support 4 and 6 channel output mixes. added -channels command line option
steve
parents:
3137
diff
changeset
|
220 ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_data.samplerate); |
1528
a444bd456fcc
ac3/spdif patch by German Gomez Garcia <german@piraos.com>
arpi
parents:
1456
diff
changeset
|
221 } |
954 | 222 } |
223 | |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
224 // stop playing, keep buffers (for pause) |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
225 static void audio_pause() |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
226 { |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
227 // for now, just call reset(); |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
228 reset(); |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
229 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
230 |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
231 // resume playing, after audio_pause() |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
232 static void audio_resume() |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
233 { |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
234 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
235 |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
1020
diff
changeset
|
236 |
954 | 237 // return: how many bytes can be played without blocking |
238 static int get_space(){ | |
3095 | 239 int playsize=ao_data.outburst; |
954 | 240 |
1020
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
241 #ifdef SNDCTL_DSP_GETOSPACE |
954 | 242 if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1){ |
243 // calculate exact buffer space: | |
3455
921a78c7b4aa
limit get_space return <= MAX_OUTBURST, whilst always an exact number of fragments
steve
parents:
3319
diff
changeset
|
244 playsize = zz.fragments*zz.fragsize; |
921a78c7b4aa
limit get_space return <= MAX_OUTBURST, whilst always an exact number of fragments
steve
parents:
3319
diff
changeset
|
245 if (playsize > MAX_OUTBURST) |
921a78c7b4aa
limit get_space return <= MAX_OUTBURST, whilst always an exact number of fragments
steve
parents:
3319
diff
changeset
|
246 playsize = (MAX_OUTBURST / zz.fragsize) * zz.fragsize; |
921a78c7b4aa
limit get_space return <= MAX_OUTBURST, whilst always an exact number of fragments
steve
parents:
3319
diff
changeset
|
247 return playsize; |
954 | 248 } |
1020
72cacd3b8f30
Solaris 8 support - patch by Marcus Comstedt <marcus@idonex.se>
arpi_esp
parents:
956
diff
changeset
|
249 #endif |
954 | 250 |
251 // check buffer | |
252 #ifdef HAVE_AUDIO_SELECT | |
253 { fd_set rfds; | |
254 struct timeval tv; | |
255 FD_ZERO(&rfds); | |
256 FD_SET(audio_fd, &rfds); | |
257 tv.tv_sec = 0; | |
258 tv.tv_usec = 0; | |
259 if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) return 0; // not block! | |
260 } | |
261 #endif | |
262 | |
3095 | 263 return ao_data.outburst; |
954 | 264 } |
265 | |
266 // plays 'len' bytes of 'data' | |
267 // it should round it down to outburst*n | |
268 // return: number of bytes played | |
269 static int play(void* data,int len,int flags){ | |
3095 | 270 len/=ao_data.outburst; |
271 len=write(audio_fd,data,len*ao_data.outburst); | |
954 | 272 return len; |
273 } | |
274 | |
275 static int audio_delay_method=2; | |
276 | |
3095 | 277 // return: delay in seconds between first and last sample in buffer |
278 static float get_delay(){ | |
279 /* Calculate how many bytes/second is sent out */ | |
954 | 280 if(audio_delay_method==2){ |
281 int r=0; | |
282 if(ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &r)!=-1) | |
3095 | 283 return ((float)r)/(float)ao_data.bps; |
954 | 284 audio_delay_method=1; // fallback if not supported |
285 } | |
286 if(audio_delay_method==1){ | |
287 // SNDCTL_DSP_GETOSPACE | |
288 if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1) | |
3095 | 289 return ((float)(ao_data.buffersize-zz.bytes))/(float)ao_data.bps; |
954 | 290 audio_delay_method=0; // fallback if not supported |
291 } | |
3095 | 292 return ((float)ao_data.buffersize)/(float)ao_data.bps; |
954 | 293 } |