18 #ifdef HAVE_SYS_SOUNDCARD_H
19 #include <sys/soundcard.h>
21 #ifdef HAVE_SOUNDCARD_H
22 #include <soundcard.h>
26 #include "libaf/af_format.h"
28 #include "audio_out.h"
29 #include "audio_out_internal.h"
31 static ao_info_t info
=
33 "OSS/ioctl audio output",
39 /* Support for >2 output channels added 2001-11-25 - Steve Davies <steve@daviesfam.org> */
43 static int format2oss(int format
)
47 case AF_FORMAT_U8
: return AFMT_U8
;
48 case AF_FORMAT_S8
: return AFMT_S8
;
49 case AF_FORMAT_U16_LE
: return AFMT_U16_LE
;
50 case AF_FORMAT_U16_BE
: return AFMT_U16_BE
;
51 case AF_FORMAT_S16_LE
: return AFMT_S16_LE
;
52 case AF_FORMAT_S16_BE
: return AFMT_S16_BE
;
54 case AF_FORMAT_U24_LE
: return AFMT_U24_LE
;
57 case AF_FORMAT_U24_BE
: return AFMT_U24_BE
;
60 case AF_FORMAT_S24_LE
: return AFMT_S24_LE
;
63 case AF_FORMAT_S24_BE
: return AFMT_S24_BE
;
66 case AF_FORMAT_U32_LE
: return AFMT_U32_LE
;
69 case AF_FORMAT_U32_BE
: return AFMT_U32_BE
;
72 case AF_FORMAT_S32_LE
: return AFMT_S32_LE
;
75 case AF_FORMAT_S32_BE
: return AFMT_S32_BE
;
78 case AF_FORMAT_FLOAT_NE
: return AFMT_FLOAT
;
81 case AF_FORMAT_MU_LAW
: return AFMT_MU_LAW
;
82 case AF_FORMAT_A_LAW
: return AFMT_A_LAW
;
83 case AF_FORMAT_IMA_ADPCM
: return AFMT_IMA_ADPCM
;
85 case AF_FORMAT_MPEG2
: return AFMT_MPEG
;
88 case AF_FORMAT_AC3
: return AFMT_AC3
;
91 mp_msg(MSGT_AO
, MSGL_V
, "OSS: Unknown/not supported internal format: %s\n", af_fmt2str_short(format
));
95 static int oss2format(int format
)
99 case AFMT_U8
: return AF_FORMAT_U8
;
100 case AFMT_S8
: return AF_FORMAT_S8
;
101 case AFMT_U16_LE
: return AF_FORMAT_U16_LE
;
102 case AFMT_U16_BE
: return AF_FORMAT_U16_BE
;
103 case AFMT_S16_LE
: return AF_FORMAT_S16_LE
;
104 case AFMT_S16_BE
: return AF_FORMAT_S16_BE
;
106 case AFMT_U24_LE
: return AF_FORMAT_U24_LE
;
109 case AFMT_U24_BE
: return AF_FORMAT_U24_BE
;
112 case AFMT_S24_LE
: return AF_FORMAT_S24_LE
;
115 case AFMT_S24_BE
: return AF_FORMAT_S24_BE
;
118 case AFMT_U32_LE
: return AF_FORMAT_U32_LE
;
121 case AFMT_U32_BE
: return AF_FORMAT_U32_BE
;
124 case AFMT_S32_LE
: return AF_FORMAT_S32_LE
;
127 case AFMT_S32_BE
: return AF_FORMAT_S32_BE
;
130 case AFMT_FLOAT
: return AF_FORMAT_FLOAT_NE
;
133 case AFMT_MU_LAW
: return AF_FORMAT_MU_LAW
;
134 case AFMT_A_LAW
: return AF_FORMAT_A_LAW
;
135 case AFMT_IMA_ADPCM
: return AF_FORMAT_IMA_ADPCM
;
137 case AFMT_MPEG
: return AF_FORMAT_MPEG2
;
140 case AFMT_AC3
: return AF_FORMAT_AC3
;
143 mp_msg(MSGT_GLOBAL
,MSGL_ERR
,MSGTR_AO_OSS_UnknownUnsupportedFormat
, format
);
147 static char *dsp
=PATH_DEV_DSP
;
148 static audio_buf_info zz
;
149 static int audio_fd
=-1;
150 static int prepause_space
;
152 static const char *oss_mixer_device
= PATH_DEV_MIXER
;
153 static int oss_mixer_channel
= SOUND_MIXER_PCM
;
155 // to set/get/query special features/parameters
156 static int control(int cmd
,void *arg
){
158 case AOCONTROL_SET_DEVICE
:
161 case AOCONTROL_GET_DEVICE
:
164 #ifdef SNDCTL_DSP_GETFMTS
165 case AOCONTROL_QUERY_FORMAT
:
168 if (!ioctl(audio_fd
, SNDCTL_DSP_GETFMTS
, &format
))
169 if (format
& (int)arg
)
171 return CONTROL_FALSE
;
174 case AOCONTROL_GET_VOLUME
:
175 case AOCONTROL_SET_VOLUME
:
177 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
180 if(ao_data
.format
== AF_FORMAT_AC3
)
183 if ((fd
= open(oss_mixer_device
, O_RDONLY
)) > 0)
185 ioctl(fd
, SOUND_MIXER_READ_DEVMASK
, &devs
);
186 if (devs
& (1 << oss_mixer_channel
))
188 if (cmd
== AOCONTROL_GET_VOLUME
)
190 ioctl(fd
, MIXER_READ(oss_mixer_channel
), &v
);
191 vol
->right
= (v
& 0xFF00) >> 8;
192 vol
->left
= v
& 0x00FF;
196 v
= ((int)vol
->right
<< 8) | (int)vol
->left
;
197 ioctl(fd
, MIXER_WRITE(oss_mixer_channel
), &v
);
203 return CONTROL_ERROR
;
209 return CONTROL_ERROR
;
211 return CONTROL_UNKNOWN
;
214 // open & setup audio device
215 // return: 1=success 0=fail
216 static int init(int rate
,int channels
,int format
,int flags
){
217 char *mixer_channels
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
219 char *mdev
= mixer_device
, *mchan
= mixer_channel
;
221 mp_msg(MSGT_AO
,MSGL_V
,"ao2: %d Hz %d chans %s\n",rate
,channels
,
222 af_fmt2str_short(format
));
226 m
= strchr(ao_subdevice
,':');
240 oss_mixer_device
=mdev
;
242 oss_mixer_device
=PATH_DEV_MIXER
;
247 if ((fd
= open(oss_mixer_device
, O_RDONLY
)) == -1){
248 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantOpenMixer
,
249 oss_mixer_device
, strerror(errno
));
251 ioctl(fd
, SOUND_MIXER_READ_DEVMASK
, &devs
);
254 for (i
=0; i
<SOUND_MIXER_NRDEVICES
; i
++){
255 if(!strcasecmp(mixer_channels
[i
], mchan
)){
256 if(!(devs
& (1 << i
))){
257 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_ChanNotFound
,mchan
);
258 i
= SOUND_MIXER_NRDEVICES
+1;
261 oss_mixer_channel
= i
;
265 if(i
==SOUND_MIXER_NRDEVICES
){
266 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_ChanNotFound
,mchan
);
270 oss_mixer_channel
= SOUND_MIXER_PCM
;
272 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' dsp device\n", dsp
);
273 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' mixer device\n", oss_mixer_device
);
274 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' mixer device\n", mixer_channels
[oss_mixer_channel
]);
277 audio_fd
=open(dsp
, O_WRONLY
| O_NONBLOCK
);
279 audio_fd
=open(dsp
, O_WRONLY
);
282 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantOpenDev
, dsp
, strerror(errno
));
287 /* Remove the non-blocking flag */
288 if(fcntl(audio_fd
, F_SETFL
, 0) < 0) {
289 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantMakeFd
, strerror(errno
));
294 #if defined(FD_CLOEXEC) && defined(F_SETFD)
295 fcntl(audio_fd
, F_SETFD
, FD_CLOEXEC
);
298 if(format
== AF_FORMAT_AC3
) {
299 ao_data
.samplerate
=rate
;
300 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
304 ao_data
.format
=format
;
305 oss_format
=format2oss(format
);
306 if (oss_format
== -1) {
307 #ifdef WORDS_BIGENDIAN
308 oss_format
=AFMT_S16_BE
;
310 oss_format
=AFMT_S16_LE
;
312 format
=AF_FORMAT_S16_NE
;
314 if( ioctl(audio_fd
, SNDCTL_DSP_SETFMT
, &oss_format
)<0 ||
315 oss_format
!= format2oss(format
)) {
316 mp_msg(MSGT_AO
,MSGL_WARN
, MSGTR_AO_OSS_CantSet
, dsp
,
317 af_fmt2str_short(format
), af_fmt2str_short(AF_FORMAT_S16_NE
) );
318 format
=AF_FORMAT_S16_NE
;
322 if(oss_format
!=format2oss(format
))
323 mp_msg(MSGT_AO
,MSGL_WARN
,"WARNING! Your soundcard does NOT support %s sample format! Broken audio or bad playback speed are possible! Try with '-af format'\n",audio_out_format_name(format
));
326 ao_data
.format
= oss2format(oss_format
);
327 if (ao_data
.format
== -1) return 0;
329 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: sample format: %s (requested: %s)\n",
330 af_fmt2str_short(ao_data
.format
), af_fmt2str_short(format
));
332 ao_data
.channels
= channels
;
333 if(format
!= AF_FORMAT_AC3
) {
334 // We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
335 if (ao_data
.channels
> 2) {
336 if ( ioctl(audio_fd
, SNDCTL_DSP_CHANNELS
, &ao_data
.channels
) == -1 ||
337 ao_data
.channels
!= channels
) {
338 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantSetChans
, channels
);
343 int c
= ao_data
.channels
-1;
344 if (ioctl (audio_fd
, SNDCTL_DSP_STEREO
, &c
) == -1) {
345 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantSetChans
, ao_data
.channels
);
348 ao_data
.channels
=c
+1;
350 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using %d channels (requested: %d)\n", ao_data
.channels
, channels
);
352 ao_data
.samplerate
=rate
;
353 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
354 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using %d Hz samplerate (requested: %d)\n",ao_data
.samplerate
,rate
);
357 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)==-1){
359 mp_msg(MSGT_AO
,MSGL_WARN
,MSGTR_AO_OSS_CantUseGetospace
);
360 if(ioctl(audio_fd
, SNDCTL_DSP_GETBLKSIZE
, &r
)==-1){
361 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: %d bytes/frag (config.h)\n",ao_data
.outburst
);
364 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_data
.outburst
);
367 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n",
368 zz
.fragments
, zz
.fragstotal
, zz
.fragsize
, zz
.bytes
);
369 if(ao_data
.buffersize
==-1) ao_data
.buffersize
=zz
.bytes
;
370 ao_data
.outburst
=zz
.fragsize
;
373 if(ao_data
.buffersize
==-1){
374 // Measuring buffer size:
376 ao_data
.buffersize
=0;
377 #ifdef HAVE_AUDIO_SELECT
378 data
=malloc(ao_data
.outburst
); memset(data
,0,ao_data
.outburst
);
379 while(ao_data
.buffersize
<0x40000){
382 FD_ZERO(&rfds
); FD_SET(audio_fd
,&rfds
);
383 tv
.tv_sec
=0; tv
.tv_usec
= 0;
384 if(!select(audio_fd
+1, NULL
, &rfds
, NULL
, &tv
)) break;
385 write(audio_fd
,data
,ao_data
.outburst
);
386 ao_data
.buffersize
+=ao_data
.outburst
;
389 if(ao_data
.buffersize
==0){
390 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantUseSelect
);
396 ao_data
.bps
=ao_data
.channels
;
397 if(ao_data
.format
!= AF_FORMAT_U8
&& ao_data
.format
!= AF_FORMAT_S8
)
400 ao_data
.outburst
-=ao_data
.outburst
% ao_data
.bps
; // round down
401 ao_data
.bps
*=ao_data
.samplerate
;
406 // close audio device
407 static void uninit(int immed
){
408 if(audio_fd
== -1) return;
409 #ifdef SNDCTL_DSP_SYNC
410 // to get the buffer played
412 ioctl(audio_fd
, SNDCTL_DSP_SYNC
, NULL
);
414 #ifdef SNDCTL_DSP_RESET
416 ioctl(audio_fd
, SNDCTL_DSP_RESET
, NULL
);
422 // stop playing and empty buffers (for seeking/pause)
423 static void reset(void){
426 audio_fd
=open(dsp
, O_WRONLY
);
428 mp_msg(MSGT_AO
,MSGL_ERR
,MSGTR_AO_OSS_CantReopen
, strerror(errno
));
432 #if defined(FD_CLOEXEC) && defined(F_SETFD)
433 fcntl(audio_fd
, F_SETFD
, FD_CLOEXEC
);
436 oss_format
= format2oss(ao_data
.format
);
437 ioctl (audio_fd
, SNDCTL_DSP_SETFMT
, &oss_format
);
438 if(ao_data
.format
!= AF_FORMAT_AC3
) {
439 if (ao_data
.channels
> 2)
440 ioctl (audio_fd
, SNDCTL_DSP_CHANNELS
, &ao_data
.channels
);
442 int c
= ao_data
.channels
-1;
443 ioctl (audio_fd
, SNDCTL_DSP_STEREO
, &c
);
445 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
449 // stop playing, keep buffers (for pause)
450 static void audio_pause(void)
452 prepause_space
= get_space();
456 // resume playing, after audio_pause()
457 static void audio_resume(void)
461 fillcnt
= get_space() - prepause_space
;
463 void *silence
= calloc(fillcnt
, 1);
464 play(silence
, fillcnt
, 0);
470 // return: how many bytes can be played without blocking
471 static int get_space(void){
472 int playsize
=ao_data
.outburst
;
474 #ifdef SNDCTL_DSP_GETOSPACE
475 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)!=-1){
476 // calculate exact buffer space:
477 playsize
= zz
.fragments
*zz
.fragsize
;
478 if (playsize
> MAX_OUTBURST
)
479 playsize
= (MAX_OUTBURST
/ zz
.fragsize
) * zz
.fragsize
;
485 #ifdef HAVE_AUDIO_SELECT
489 FD_SET(audio_fd
, &rfds
);
492 if(!select(audio_fd
+1, NULL
, &rfds
, NULL
, &tv
)) return 0; // not block!
496 return ao_data
.outburst
;
499 // plays 'len' bytes of 'data'
500 // it should round it down to outburst*n
501 // return: number of bytes played
502 static int play(void* data
,int len
,int flags
){
505 if(len
>ao_data
.outburst
|| !(flags
& AOPLAY_FINAL_CHUNK
)) {
506 len
/=ao_data
.outburst
;
507 len
*=ao_data
.outburst
;
509 len
=write(audio_fd
,data
,len
);
513 static int audio_delay_method
=2;
515 // return: delay in seconds between first and last sample in buffer
516 static float get_delay(void){
517 /* Calculate how many bytes/second is sent out */
518 if(audio_delay_method
==2){
519 #ifdef SNDCTL_DSP_GETODELAY
521 if(ioctl(audio_fd
, SNDCTL_DSP_GETODELAY
, &r
)!=-1)
522 return ((float)r
)/(float)ao_data
.bps
;
524 audio_delay_method
=1; // fallback if not supported
526 if(audio_delay_method
==1){
527 // SNDCTL_DSP_GETOSPACE
528 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)!=-1)
529 return ((float)(ao_data
.buffersize
-zz
.bytes
))/(float)ao_data
.bps
;
530 audio_delay_method
=0; // fallback if not supported
532 return ((float)ao_data
.buffersize
)/(float)ao_data
.bps
;