diff --git a/libao2/ao_plugin.c b/libao2/ao_plugin.c new file mode 100644 index 0000000000..9bf8d9b5c7 --- /dev/null +++ b/libao2/ao_plugin.c @@ -0,0 +1,145 @@ +#include +#include + +#include "../config.h" + +#include "audio_out.h" +#include "audio_out_internal.h" + +#include "audio_plugin.h" + +static ao_info_t info = +{ + "Plugin audio output", + "plugin", + "Anders", + "" +}; + +LIBAO_EXTERN(plugin) + +#define plugin(i) (ao_plugin_local_data.ao_plugins[i]) +#define driver() (ao_plugin_local_data.ao_driver) + +/* local data */ +typedef struct ao_plugin_local_data_s +{ + ao_plugin_functions_t** ao_plugins; /* List of all plugins */ + ao_functions_t* ao_driver; /* ao driver used by ao_plugin */ +} ao_plugin_local_data_t; + +ao_plugin_local_data_t ao_plugin_local_data; + +/* gloabal data */ +ao_plugin_data_t ao_plugin_data; + +// to set/get/query special features/parameters +static int control(int cmd,int arg){ + return driver()->control(cmd,arg); +} + +// open & setup audio device and plugins +// return: 1=success 0=fail +static int init(int rate,int channels,int format,int flags){ + int ok=1; + + /* FIXME these are cfg file parameters */ + int i=0; + ao_plugin_local_data.ao_plugins=malloc((i+1)*sizeof(ao_plugin_functions_t*)); + plugin(i)=NULL; + ao_plugin_local_data.ao_driver=audio_out_drivers[1]; + + /* Set input parameters and itterate through plugins each plugin + changes the parameters according to its output */ + ao_plugin_data.rate=rate; + ao_plugin_data.channels=channels; + ao_plugin_data.format=format; + ao_plugin_data.sz_mult=1; + ao_plugin_data.sz_fix=0; + ao_plugin_data.delay_mult=1; + ao_plugin_data.delay_fix=0; + i=0; + while(plugin(i)&&ok) + ok=plugin(i++)->init(); + + if(!ok) return 0; + + ok = driver()->init(ao_plugin_data.rate, + ao_plugin_data.channels, + ao_plugin_data.format, + flags); + if(!ok) return 0; + + /* Now that the driver is initialized we can calculate and set the + input and output buffers for each plugin */ + ao_plugin_data.len=driver()->get_space(); + + return 1; +} + +// close audio device +static void uninit(){ + int i=0; + driver()->uninit(); + while(plugin(i)) + plugin(i++)->uninit(); + if(ao_plugin_local_data.ao_plugins) + free(ao_plugin_local_data.ao_plugins); +} + +// stop playing and empty buffers (for seeking/pause) +static void reset(){ + int i=0; + driver()->reset(); + while(plugin(i)) + plugin(i++)->reset(); +} + +// stop playing, keep buffers (for pause) +static void audio_pause(){ + driver()->pause(); +} + +// resume playing, after audio_pause() +static void audio_resume(){ + driver()->resume(); +} + +// return: how many bytes can be played without blocking +static int get_space(){ + double sz=(double)(driver()->get_space()); + sz*=ao_plugin_data.sz_mult; + sz+=ao_plugin_data.sz_fix; + return (int)(sz); +} + +// plays 'len' bytes of 'data' +// return: number of bytes played +static int play(void* data,int len,int flags){ + int i=0; + /* Due to constant buffer sizes in plugins limit length */ + int tmp = get_space(); + int ret_len =(tmpplay(); + /* Send data to output */ + len=driver()->play(ao_plugin_data.data,ao_plugin_data.len,flags); + + if(len!=ao_plugin_data.len) + printf("Buffer over flow in sound plugin "); + + return ret_len; +} + +// return: delay in seconds between first and last sample in buffer +static float get_delay(){ + float delay=driver()->get_delay(); + delay*=ao_plugin_data.delay_mult; + delay+=ao_plugin_data.delay_fix; + return delay; +} + + diff --git a/libao2/audio_plugin.h b/libao2/audio_plugin.h new file mode 100644 index 0000000000..22bbdfd14c --- /dev/null +++ b/libao2/audio_plugin.h @@ -0,0 +1,27 @@ +/* functions supplied by plugins */ +typedef struct ao_plugin_functions_s +{ + ao_info_t *info; + int (*control)(int cmd,int arg); + int (*init)(); + void (*uninit)(); + void (*reset)(); + int (*play)(); +} ao_plugin_functions_t; + +/* Global data for all audio plugins */ +typedef struct ao_plugin_data_s +{ + void* data; /* current data block read only ok to change */ + int len; /* setup and current buffer length */ + int rate; /* setup data rate */ + int channels; /* setup number of channels */ + int format; /* setup format */ + double sz_mult; /* Buffer size multiplier */ + double sz_fix; /* Fix extra buffer size */ + float delay_mult; /* Delay multiplier */ + float delay_fix; /* Fix delay */ +}ao_plugin_data_t; + +extern ao_plugin_data_t ao_plugin_data; + diff --git a/libao2/audio_plugin_internal.h b/libao2/audio_plugin_internal.h new file mode 100644 index 0000000000..b928ccf95b --- /dev/null +++ b/libao2/audio_plugin_internal.h @@ -0,0 +1,16 @@ +// prototypes: +static int control(int cmd,int arg); +static int init(float*); +static void uninit(); +static void reset(); +static int play(void* data,int len,int flags); + +#define LIBAO_PLUGIN_EXTERN(x) ao_functions_t audio_out_##x =\ +{\ + &info,\ + control,\ + init,\ + uninit,\ + reset,\ + play,\ +};