summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libao2/ao_plugin.c145
-rw-r--r--libao2/audio_plugin.h27
-rw-r--r--libao2/audio_plugin_internal.h16
3 files changed, 188 insertions, 0 deletions
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 <stdio.h>
+#include <stdlib.h>
+
+#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 =(tmp<len)?tmp:len;
+ /* Filter data */
+ ao_plugin_data.len=ret_len;
+ ao_plugin_data.data=data;
+ while(plugin(i))
+ plugin(i++)->play();
+ /* 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,\
+};