From 7a2eec4b59f4055cb022710a71ebee498c7f55c5 Mon Sep 17 00:00:00 2001 From: arpi_esp Date: Sat, 2 Jun 2001 23:25:43 +0000 Subject: [PATCH] audio out drivers git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@955 b3059339-0415-0410-9bf9-f77b7e298cf2 --- libao2/Makefile | 41 ++++++++ libao2/ao_null.c | 73 ++++++++++++++ libao2/ao_oss.c | 191 ++++++++++++++++++++++++++++++++++++ libao2/audio_out.c | 29 ++++++ libao2/audio_out.h | 68 +++++++++++++ libao2/audio_out_internal.h | 23 +++++ 6 files changed, 425 insertions(+) create mode 100644 libao2/Makefile create mode 100644 libao2/ao_null.c create mode 100644 libao2/ao_oss.c create mode 100644 libao2/audio_out.c create mode 100644 libao2/audio_out.h create mode 100644 libao2/audio_out_internal.h diff --git a/libao2/Makefile b/libao2/Makefile new file mode 100644 index 0000000000..c726ab42de --- /dev/null +++ b/libao2/Makefile @@ -0,0 +1,41 @@ + +include ../config.mak + +LIBNAME = libao.a + +SRCS=audio_out.c ao_oss.c ao_null.c +OBJS=$(SRCS:.c=.o) + +CFLAGS = $(OPTFLAGS) -I. -I.. +# -I/usr/X11R6/include/ + +.SUFFIXES: .c .o + +# .PHONY: all clean + +.c.o: + $(CC) -c $(CFLAGS) -o $@ $< + +$(LIBNAME): .depend $(OBJS) + $(AR) r $(LIBNAME) $(OBJS) + +all: $(LIBNAME) + +clean: + rm -f *.o *.a *~ + +distclean: + rm -f Makefile.bak *.o *.a *~ .depend + +dep: depend +depend: .depend + +.depend: Makefile ../config.mak ../config.h + $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend + +# +# include dependency files if they exist +# +ifneq ($(wildcard .depend),) +include .depend +endif diff --git a/libao2/ao_null.c b/libao2/ao_null.c new file mode 100644 index 0000000000..d48667757f --- /dev/null +++ b/libao2/ao_null.c @@ -0,0 +1,73 @@ +#include +#include + +#include "audio_out.h" +#include "audio_out_internal.h" + +static ao_info_t info = +{ + "Null audio output", + "null", + "A'rpi", + "" +}; + +LIBAO_EXTERN(null) + +// there are some globals: +// ao_samplerate +// ao_channels +// ao_format +// ao_bps +// ao_outburst +// ao_buffersize + +// to set/get/query special features/parameters +static int control(int cmd,int arg){ + return -1; +} + +// open & setup audio device +// return: 1=success 0=fail +static int init(int rate,int channels,int format,int flags){ + + ao_outburst=4096; + + return 0; +} + +// close audio device +static void uninit(){ + +} + +// stop playing and empty buffers (for seeking/pause) +static void reset(){ + +} + +// return: how many bytes can be played without blocking +static int get_space(){ + + return ao_outburst; +} + +// plays 'len' bytes of 'data' +// it should round it down to outburst*n +// return: number of bytes played +static int play(void* data,int len,int flags){ + + return len; +} + +// return: how many unplayed bytes are in the buffer +static int get_delay(){ + + return 0; +} + + + + + + diff --git a/libao2/ao_oss.c b/libao2/ao_oss.c new file mode 100644 index 0000000000..4c35bb4cfc --- /dev/null +++ b/libao2/ao_oss.c @@ -0,0 +1,191 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" + +#include "audio_out.h" +#include "audio_out_internal.h" + +static ao_info_t info = +{ + "OSS/ioctl audio output", + "null", + "A'rpi", + "" +}; + +LIBAO_EXTERN(oss) + +// there are some globals: +// ao_samplerate +// ao_channels +// ao_format +// ao_bps +// ao_outburst +// ao_buffersize + +static char* dsp="/dev/dsp"; +static int audio_fd=-1; +static audio_buf_info zz; + +// to set/get/query special features/parameters +static int control(int cmd,int arg){ + switch(cmd){ + case AOCONTROL_SET_DEVICE: + dsp=(char*)arg; + return CONTROL_OK; + case AOCONTROL_QUERY_FORMAT: + return CONTROL_TRUE; + } + return CONTROL_UNKNOWN; +} + +// open & setup audio device +// return: 1=success 0=fail +static int init(int rate,int channels,int format,int flags){ + + printf("ao2: %d Hz %d chans 0x%X\n",rate,channels,format); + + audio_fd=open(dsp, O_WRONLY); + if(audio_fd<0){ + printf("Can't open audio device %s -> nosound\n",dsp); + return 0; + } + + ao_format=format; + ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format); + printf("audio_setup: sample format: 0x%X (requested: 0x%X)\n",ao_format,format); + + ao_channels=channels-1; + ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels); + + // set rate + ao_samplerate=rate; + ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate); + printf("audio_setup: using %d Hz samplerate (requested: %d)\n",ao_samplerate,rate); + + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)==-1){ + int r=0; + printf("audio_setup: driver doesn't support SNDCTL_DSP_GETOSPACE :-(\n"); + if(ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &r)==-1){ + printf("audio_setup: %d bytes/frag (config.h)\n",ao_outburst); + } else { + ao_outburst=r; + printf("audio_setup: %d bytes/frag (GETBLKSIZE)\n",ao_outburst); + } + } else { + printf("audio_setup: frags: %3d/%d (%d bytes/frag) free: %6d\n", + zz.fragments, zz.fragstotal, zz.fragsize, zz.bytes); + if(ao_buffersize==-1) ao_buffersize=zz.bytes; + ao_outburst=zz.fragsize; + } + + if(ao_buffersize==-1){ + // Measuring buffer size: + void* data; + ao_buffersize=0; +#ifdef HAVE_AUDIO_SELECT + data=malloc(ao_outburst); memset(data,0,ao_outburst); + while(ao_buffersize<0x40000){ + fd_set rfds; + struct timeval tv; + FD_ZERO(&rfds); FD_SET(audio_fd,&rfds); + tv.tv_sec=0; tv.tv_usec = 0; + if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) break; + write(audio_fd,data,ao_outburst); + ao_buffersize+=ao_outburst; + } + free(data); + if(ao_buffersize==0){ + printf("\n *** Your audio driver DOES NOT support select() ***\n"); + printf("Recompile mplayer with #undef HAVE_AUDIO_SELECT in config.h !\n\n"); + return 0; + } +#endif + } + + return 1; +} + +// close audio device +static void uninit(){ + ioctl(audio_fd, SNDCTL_DSP_RESET, NULL); + close(audio_fd); +} + +// stop playing and empty buffers (for seeking/pause) +static void reset(){ + uninit(); + audio_fd=open(dsp, O_WRONLY); + if(audio_fd<0){ + printf("\nFatal error: *** CANNOT RE-OPEN / RESET AUDIO DEVICE ***\n"); + return; + } + + ioctl (audio_fd, SNDCTL_DSP_SETFMT, &ao_format); + ioctl (audio_fd, SNDCTL_DSP_STEREO, &ao_channels); + ioctl (audio_fd, SNDCTL_DSP_SPEED, &ao_samplerate); + +} + +// return: how many bytes can be played without blocking +static int get_space(){ + int playsize=ao_outburst; + + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1){ + // calculate exact buffer space: + return zz.fragments*zz.fragsize; + } + + // check buffer +#ifdef HAVE_AUDIO_SELECT + { fd_set rfds; + struct timeval tv; + FD_ZERO(&rfds); + FD_SET(audio_fd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + if(!select(audio_fd+1, NULL, &rfds, NULL, &tv)) return 0; // not block! + } +#endif + + return ao_outburst; +} + +// plays 'len' bytes of 'data' +// it should round it down to outburst*n +// return: number of bytes played +static int play(void* data,int len,int flags){ + len/=ao_outburst; + len=write(audio_fd,data,len*ao_outburst); + return len; +} + +static int audio_delay_method=2; + +// return: how many unplayed bytes are in the buffer +static int get_delay(){ + if(audio_delay_method==2){ + // + int r=0; + if(ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &r)!=-1) + return r; + audio_delay_method=1; // fallback if not supported + } + if(audio_delay_method==1){ + // SNDCTL_DSP_GETOSPACE + if(ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &zz)!=-1) + return ao_buffersize-zz.bytes; + audio_delay_method=0; // fallback if not supported + } + return ao_buffersize; +} + diff --git a/libao2/audio_out.c b/libao2/audio_out.c new file mode 100644 index 0000000000..0e54a62672 --- /dev/null +++ b/libao2/audio_out.c @@ -0,0 +1,29 @@ + +#include +#include + +#include "../config.h" + +#include "audio_out.h" + +// there are some globals: +int ao_samplerate=0; +int ao_channels=0; +int ao_format=0; +int ao_bps=0; +int ao_outburst=OUTBURST; // config.h default +int ao_buffersize=-1; + +extern ao_functions_t audio_out_oss; +//extern ao_functions_t audio_out_ossold; +//extern ao_functions_t audio_out_alsa; +//extern ao_functions_t audio_out_esd; +extern ao_functions_t audio_out_null; + +ao_functions_t* audio_out_drivers[] = +{ + &audio_out_oss, + &audio_out_null, + NULL +}; + diff --git a/libao2/audio_out.h b/libao2/audio_out.h new file mode 100644 index 0000000000..cdd58dc7d4 --- /dev/null +++ b/libao2/audio_out.h @@ -0,0 +1,68 @@ + +typedef struct ao_info_s +{ + /* driver name ("Matrox Millennium G200/G400" */ + const char *name; + /* short name (for config strings) ("mga") */ + const char *short_name; + /* author ("Aaron Holtzman ") */ + const char *author; + /* any additional comments */ + const char *comment; +} ao_info_t; + +typedef struct ao_functions_s { + + ao_info_t *info; + + /* + */ + int (*control)(int cmd,int arg); + + /* + */ + int (*init)(int rate,int channels,int format,int flags); + + /* + */ + void (*uninit)(); + + /* + */ + void (*reset)(); + + /* + */ + int (*get_space)(); + + /* + */ + int (*play)(void* data,int len,int flags); + + /* + */ + int (*get_delay)(); + +} ao_functions_t; + +// NULL terminated array of all drivers +extern ao_functions_t* audio_out_drivers[]; + +extern int ao_samplerate; +extern int ao_channels; +extern int ao_format; +extern int ao_bps; +extern int ao_outburst; +extern int ao_buffersize; + +#define CONTROL_OK 1 +#define CONTROL_TRUE 1 +#define CONTROL_FALSE 0 +#define CONTROL_UNKNOWN -1 +#define CONTROL_ERROR -2 +#define CONTROL_NA -3 + +#define AOCONTROL_SET_DEVICE 1 +#define AOCONTROL_QUERY_FORMAT 2 + + diff --git a/libao2/audio_out_internal.h b/libao2/audio_out_internal.h new file mode 100644 index 0000000000..5899270af2 --- /dev/null +++ b/libao2/audio_out_internal.h @@ -0,0 +1,23 @@ + +// prototypes: +//static ao_info_t info; +static int control(int cmd,int arg); +static int init(int rate,int channels,int format,int flags); +static void uninit(); +static void reset(); +static int get_space(); +static int play(void* data,int len,int flags); +static int get_delay(); + +#define LIBAO_EXTERN(x) ao_functions_t audio_out_##x =\ +{\ + &info,\ + control,\ + init,\ + uninit,\ + reset,\ + get_space,\ + play,\ + get_delay\ +}; +