2 * OSS audio output driver
4 * This file is part of MPlayer.
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * MPlayer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <sys/ioctl.h>
27 #include <sys/types.h>
38 #ifdef HAVE_SYS_SOUNDCARD_H
39 #include <sys/soundcard.h>
41 #ifdef HAVE_SOUNDCARD_H
42 #include <soundcard.h>
46 #include "libaf/af_format.h"
48 #include "audio_out.h"
49 #include "audio_out_internal.h"
51 static const ao_info_t info
=
53 "OSS/ioctl audio output",
59 /* Support for >2 output channels added 2001-11-25 - Steve Davies <steve@daviesfam.org> */
63 static int format2oss(int format
)
67 case AF_FORMAT_U8
: return AFMT_U8
;
68 case AF_FORMAT_S8
: return AFMT_S8
;
69 case AF_FORMAT_U16_LE
: return AFMT_U16_LE
;
70 case AF_FORMAT_U16_BE
: return AFMT_U16_BE
;
71 case AF_FORMAT_S16_LE
: return AFMT_S16_LE
;
72 case AF_FORMAT_S16_BE
: return AFMT_S16_BE
;
74 case AF_FORMAT_U24_LE
: return AFMT_U24_LE
;
77 case AF_FORMAT_U24_BE
: return AFMT_U24_BE
;
80 case AF_FORMAT_S24_LE
: return AFMT_S24_LE
;
83 case AF_FORMAT_S24_BE
: return AFMT_S24_BE
;
86 case AF_FORMAT_U32_LE
: return AFMT_U32_LE
;
89 case AF_FORMAT_U32_BE
: return AFMT_U32_BE
;
92 case AF_FORMAT_S32_LE
: return AFMT_S32_LE
;
95 case AF_FORMAT_S32_BE
: return AFMT_S32_BE
;
98 case AF_FORMAT_FLOAT_NE
: return AFMT_FLOAT
;
101 case AF_FORMAT_MU_LAW
: return AFMT_MU_LAW
;
102 case AF_FORMAT_A_LAW
: return AFMT_A_LAW
;
103 case AF_FORMAT_IMA_ADPCM
: return AFMT_IMA_ADPCM
;
105 case AF_FORMAT_MPEG2
: return AFMT_MPEG
;
108 case AF_FORMAT_AC3
: return AFMT_AC3
;
111 mp_msg(MSGT_AO
, MSGL_V
, "OSS: Unknown/not supported internal format: %s\n", af_fmt2str_short(format
));
115 static int oss2format(int format
)
119 case AFMT_U8
: return AF_FORMAT_U8
;
120 case AFMT_S8
: return AF_FORMAT_S8
;
121 case AFMT_U16_LE
: return AF_FORMAT_U16_LE
;
122 case AFMT_U16_BE
: return AF_FORMAT_U16_BE
;
123 case AFMT_S16_LE
: return AF_FORMAT_S16_LE
;
124 case AFMT_S16_BE
: return AF_FORMAT_S16_BE
;
126 case AFMT_U24_LE
: return AF_FORMAT_U24_LE
;
129 case AFMT_U24_BE
: return AF_FORMAT_U24_BE
;
132 case AFMT_S24_LE
: return AF_FORMAT_S24_LE
;
135 case AFMT_S24_BE
: return AF_FORMAT_S24_BE
;
138 case AFMT_U32_LE
: return AF_FORMAT_U32_LE
;
141 case AFMT_U32_BE
: return AF_FORMAT_U32_BE
;
144 case AFMT_S32_LE
: return AF_FORMAT_S32_LE
;
147 case AFMT_S32_BE
: return AF_FORMAT_S32_BE
;
150 case AFMT_FLOAT
: return AF_FORMAT_FLOAT_NE
;
153 case AFMT_MU_LAW
: return AF_FORMAT_MU_LAW
;
154 case AFMT_A_LAW
: return AF_FORMAT_A_LAW
;
155 case AFMT_IMA_ADPCM
: return AF_FORMAT_IMA_ADPCM
;
157 case AFMT_MPEG
: return AF_FORMAT_MPEG2
;
160 case AFMT_AC3
: return AF_FORMAT_AC3
;
163 mp_tmsg(MSGT_GLOBAL
,MSGL_ERR
,"[AO OSS] Unknown/Unsupported OSS format: %x.\n", format
);
167 static char *dsp
=PATH_DEV_DSP
;
168 static audio_buf_info zz
;
169 static int audio_fd
=-1;
170 static int prepause_space
;
172 static const char *oss_mixer_device
= PATH_DEV_MIXER
;
173 static int oss_mixer_channel
= SOUND_MIXER_PCM
;
175 #ifdef SNDCTL_DSP_GETPLAYVOL
176 static int volume_oss4(ao_control_vol_t
*vol
, int cmd
) {
180 return CONTROL_ERROR
;
182 if (cmd
== AOCONTROL_GET_VOLUME
) {
183 if (ioctl(audio_fd
, SNDCTL_DSP_GETPLAYVOL
, &v
) == -1)
184 return CONTROL_ERROR
;
185 vol
->right
= (v
& 0xff00) >> 8;
186 vol
->left
= v
& 0x00ff;
188 } else if (cmd
== AOCONTROL_SET_VOLUME
) {
189 v
= ((int) vol
->right
<< 8) | (int) vol
->left
;
190 if (ioctl(audio_fd
, SNDCTL_DSP_SETPLAYVOL
, &v
) == -1)
191 return CONTROL_ERROR
;
194 return CONTROL_UNKNOWN
;
198 // to set/get/query special features/parameters
199 static int control(int cmd
,void *arg
){
201 case AOCONTROL_SET_DEVICE
:
204 case AOCONTROL_GET_DEVICE
:
207 #ifdef SNDCTL_DSP_GETFMTS
208 case AOCONTROL_QUERY_FORMAT
:
211 if (!ioctl(audio_fd
, SNDCTL_DSP_GETFMTS
, &format
))
212 if ((unsigned int)format
& (unsigned long)arg
)
214 return CONTROL_FALSE
;
217 case AOCONTROL_GET_VOLUME
:
218 case AOCONTROL_SET_VOLUME
:
220 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
223 #ifdef SNDCTL_DSP_GETPLAYVOL
225 if (volume_oss4(vol
, cmd
) == CONTROL_OK
)
229 if(ao_data
.format
== AF_FORMAT_AC3
)
232 if ((fd
= open(oss_mixer_device
, O_RDONLY
)) > 0)
234 ioctl(fd
, SOUND_MIXER_READ_DEVMASK
, &devs
);
235 if (devs
& (1 << oss_mixer_channel
))
237 if (cmd
== AOCONTROL_GET_VOLUME
)
239 ioctl(fd
, MIXER_READ(oss_mixer_channel
), &v
);
240 vol
->right
= (v
& 0xFF00) >> 8;
241 vol
->left
= v
& 0x00FF;
245 v
= ((int)vol
->right
<< 8) | (int)vol
->left
;
246 ioctl(fd
, MIXER_WRITE(oss_mixer_channel
), &v
);
252 return CONTROL_ERROR
;
258 return CONTROL_ERROR
;
260 return CONTROL_UNKNOWN
;
263 // open & setup audio device
264 // return: 1=success 0=fail
265 static int init(int rate
,int channels
,int format
,int flags
){
266 char *mixer_channels
[SOUND_MIXER_NRDEVICES
] = SOUND_DEVICE_NAMES
;
268 char *mdev
= mixer_device
, *mchan
= mixer_channel
;
270 mp_msg(MSGT_AO
,MSGL_V
,"ao2: %d Hz %d chans %s\n",rate
,channels
,
271 af_fmt2str_short(format
));
275 m
= strchr(ao_subdevice
,':');
289 oss_mixer_device
=mdev
;
291 oss_mixer_device
=PATH_DEV_MIXER
;
296 if ((fd
= open(oss_mixer_device
, O_RDONLY
)) == -1){
297 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Can't open mixer device %s: %s\n",
298 oss_mixer_device
, strerror(errno
));
300 ioctl(fd
, SOUND_MIXER_READ_DEVMASK
, &devs
);
303 for (i
=0; i
<SOUND_MIXER_NRDEVICES
; i
++){
304 if(!strcasecmp(mixer_channels
[i
], mchan
)){
305 if(!(devs
& (1 << i
))){
306 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Audio card mixer does not have channel '%s', using default.\n",mchan
);
307 i
= SOUND_MIXER_NRDEVICES
+1;
310 oss_mixer_channel
= i
;
314 if(i
==SOUND_MIXER_NRDEVICES
){
315 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Audio card mixer does not have channel '%s', using default.\n",mchan
);
319 oss_mixer_channel
= SOUND_MIXER_PCM
;
321 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' dsp device\n", dsp
);
322 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' mixer device\n", oss_mixer_device
);
323 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using '%s' mixer device\n", mixer_channels
[oss_mixer_channel
]);
326 audio_fd
=open(dsp
, O_WRONLY
| O_NONBLOCK
);
328 audio_fd
=open(dsp
, O_WRONLY
);
331 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Can't open audio device %s: %s\n", dsp
, strerror(errno
));
336 /* Remove the non-blocking flag */
337 if(fcntl(audio_fd
, F_SETFL
, 0) < 0) {
338 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Can't make file descriptor blocking: %s\n", strerror(errno
));
343 #if defined(FD_CLOEXEC) && defined(F_SETFD)
344 fcntl(audio_fd
, F_SETFD
, FD_CLOEXEC
);
347 if(format
== AF_FORMAT_AC3
) {
348 ao_data
.samplerate
=rate
;
349 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
353 ao_data
.format
=format
;
354 oss_format
=format2oss(format
);
355 if (oss_format
== -1) {
356 #ifdef WORDS_BIGENDIAN
357 oss_format
=AFMT_S16_BE
;
359 oss_format
=AFMT_S16_LE
;
361 format
=AF_FORMAT_S16_NE
;
363 if( ioctl(audio_fd
, SNDCTL_DSP_SETFMT
, &oss_format
)<0 ||
364 oss_format
!= format2oss(format
)) {
365 mp_tmsg(MSGT_AO
,MSGL_WARN
, "[AO OSS] Can't set audio device %s to %s output, trying %s...\n", dsp
,
366 af_fmt2str_short(format
), af_fmt2str_short(AF_FORMAT_S16_NE
) );
367 format
=AF_FORMAT_S16_NE
;
371 if(oss_format
!=format2oss(format
))
372 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
));
375 ao_data
.format
= oss2format(oss_format
);
376 if (ao_data
.format
== -1) return 0;
378 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: sample format: %s (requested: %s)\n",
379 af_fmt2str_short(ao_data
.format
), af_fmt2str_short(format
));
381 ao_data
.channels
= channels
;
382 if(format
!= AF_FORMAT_AC3
) {
383 // We only use SNDCTL_DSP_CHANNELS for >2 channels, in case some drivers don't have it
384 if (ao_data
.channels
> 2) {
385 if ( ioctl(audio_fd
, SNDCTL_DSP_CHANNELS
, &ao_data
.channels
) == -1 ||
386 ao_data
.channels
!= channels
) {
387 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", channels
);
392 int c
= ao_data
.channels
-1;
393 if (ioctl (audio_fd
, SNDCTL_DSP_STEREO
, &c
) == -1) {
394 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS] audio_setup: Failed to set audio device to %d channels.\n", ao_data
.channels
);
397 ao_data
.channels
=c
+1;
399 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using %d channels (requested: %d)\n", ao_data
.channels
, channels
);
401 ao_data
.samplerate
=rate
;
402 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
403 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: using %d Hz samplerate (requested: %d)\n",ao_data
.samplerate
,rate
);
406 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)==-1){
408 mp_tmsg(MSGT_AO
,MSGL_WARN
,"[AO OSS] audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n");
409 if(ioctl(audio_fd
, SNDCTL_DSP_GETBLKSIZE
, &r
)==-1){
410 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: %d bytes/frag (config.h)\n",ao_data
.outburst
);
413 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_data
.outburst
);
416 mp_msg(MSGT_AO
,MSGL_V
,"audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n",
417 zz
.fragments
, zz
.fragstotal
, zz
.fragsize
, zz
.bytes
);
418 if(ao_data
.buffersize
==-1) ao_data
.buffersize
=zz
.bytes
;
419 ao_data
.outburst
=zz
.fragsize
;
422 if(ao_data
.buffersize
==-1){
423 // Measuring buffer size:
425 ao_data
.buffersize
=0;
426 #ifdef HAVE_AUDIO_SELECT
427 data
=malloc(ao_data
.outburst
); memset(data
,0,ao_data
.outburst
);
428 while(ao_data
.buffersize
<0x40000){
431 FD_ZERO(&rfds
); FD_SET(audio_fd
,&rfds
);
432 tv
.tv_sec
=0; tv
.tv_usec
= 0;
433 if(!select(audio_fd
+1, NULL
, &rfds
, NULL
, &tv
)) break;
434 write(audio_fd
,data
,ao_data
.outburst
);
435 ao_data
.buffersize
+=ao_data
.outburst
;
438 if(ao_data
.buffersize
==0){
439 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS]\n *** Your audio driver DOES NOT support select() ***\n Recompile MPlayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n");
445 ao_data
.bps
=ao_data
.channels
;
446 if(ao_data
.format
!= AF_FORMAT_U8
&& ao_data
.format
!= AF_FORMAT_S8
)
449 ao_data
.outburst
-=ao_data
.outburst
% ao_data
.bps
; // round down
450 ao_data
.bps
*=ao_data
.samplerate
;
455 // close audio device
456 static void uninit(int immed
){
457 if(audio_fd
== -1) return;
458 #ifdef SNDCTL_DSP_SYNC
459 // to get the buffer played
461 ioctl(audio_fd
, SNDCTL_DSP_SYNC
, NULL
);
463 #ifdef SNDCTL_DSP_RESET
465 ioctl(audio_fd
, SNDCTL_DSP_RESET
, NULL
);
471 // stop playing and empty buffers (for seeking/pause)
472 static void reset(void){
475 audio_fd
=open(dsp
, O_WRONLY
);
477 mp_tmsg(MSGT_AO
,MSGL_ERR
,"[AO OSS]\nFatal error: *** CANNOT RE-OPEN / RESET AUDIO DEVICE *** %s\n", strerror(errno
));
481 #if defined(FD_CLOEXEC) && defined(F_SETFD)
482 fcntl(audio_fd
, F_SETFD
, FD_CLOEXEC
);
485 oss_format
= format2oss(ao_data
.format
);
486 if(ao_data
.format
== AF_FORMAT_AC3
)
487 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
488 ioctl (audio_fd
, SNDCTL_DSP_SETFMT
, &oss_format
);
489 if(ao_data
.format
!= AF_FORMAT_AC3
) {
490 if (ao_data
.channels
> 2)
491 ioctl (audio_fd
, SNDCTL_DSP_CHANNELS
, &ao_data
.channels
);
493 int c
= ao_data
.channels
-1;
494 ioctl (audio_fd
, SNDCTL_DSP_STEREO
, &c
);
496 ioctl (audio_fd
, SNDCTL_DSP_SPEED
, &ao_data
.samplerate
);
500 // stop playing, keep buffers (for pause)
501 static void audio_pause(void)
503 prepause_space
= get_space();
507 // resume playing, after audio_pause()
508 static void audio_resume(void)
512 fillcnt
= get_space() - prepause_space
;
513 if (fillcnt
> 0 && !(ao_data
.format
& AF_FORMAT_SPECIAL_MASK
)) {
514 void *silence
= calloc(fillcnt
, 1);
515 play(silence
, fillcnt
, 0);
521 // return: how many bytes can be played without blocking
522 static int get_space(void){
523 int playsize
=ao_data
.outburst
;
525 #ifdef SNDCTL_DSP_GETOSPACE
526 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)!=-1){
527 // calculate exact buffer space:
528 playsize
= zz
.fragments
*zz
.fragsize
;
529 if (playsize
> MAX_OUTBURST
)
530 playsize
= (MAX_OUTBURST
/ zz
.fragsize
) * zz
.fragsize
;
536 #ifdef HAVE_AUDIO_SELECT
540 FD_SET(audio_fd
, &rfds
);
543 if(!select(audio_fd
+1, NULL
, &rfds
, NULL
, &tv
)) return 0; // not block!
547 return ao_data
.outburst
;
550 // plays 'len' bytes of 'data'
551 // it should round it down to outburst*n
552 // return: number of bytes played
553 static int play(void* data
,int len
,int flags
){
556 if(len
>ao_data
.outburst
|| !(flags
& AOPLAY_FINAL_CHUNK
)) {
557 len
/=ao_data
.outburst
;
558 len
*=ao_data
.outburst
;
560 len
=write(audio_fd
,data
,len
);
564 static int audio_delay_method
=2;
566 // return: delay in seconds between first and last sample in buffer
567 static float get_delay(void){
568 /* Calculate how many bytes/second is sent out */
569 if(audio_delay_method
==2){
570 #ifdef SNDCTL_DSP_GETODELAY
572 if(ioctl(audio_fd
, SNDCTL_DSP_GETODELAY
, &r
)!=-1)
573 return ((float)r
)/(float)ao_data
.bps
;
575 audio_delay_method
=1; // fallback if not supported
577 if(audio_delay_method
==1){
578 // SNDCTL_DSP_GETOSPACE
579 if(ioctl(audio_fd
, SNDCTL_DSP_GETOSPACE
, &zz
)!=-1)
580 return ((float)(ao_data
.buffersize
-zz
.bytes
))/(float)ao_data
.bps
;
581 audio_delay_method
=0; // fallback if not supported
583 return ((float)ao_data
.buffersize
)/(float)ao_data
.bps
;