diff --git a/Makefile.am b/Makefile.am
index 99d7d1c52d28cf9cc5ef5b07240a6928633584a6..de996fc03eb52dc16faafc0d933d3f987b9ee81d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,12 @@ AUTOMAKE_OPTIONS = foreign dist-zip
 
 SUBDIRS = src include doc
 
-EXTRA_DIST = README AUTHORS CHANGES COPYING libao.spec
+bin_SCRIPTS = ao-config
+
+m4datadir = $(datadir)/aclocal
+m4data_DATA = ao.m4
+
+EXTRA_DIST = README AUTHORS CHANGES COPYING libao.spec ao.m4
 
 debug:
 	$(MAKE) all CFLAGS="@DEBUG@"
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000000000000000000000000000000000000..39b37898802644f51730a6766750c169732297e9
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,164 @@
+# Configure paths for ESD
+# Manish Singh    98-9-30
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS
+dnl
+AC_DEFUN(AM_PATH_ESD,
+[dnl 
+dnl Get the cflags and libraries from the esd-config script
+dnl
+AC_ARG_WITH(esd-prefix,[  --with-esd-prefix=PFX   Prefix where ESD is installed (optional)],
+            esd_prefix="$withval", esd_prefix="")
+AC_ARG_WITH(esd-exec-prefix,[  --with-esd-exec-prefix=PFX Exec prefix where ESD is installed (optional)],
+            esd_exec_prefix="$withval", esd_exec_prefix="")
+AC_ARG_ENABLE(esdtest, [  --disable-esdtest       Do not try to compile and run a test ESD program],
+		    , enable_esdtest=yes)
+
+  if test x$esd_exec_prefix != x ; then
+     esd_args="$esd_args --exec-prefix=$esd_exec_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_exec_prefix/bin/esd-config
+     fi
+  fi
+  if test x$esd_prefix != x ; then
+     esd_args="$esd_args --prefix=$esd_prefix"
+     if test x${ESD_CONFIG+set} != xset ; then
+        ESD_CONFIG=$esd_prefix/bin/esd-config
+     fi
+  fi
+
+  AC_PATH_PROG(ESD_CONFIG, esd-config, no)
+  min_esd_version=ifelse([$1], ,0.2.7,$1)
+  AC_MSG_CHECKING(for ESD - version >= $min_esd_version)
+  no_esd=""
+  if test "$ESD_CONFIG" = "no" ; then
+    no_esd=yes
+  else
+    ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags`
+    ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs`
+
+    esd_major_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    esd_minor_version=`$ESD_CONFIG $esd_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_esdtest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $ESD_CFLAGS"
+      LIBS="$LIBS $ESD_LIBS"
+dnl
+dnl Now check if the installed ESD is sufficiently new. (Also sanity
+dnl checks the results of esd-config to some extent
+dnl
+      rm -f conf.esdtest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <esd.h>
+
+char*
+my_strdup (char *str)
+{
+  char *new_str;
+  
+  if (str)
+    {
+      new_str = malloc ((strlen (str) + 1) * sizeof(char));
+      strcpy (new_str, str);
+    }
+  else
+    new_str = NULL;
+  
+  return new_str;
+}
+
+int main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.esdtest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = my_strdup("$min_esd_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_esd_version");
+     exit(1);
+   }
+
+   if (($esd_major_version > major) ||
+      (($esd_major_version == major) && ($esd_minor_version > minor)) ||
+      (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version);
+      printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n");
+      printf("*** to point to the correct copy of esd-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_esd" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$ESD_CONFIG" = "no" ; then
+       echo "*** The esd-config script installed by ESD could not be found"
+       echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the ESD_CONFIG environment variable to the"
+       echo "*** full path to esd-config."
+     else
+       if test -f conf.esdtest ; then
+        :
+       else
+          echo "*** Could not run ESD test program, checking why..."
+          CFLAGS="$CFLAGS $ESD_CFLAGS"
+          LIBS="$LIBS $ESD_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <esd.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding ESD or finding the wrong"
+          echo "*** version of ESD. If it is not finding ESD, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means ESD was incorrectly installed"
+          echo "*** or that you have moved ESD since it was installed. In the latter case, you"
+          echo "*** may want to edit the esd-config script: $ESD_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     ESD_CFLAGS=""
+     ESD_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(ESD_CFLAGS)
+  AC_SUBST(ESD_LIBS)
+  rm -f conf.esdtest
+])
diff --git a/ao-config.in b/ao-config.in
new file mode 100644
index 0000000000000000000000000000000000000000..592f9e02a7960d8c16d8043676d34251c2287608
--- /dev/null
+++ b/ao-config.in
@@ -0,0 +1,116 @@
+#!/bin/sh
+
+# ao-config
+#
+# Tool for retrieving the library/include paths ao was compiled with.
+#
+# Written 29 October 2000 by Jack Moffitt <jack@icecast.org>
+# Based *HEAVILY* on xmms-config from the XMMS package
+# which was
+# Based *HEAVILY* on gtk-config from the GTK+ library package.
+#
+# This work is released under the GNU GPL, version 2 or later.
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+exec_prefix_set=no
+data_dir="@datadir@/@PACKAGE@"
+
+version="@VERSION@"
+include_dir="@includedir@"
+ao_include_dir="@includedir@/@PACKAGE@"
+lib_dir="@libdir@"
+
+esd_cflags="@ESD_CFLAGS@"
+esd_libs="@ESD_LIBS@"
+
+plugin_dir="@plugindir@"
+
+usage()
+{
+    cat <<EOF
+Usage: ao-config [OPTIONS]
+Options:
+    [--prefix[=DIR]]
+    [--version]
+    [--libs]
+    [--cflags]
+    [--plugin-dir]
+
+EOF
+    exit $1
+}
+
+if test $# -eq 0; then
+    usage 1 1>&2
+fi
+
+while test $# -gt 0; do
+    case "$1" in
+	-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+	*) optarg= ;;
+    esac
+
+    case $1 in
+	--prefix=*)
+	    prefix=$optarg
+	    ;;
+
+	--prefix)
+	    echo_prefix=yes
+	    ;;
+
+	--version)
+	    echo $version
+	    ;;
+
+	--cflags)
+	    echo_cflags=yes
+	    ;;
+
+	--libs)
+	    echo_libs=yes
+	    ;;
+
+	--plugin-dir)
+	    echo_plugin_dir=yes
+	    ;;
+
+	*)
+	    usage 1 1>&2
+	    ;;
+    esac
+  shift
+done
+
+if test "$echo_prefix" = "yes"; then
+    echo $prefix
+fi
+
+if test "$echo_exec_prefix" = "yes"; then
+    echo $exec_prefix
+fi
+
+if test "$include_dir" != "/usr/include"; then
+    cflags="-I$include_dir $esd_cflags"
+else
+    cflags="$esd_cflags"
+fi
+
+if test "$lib_dir" != "/usr/lib"; then
+    libs="-L$lib_dir $esd_libs -lao"
+else
+    libs="$esd_libs -lao"
+fi
+
+if test "$echo_cflags" = "yes"; then
+    echo $cflags
+fi
+
+if test "$echo_libs" = "yes"; then
+    echo $libs
+fi
+
+if test "$echo_plugin_dir" = "yes"; then
+    echo $plugin_dir
+fi
diff --git a/ao.m4 b/ao.m4
new file mode 100644
index 0000000000000000000000000000000000000000..e651e5590ced0a216964cc00689f903860e4e7ce
--- /dev/null
+++ b/ao.m4
@@ -0,0 +1,110 @@
+# Configure paths for libao
+# Jack Moffitt <jack@icecast.org> 10-21-2000
+# Shamelessly stolen from Owen Taylor and Manish Singh
+
+dnl AM_PATH_AO([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for libao, and define AO_CFLAGS and AO_LIBS
+dnl
+AC_DEFUN(AM_PATH_AO,
+[dnl 
+dnl Get the cflags and libraries from the ao-config script
+dnl
+AC_ARG_WITH(ao-prefix,[  --with-ao-prefix=PFX   Prefix where libao is installed (optional)], ao_prefix="$withval", ao_prefix="")
+AC_ARG_ENABLE(aotest, [  --disable-aotest       Do not try to compile and run a test ao program],, enable_aotest=yes)
+
+  if test x$ao_prefix != x ; then
+     ao_args="$ao_args --prefix=$ao_prefix"
+     if test x${AO_CONFIG+set} != xset ; then
+        AO_CONFIG=$ao_prefix/bin/ao-config
+     fi
+  fi
+
+  AC_PATH_PROG(AO_CONFIG, ao-config, no)
+  min_ao_version=ifelse([$1], ,1.0.0,$1)
+  AC_MSG_CHECKING(for ao - version >= $min_ao_version)
+  no_ao=""
+  if test "$AO_CONFIG" = "no" ; then
+    no_ao=yes
+  else
+    AO_CFLAGS=`$AO_CONFIG $aoconf_args --cflags`
+    AO_LIBS=`$AO_CONFIG $aoconf_args --libs`
+
+    ao_major_version=`$AO_CONFIG $ao_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    ao_minor_version=`$AO_CONFIG $ao_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    ao_micro_version=`$AO_CONFIG $ao_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_aotest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $AO_CFLAGS"
+      LIBS="$LIBS $AO_LIBS"
+dnl
+dnl Now check if the installed ao is sufficiently new. (Also sanity
+dnl checks the results of ao-config to some extent
+dnl
+      rm -f conf.aotest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ao/ao.h>
+
+int main ()
+{
+  system("touch conf.aotest");
+  return 0;
+}
+
+],, no_ao=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_ao" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$AO_CONFIG" = "no" ; then
+       echo "*** The ao-config script installed by ao could not be found"
+       echo "*** If ao was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the AO_CONFIG environment variable to the"
+       echo "*** full path to ao-config."
+     else
+       if test -f conf.aotest ; then
+        :
+       else
+          echo "*** Could not run ao test program, checking why..."
+          CFLAGS="$CFLAGS $AO_CFLAGS"
+          LIBS="$LIBS $AO_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include <ao/ao.h>
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding ao or finding the wrong"
+          echo "*** version of ao. If it is not finding ao, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means ao was incorrectly installed"
+          echo "*** or that you have moved ao since it was installed. In the latter case, you"
+          echo "*** may want to edit the ao-config script: $AO_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     AO_CFLAGS=""
+     AO_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(AO_CFLAGS)
+  AC_SUBST(AO_LIBS)
+  rm -f conf.aotest
+])
diff --git a/configure.in b/configure.in
index 59a7ea736e12341527470173461b5a559d910307..126e7f72d14cab86f6a7fe29870caa76f8aeaaf2 100644
--- a/configure.in
+++ b/configure.in
@@ -2,6 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/audio_out.c)
 
 AM_INIT_AUTOMAKE(libao,1.0.0)
+AM_DISABLE_STATIC
 
 dnl Library versioning
 LIB_CURRENT=0
@@ -13,13 +14,15 @@ AC_SUBST(LIB_AGE)
 
 AC_CANONICAL_HOST
 
+plugindir=$libdir/ao
+AC_SUBST(plugindir)
+
 dnl ====================================
 dnl Check for programs
 dnl ====================================
 
 AC_PROG_CC
 AM_PROG_LIBTOOL
-AC_PROG_CPP
 AC_PROG_RANLIB
 
 AC_SUBST(RANLIB)
@@ -64,6 +67,7 @@ else
         esac
 fi
 
+
 AC_SUBST(CC)
 AC_SUBST(DEBUG)
 AC_SUBST(PROFILE)
@@ -72,20 +76,10 @@ dnl ==============================
 dnl Check for libraries
 dnl ==============================
 
-dnl --- if we're on irix, check for -laudio ---
-
-case $host in
-        *-*-irix*)
-                AC_CHECK_LIB(audio, ALwritesamps)
-        ;;
-esac
-
 dnl ==============================
 dnl Checks for header files
 dnl ==============================
 
-AC_HEADER_STDC
-
 dnl ==============================
 dnl Checks for types
 dnl ==============================
@@ -106,144 +100,46 @@ case 4 in
 esac
 
 if test -z "$SIZE16"; then
-        AC_MSG_WARN(No 16 bit type found on this platform!)
+        AC_MSG_ERROR(No 16 bit type found on this platform!)
 fi
 if test -z "$SIZE32"; then
-        AC_MSG_WARN(No 32 bit type found on this platform!)
+        AC_MSG_ERROR(No 32 bit type found on this platform!)
 fi
 
 AC_SUBST(SIZE16)
 AC_SUBST(SIZE32)
-AC_SUBST(SIZE64)
-
-dnl =========================================
-dnl Figure out which ao_* files to compile
-dnl =========================================
-
-AC_ARG_ENABLE(oss,,,enable_oss=yes)
-AC_ARG_ENABLE(irix,,,enable_irix=yes)
-AC_ARG_ENABLE(solaris,,,enable_solaris=yes)
-AC_ARG_ENABLE(alsa,,,enable_alsa=yes)
-AC_ARG_ENABLE(esd,,,enable_esd=yes)
-AC_ARG_ENABLE(default-output,,,enable_default_output=def)
 
 dnl ======================================
 dnl Detect possible output devices 
 dnl ======================================
 
-dnl --- Initialize default variable values ---
-has_oss=no
-has_irix=no
-has_solaris=no
-has_esd=no
-has_alsa=no
-need_libossaudio=no
-
-AC_CHECK_LIB(ossaudio, main, has_libossaudio=yes, has_libossaudio=no)
-
-case $host in
-        *-*-linux*|*-openbsd*|*-freebsd*)
-		has_oss=yes;;
-	*-netbsd*)
-   	  	if test has_libossaudio = "yes"; then
-                   	has_oss=yes
-                      	need_libossaudio=yes
-              	fi;;
-        *-irix*)
-		has_irix=yes;;
-        *-solaris*)
-		has_solaris=yes;;
-esac
-
-AC_CHECK_LIB(esd, esd_play_stream, has_esd=yes)
-AC_CHECK_LIB(asound, snd_pcm_open, has_alsa=yes, has_alsa=no)
-
-dnl -- Set appropriate variables for each driver --
-
-AC_MSG_CHECKING("whether to compile OSS driver")
-if test $enable_oss = "yes" && test $has_oss = "yes"; then
-	AC_MSG_RESULT("yes")
-	LIBAO_FILES="$LIBAO_FILES ao_oss.c"
-	LIBAO_FLAGS="$LIBAO_FLAGS -DAO_COMPILE_OSS"
-      	if test need_libossaudio = yes; then
-              	LIBAO_LIBS="$LIBAO_LIBS -lossaudio"
-      	fi
-	ao_default=oss
-else
-	AC_MSG_RESULT("no")
-fi
+dnl Check for ESD
 
-AC_MSG_CHECKING("whether to compile IRIX driver")
-if test $enable_irix = "yes" && test $has_irix = "yes"; then
-	AC_MSG_RESULT("yes")
-	LIBAO_FILES="$LIBAO_FILES ao_irix.c"
-	LIBAO_FLAGS="$LIBAO_FLAGS -DAO_COMPILE_IRIX"
-	ao_default=irix
-else
-	AC_MSG_RESULT("no")
-fi
+AM_PATH_ESD(0.2.8, have_esd=yes, have_esd=no)
+AM_CONDITIONAL(HAVE_ESD,test "x$have_esd" = xyes)
 
-AC_MSG_CHECKING("whether to compile Solaris driver")
-if test $enable_solaris = "yes" && test $has_solaris = "yes"; then
-	LIBAO_FILES="$LIBAO_FILES ao_solaris.c"
-	LIBAO_FLAGS="$LIBAO_FLAGS -DAO_COMPILE_SOLARIS"
-	ao_default=solaris
-else
-	AC_MSG_RESULT("no")
-fi
+dnl Check for OSS
 
-AC_MSG_CHECKING("whether to compile ESD driver")
-if test $enable_esd = "yes" && test $has_esd = "yes"; then
-	AC_MSG_RESULT("yes")
-	LIBAO_LIBS="$LIBAO_LIBS -lesd"
-	LIBAO_FLAGS="$LIBAO_FLAGS -DAO_COMPILE_ESD"
-	LIBAO_FILES="$LIBAO_FILES ao_esd.c"
-else
-	AC_MSG_RESULT("no")
-fi
+AC_CHECK_HEADERS(sys/soundcard.h)
+AC_CHECK_HEADERS(machine/soundcard.h)
+AM_CONDITIONAL(HAVE_OSS,test "${ac_cv_header_sys_soundcard_h}" = "yes" || test "${ac_cv_header_machine_soundcard_h}" = "yes")
 
-AC_MSG_CHECKING("whether to compile ALSA driver")
-if test $enable_alsa = "yes" && test $has_alsa = "yes"; then
-	AC_MSG_RESULT("yes")
-	LIBAO_FLAGS="$LIBAO_FLAGS -DAO_COMPILE_ALSA"
-	LIBAO_FILES="$LIBAO_FILES ao_alsa.c"
-	LIBAO_LIBS="$LIBAO_LIBS -lasound"
-else
-	AC_MSG_RESULT("no")
-fi
+dnl Check for ALSA
 
-dnl -- Set the default device
+AC_CHECK_LIB(asound, snd_pcm_open, has_alsa=yes, has_alsa=no)
+AM_CONDITIONAL(HAVE_ALSA,test "x$have_alsa" = xyes)
 
-if test $enable_default_output != "def"; then
-	ao_default=$enable_default_output
-fi
+dnl Check for IRIX
 
-case $ao_default in
-	null)
-		AO_DEFAULT_DEF=AO_NULL;;
-	oss)
-		AO_DEFAULT_DEF=AO_OSS;;
-	irix)
-		AO_DEFAULT_DEF=AO_IRIX;;
-	solaris)
-		AO_DEFAULT_DEF=AO_SOLARIS;;
-	esd)
-		AO_DEFAULT_DEF=AO_ESD;;
-	alsa)
-		AO_DEFAULT_DEF=AO_ALSA;;
-	wav)
-		AO_DEFAULT_DEF=AO_WAV;;
-	*)
-		dnl Make the default output device AO_NULL
-		ao_default=null
-		AO_DEFAULT_DEF=AO_NULL;;
+case $host in
+        *-*-irix*)
+                AC_CHECK_LIB(audio, ALwritesamps, have_irix=yes, have_irix=no)
+        ;;
 esac
+AM_CONDITIONAL(HAVE_IRIX,test "x$have_irix" = xyes)
 
-AC_MSG_RESULT("setting default output device... $ao_default")
-
-CFLAGS="$LIBAO_FLAGS -DAO_DEFAULT=$AO_DEFAULT_DEF"
+AM_CONDITIONAL(HAVE_SOLARIS,test "x$have_solaris" = xyes)
 
-AC_SUBST(LIBAO_FILES)
-AC_SUBST(LIBAO_LIBS)
+CFLAGS="$CFLAGS -DAO_PLUGIN_PATH=\\\"$plugindir\\\""
 
-AC_OUTPUT(Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h include/ao/ao_libs.inc)
+AC_OUTPUT(Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h include/ao/ao_libs.inc src/plugins/Makefile src/plugins/esd/Makefile src/plugins/oss/Makefile src/plugins/alsa/Makefile ao-config)
diff --git a/include/ao/ao.h b/include/ao/ao.h
index b9835b6b77f56897bf879a1627cc3f4a99ff1dbc..b276fe6fb3580bd6ae1d4883af524481558993c3 100644
--- a/include/ao/ao.h
+++ b/include/ao/ao.h
@@ -1,11 +1,12 @@
 /*
  *
- *  audio_out.h 
+ *  ao.h 
  *    
  *	Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
+ *      More Modifications Copyright (C) Jack Moffitt - October 2000
  *
- *  This file is part of libao, a cross-platform library.  See
+ *  This file is part of libao, a cross-platform audio outputlibrary.  See
  *  README for a history of this source code.
  *
  *  libao is free software; you can redistribute it and/or modify
@@ -23,9 +24,10 @@
  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.	
  *
  */
+#ifndef __AO_H__
+#define __AO_H__
 
 #include <stdlib.h>
-
 #include "os_types.h"
 
 /* --- Structures --- */
@@ -36,8 +38,7 @@ typedef struct ao_option_s {
 	struct ao_option_s *next;
 } ao_option_t;
 
-typedef struct ao_info_s
-{
+typedef struct ao_info_s {
 	/* driver name (Ex: "OSS Audio driver") */
 	const char *name;
 	/* short name (for config strings) (Ex: "oss") */
@@ -50,59 +51,46 @@ typedef struct ao_info_s
 
 typedef void ao_internal_t;
 
-typedef struct ao_functions_s
-{
-	ao_info_t* (*get_driver_info) (void);
-	ao_internal_t*     (*open)  (uint_32 bits, uint_32 rate, 
-				     uint_32 channels, ao_option_t *options);
-	void             (*play)  (ao_internal_t *state, 
-				   void* output_samples, uint_32 num_bytes);
-	void             (*close) (ao_internal_t *state);
+typedef struct ao_functions_s {
+	ao_info_t *(*get_driver_info)(void);
+	ao_internal_t *(*open)(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options);
+	void (*play)(ao_internal_t *state, void* output_samples, uint_32 num_bytes);
+	void (*close)(ao_internal_t *state);
 } ao_functions_t;
 
-typedef struct ao_device_s
-{
+typedef struct ao_device_s {
 	ao_functions_t *funcs;
 	ao_internal_t *state;
 } ao_device_t;
 
 
 
-/* --- Driver id numbers --- */
+/* --- Standard driver_id numbers --- */
 
 #define AO_NULL     0
-
-#define AO_OSS      1
-#define AO_IRIX     2
-#define AO_SOLARIS  3
-#define AO_WIN32    4
-#define AO_BEOS     5
-#define AO_ESD      6
-#define AO_ALSA     7
-
-#define AO_WAV      10
-#define AO_RAW      11
-
-/* Total number of drivers */
-#define AO_DRIVERS 12
-
+#define AO_RAW      1
+#define AO_WAV      2
 
 /* --- Functions --- */
 
-int ao_get_driver_id (const char *short_name);
-
-ao_info_t *ao_get_driver_info (int driver_id);
-
-ao_device_t *ao_open (int driver_id, uint_32 bits, uint_32 rate, uint_32 channels, 
-	     ao_option_t *options);
+/* library init/shutdown */
+void ao_initialize(void);
+void ao_shutdown(void);
 
-void ao_play (ao_device_t *device, void* output_samples, uint_32 num_bytes);
+/* driver information */
+int ao_get_driver_id(const char *short_name);
+ao_info_t *ao_get_driver_info(int driver_id);
 
-void ao_close (ao_device_t *device);
+/* driver options */
+int ao_append_options(ao_option_t **options, const char *op_str);
+void ao_free_options(ao_option_t *options);
 
-/* Returns 1 if options successfully appended, 0 if error */
-int ao_append_option (ao_option_t **options, const char* op_str);
+/* the meat: open/play/close */
+ao_device_t *ao_open(int driver_id, uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options);
+void ao_play(ao_device_t *device, void* output_samples, uint_32 num_bytes);
+void ao_close(ao_device_t *device);
 
-void ao_free_options (ao_option_t* options);
+/* misc functions */
+int ao_is_big_endian(void);
 
-int ao_is_big_endian();
+#endif  /* __AO_H__ */
diff --git a/include/ao/os_types.h.in b/include/ao/os_types.h.in
index bb2378b1333d5b012ee16f640545d2f14a2394c1..3907c7c55d3f3a05228fd2e70d05bbc9a5c7b5ad 100644
--- a/include/ao/os_types.h.in
+++ b/include/ao/os_types.h.in
@@ -1,11 +1,11 @@
 /*
  *
- *  config.h
+ *  os_types.h
  *
  *      Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
  *
- *  This file is part of libao, a cross-platform library.  See
+ *  This file is part of libao, a cross-platform audio output library.  See
  *  README for a history of this source code.
  *
  *  libao is free software; you can redistribute it and/or modify
diff --git a/src/Makefile.am b/src/Makefile.am
index 9a9034e2bb1e0bde3d4aeac0d2fb12e3386383f7..e12d5a0922411a2ed5d05a7d51cf92f03a1dab61 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,17 +1,15 @@
 ## Process this file with automake to produce Makefile.in
 
 AUTOMAKE_OPTIONS = foreign
+SUBDIRS = plugins
 
 INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include
 
 lib_LTLIBRARIES = libao.la
 
-#libao_la_SOURCES = audio_out.c @LIBAO_FILES@
-libao_la_SOURCES = audio_out.c ao_oss.c ao_wav.c ao_null.c
+libao_la_SOURCES = audio_out.c ao_wav.c ao_null.c
 libao_la_LDFLAGS = -version-info @LIB_CURRENT@:@LIB_REVISION@:@LIB_AGE@
 
-EXTRA_libao_la_SOURCES = ao_alsa.c ao_irix.c ao_oss.c ao_wav.c ao_esd.c ao_null.c ao_solaris.c audio_out.c
-
 
 debug:
 	$(MAKE) all CFLAGS="@DEBUG@"
diff --git a/src/ao_null.c b/src/ao_null.c
index e7d1ccfa3815d65c5e1e64d2b3db9b9a6306b89b..1ffe6b745621778400dd485c873ac875e44f7667 100644
--- a/src/ao_null.c
+++ b/src/ao_null.c
@@ -5,7 +5,7 @@
  *      Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
  *
- *  This file is part of libao, a cross-platform library.  See
+ *  This file is part of libao, a cross-platform audio output library.  See
  *  README for a history of this source code.
  *
  *  libao is free software; you can redistribute it and/or modify
@@ -27,59 +27,55 @@
 #include <stdio.h>
 #include <ao/ao.h>
 
-typedef struct ao_null_internal_s
-{
+typedef struct ao_null_internal_s {
 	unsigned long byte_counter;
 } ao_null_internal_t;
 
-static ao_info_t ao_null_info =
-{
+static ao_info_t ao_null_info = {
 	"Null output",
 	"null",
 	"Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
-	""
+	"This plugin does nothing"
 };
 
-static ao_internal_t*
-ao_null_open (uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
+static ao_internal_t *ao_null_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 {
 	ao_null_internal_t *state;
 
 	state = malloc(sizeof(ao_null_internal_t));
 
-	if (state != NULL)
-	{
+	if (state != NULL) {
 		state->byte_counter = 0;
 		return state;
-	}
-	else
+	} else {
 		return NULL;
+	}
+
+	return NULL;
 }
 
-static void
-ao_null_close (ao_internal_t *state)
+static void ao_null_close(ao_internal_t *state)
 {
+        /* why would we print in a lib :)
 	fprintf(stderr, "ao_null: %ld bytes sent to null device.\n",
 		((ao_null_internal_t *) state)->byte_counter);
+	*/
+	if (state) free(state);
 }
 
-static void
-ao_null_play (ao_internal_t *state, void* output_samples, uint_32 num_bytes)
+static void ao_null_play(ao_internal_t *state, void* output_samples, uint_32 num_bytes)
 {
-	((ao_null_internal_t *) state)->byte_counter += num_bytes;
+	((ao_null_internal_t *)state)->byte_counter += num_bytes;
 }
 
-static ao_info_t*
-ao_null_get_driver_info (void)
+static ao_info_t *ao_null_get_driver_info(void)
 {
 	return &ao_null_info;
 }
 
-ao_functions_t ao_null = 
-{
+ao_functions_t ao_null = {
 	ao_null_get_driver_info,
 	ao_null_open,
 	ao_null_play,
 	ao_null_close
 };
-
diff --git a/src/ao_wav.c b/src/ao_wav.c
index 0d2167b1a4caae3c5e608c828449b7ae3fd767a7..97af8bd31b3aa19f4dc5f2530581f950c91bf2a8 100644
--- a/src/ao_wav.c
+++ b/src/ao_wav.c
@@ -5,7 +5,7 @@
  *      Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
  *
- *  This file is part of libao, a cross-platform library.  See
+ *  This file is part of libao, a cross-platform audio output library.  See
  *  README for a history of this source code.
  *
  *  libao is free software; you can redistribute it and/or modify
@@ -31,7 +31,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
-
 #include <ao/ao.h>
 
 #define WAVE_FORMAT_PCM  0x0001
@@ -51,11 +50,10 @@
 
 #define DEFAULT_SWAP_BUFFER_SIZE 2048
 
-struct riff_struct 
-{
-  unsigned char id[4];   /* RIFF */
-  unsigned int len;
-  unsigned char wave_id[4]; /* WAVE */
+struct riff_struct {
+	unsigned char id[4];   /* RIFF */
+	unsigned int len;
+	unsigned char wave_id[4]; /* WAVE */
 };
 
 
@@ -89,7 +87,7 @@ static ao_info_t ao_wav_info =
 	"WAV file output",
 	"wav",
 	"Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
-	""
+	"Sends output to a .wav file"
 };
 
 typedef struct ao_wav_internal_s
@@ -118,13 +116,11 @@ static void (*old_sig)(int);
 static void signal_handler(int sig);
 
 
-static void
-ao_wav_parse_options(ao_wav_internal_t *state, ao_option_t *options)
+static void ao_wav_parse_options(ao_wav_internal_t *state, ao_option_t *options)
 {
 	state->output_file = NULL;
 
-	while (options)
-	{
+	while (options) {
 		if (!strcmp(options->key, "file"))
 			state->output_file = strdup(options->value);
 		
@@ -135,8 +131,7 @@ ao_wav_parse_options(ao_wav_internal_t *state, ao_option_t *options)
 		state->output_file = strdup("output.wav");
 }
 
-static ao_internal_t*
-ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
+static ao_internal_t *ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 {
 	ao_wav_internal_t *state;
 	unsigned char buf[WAV_HEADER_LEN];
@@ -144,8 +139,7 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 	memset(buf, 0, WAV_HEADER_LEN);
 
 	state = malloc(sizeof(ao_wav_internal_t));
-	if (state == NULL)
-	{
+	if (state == NULL) {
 		fprintf(stderr, "ao_wav: Could not allocate state memory.\n");
 		goto ERR;
 	}
@@ -153,13 +147,11 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 	// Grab options here
 	ao_wav_parse_options(state, options);
 	state->byte_swap = (bits == 16) && (ao_is_big_endian());
-	if (state->byte_swap)
-	{
+	if (state->byte_swap) {
 		state->buffer_size = DEFAULT_SWAP_BUFFER_SIZE;
 		state->swap_buffer = calloc(sizeof(char), state->buffer_size);
 	       
-		if (state->swap_buffer == NULL)
-		{
+		if (state->swap_buffer == NULL) {
 			fprintf(stderr, "ao_wav: Could not allocate byte-swapping buffer.\n");
 			goto ERR;
 		}
@@ -167,8 +159,7 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 		
 	state->fd=open(state->output_file,O_WRONLY | O_TRUNC | O_CREAT, 0644);
 
-	if(state->fd < 0) 
-	{
+	if(state->fd < 0) {
 		fprintf(stderr,"%s: Opening audio output %s\n", strerror(errno), state->output_file);
 		goto ERR;
 	}
@@ -181,21 +172,17 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 	state->wave.common.wBitsPerSample = bits;
 	state->wave.common.dwSamplesPerSec = rate;
 
-	if (write(state->fd, buf, WAV_HEADER_LEN) != WAV_HEADER_LEN) 
-	{
+	if (write(state->fd, buf, WAV_HEADER_LEN) != WAV_HEADER_LEN) {
 		fprintf(stderr,"failed to write wav-header: %s\n", strerror(errno));
 		goto ERR;
 	}
 
-	if (last == NULL) 
-	{
+	if (last == NULL) {
 		// Empty list, install our signal handler only once
 		old_sig = signal(SIGINT,signal_handler);		
 
 		last = states = malloc(sizeof(ao_wav_state_list_t));
-	}
-	else
-	{
+	} else {
 		last->next = malloc(sizeof(ao_wav_state_list_t));
 		last = last->next;
 	}
@@ -205,7 +192,6 @@ ao_wav_open(uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 
 	return state;
 
-
 ERR:
 	if(state->fd >= 0) { close(state->fd); }
 	return NULL;
@@ -215,44 +201,39 @@ ERR:
 /*
  * play the sample to the already opened file descriptor
  */
-static void
-ao_wav_play(ao_internal_t *state, void *output_samples, uint_32 num_bytes)
+static void ao_wav_play(ao_internal_t *state, void *output_samples, uint_32 num_bytes)
 {
 	int i;
-	ao_wav_internal_t *s = (ao_wav_internal_t *) state;
+	ao_wav_internal_t *s = (ao_wav_internal_t *)state;
 
 	/* Swap all of the bytes if things are not little_endian */
-	if (s->byte_swap)
-	{
+	if (s->byte_swap) {
 		/* Resize buffer larger if needed */
-		if (num_bytes > s->buffer_size)
-		{
+		if (num_bytes > s->buffer_size) {
 			s->swap_buffer = realloc(s->swap_buffer, sizeof(char)*num_bytes);
 			if (s->swap_buffer == NULL) {
 				fprintf(stderr, "ao_wav: Could not resize swap buffer.\n");
 				return;
-			}
-			else
+			} else {
 				s->buffer_size = num_bytes;
+			}
 		}
 
 		/* Swap the bytes into the swap buffer (so we don't
 		 mess up the output_samples buffer) */
-		for(i = 0; i < num_bytes/2; i+=2)
-		{
+		for(i = 0; i < num_bytes/2; i+=2) {
 			s->swap_buffer[i]   = ((char *) output_samples)[i+1];
 			s->swap_buffer[i+1] = ((char *) output_samples)[i];
 		}
 
 		write(s->fd, s->swap_buffer, num_bytes );
-	}
-	else    /* Otherwise just write the output buffer directly */
+	} else {
+		/* Otherwise just write the output buffer directly */
 		write(s->fd, output_samples, num_bytes );
+	}
 }
 
-
-static void
-ao_wav_close(ao_internal_t *state)
+static void ao_wav_close(ao_internal_t *state)
 {
 	unsigned char buf[WAV_HEADER_LEN];
 
@@ -263,20 +244,18 @@ ao_wav_close(ao_internal_t *state)
 	/* Find how long our file is in total, including header */
 	size = lseek(s->fd, 0, SEEK_CUR);
 
-  if (size < 0) 
-	{
+	if (size < 0) {
 		fprintf(stderr,"lseek failed - wav-header is corrupt\n");
 		goto ERR;
 	}
 
-  /* Rewind file */
-	if (lseek(s->fd, 0, SEEK_SET) < 0) 
-	{
+	/* Rewind file */
+	if (lseek(s->fd, 0, SEEK_SET) < 0) {
 		fprintf(stderr,"rewind failed - wav-header is corrupt\n");
 		goto ERR;
 	}
 
-	// Fill out our wav-header with some information. 
+	/* Fill out our wav-header with some information. */
 
 	strncpy(s->wave.riff.id, "RIFF",4);
 	s->wave.riff.len = size - 8;
@@ -311,8 +290,7 @@ ao_wav_close(ao_internal_t *state)
 	strncpy(buf+36, s->wave.data.id, 4);
 	WRITE_U32(buf+40, s->wave.data.len);
 
-	if (write(s->fd, buf, WAV_HEADER_LEN) < WAV_HEADER_LEN) 
-	{
+	if (write(s->fd, buf, WAV_HEADER_LEN) < WAV_HEADER_LEN) {
 		fprintf(stderr,"wav-header write failed -- file is corrupt\n");
 		goto ERR;
 	}
@@ -322,20 +300,17 @@ ERR:
 	free(s);
 }
 
-static ao_info_t*
-ao_wav_get_driver_info(void)
+static ao_info_t *ao_wav_get_driver_info(void)
 {
 	return &ao_wav_info;
 }
 
 
-static 
-void signal_handler(int sig)
+static void signal_handler(int sig)
 {
 	ao_wav_state_list_t *temp = states;
 	
-	while (states)
-	{
+	while (states) {
 		ao_wav_close(states->state);
 		temp = states;
 		states = states->next;
diff --git a/src/audio_out.c b/src/audio_out.c
index 4812cd8b7ef37440e6f86d9ffdd5c09abf0fcfb1..93395e607947551e252eb380f246b796305dcc06 100644
--- a/src/audio_out.c
+++ b/src/audio_out.c
@@ -5,7 +5,7 @@
  *      Original Copyright (C) Aaron Holtzman - May 1999
  *      Modifications Copyright (C) Stan Seibert - July 2000
  *
- *  This file is part of libao, a cross-platform library.  See
+ *  This file is part of libao, a cross-platform audio output library.  See
  *  README for a history of this source code.
  *
  *  libao is free software; you can redistribute it and/or modify
@@ -27,113 +27,154 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
 #include <ao/ao.h>
 
-/* --- Function Tables --- */
-
-extern ao_functions_t ao_null;
-
-/* Okay, so this is messy.  I'm open to ideas of how to clean this
-   up.  - Stan */
-
-#ifdef AO_COMPILE_OSS
-extern ao_functions_t ao_oss;
-#define AO_FUNC_OSS &ao_oss
-#else
-#define AO_FUNC_OSS NULL
-#endif
-
-#ifdef AO_COMPILE_IRIX
-extern ao_functions_t ao_irix;
-#define AO_FUNC_IRIX &ao_irix
-#else
-#define AO_FUNC_IRIX NULL
-#endif
-
-#ifdef AO_COMPILE_SOLARIS
-extern ao_functions_t ao_solaris;
-#define AO_FUNC_SOLARIS &ao_solaris
-#else
-#define AO_FUNC_SOLARIS NULL
+/* These should have been set by the Makefile */
+#ifndef AO_DEFAULT
+#define AO_DEFAULT AO_NULL
 #endif
-
-#ifdef AO_COMPILE_WIN32
-extern ao_functions_t ao_win32;
-#define AO_FUNC_WIN32 &ao_win32
-#else
-#define AO_FUNC_WIN32 NULL
+#ifndef AO_PLUGIN_PATH
+#define AO_PLUGIN_PATH "/usr/local/lib/ao"
 #endif
-
-#ifdef AO_COMPILE_BEOS
-extern ao_functions_t ao_beos;
-#define AO_FUNC_BEOS &ao_beos
-#else
-#define AO_FUNC_BEOS NULL
+#ifndef SHARED_LIB_EXT
+#define SHARED_LIB_EXT ".so"
 #endif
 
-#ifdef AO_COMPILE_ESD
-extern ao_functions_t ao_esd;
-#define AO_FUNC_ESD &ao_esd
-#else
-#define AO_FUNC_ESD NULL
-#endif
+/* --- Driver Table --- */
 
-#ifdef AO_COMPILE_ALSA
-extern ao_functions_t ao_alsa;
-#define AO_FUNC_ALSA &ao_alsa
-#else
-#define AO_FUNC_ALSA NULL
-#endif
+typedef struct driver_tree_s {
+	ao_functions_t *functions;
+	void *handle;
+	struct driver_tree_s *next;
+} driver_tree_t;
 
+extern ao_functions_t ao_null;
 extern ao_functions_t ao_wav;
 
+driver_tree_t *driver_head = NULL;
 
+driver_tree_t *_get_plugin(char *plugin_file)
+{
+	driver_tree_t *dt;
+	void *handle;
+	
+	handle = dlopen(plugin_file, RTLD_NOW);
+	if (handle) {
+		dt = (driver_tree_t *)malloc(sizeof(driver_tree_t));
+		if (!dt) return NULL;
 
-/* --- Driver Table --- */
+		dt->handle = handle;
+		
+		dt->functions = (ao_functions_t *)malloc(sizeof(ao_functions_t));
+		if (!(dt->functions)) {
+			free(dt);
+			return NULL;
+		}
 
-ao_functions_t* ao_drivers[AO_DRIVERS] = 
-{
-	&ao_null,        /* 0: Null Device */
-        AO_FUNC_OSS,     /* 1: Linux, *BSD */ 
-	AO_FUNC_IRIX,    /* 2: IRIX */
-	AO_FUNC_SOLARIS, /* 3: Solaris */
-	AO_FUNC_WIN32,   /* 4: Win32 */
-	AO_FUNC_BEOS,    /* 5: BeOS */
-	AO_FUNC_ESD,     /* 6: EsounD */
-	AO_FUNC_ALSA,    /* 7: ALSA */
-	NULL,            /* 8: Unassigned */
-	NULL,            /* 9: Unassigned */
-	&ao_wav,         /* 10: .WAV output */
-	NULL,            /* 11: RAW output */
-};
+		dt->functions->get_driver_info = dlsym(dt->handle, "get_driver_info");
+		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
+		dt->functions->open = dlsym(dt->handle, "open");
+		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
+		dt->functions->play = dlsym(dt->handle, "play");
+		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
+		dt->functions->close = dlsym(dt->handle, "close");
+		if (dlerror()) { free(dt->functions); free(dt); return NULL; }
+	} else {
+		return NULL;
+	}
 
+	return dt;
+}
 
+void ao_initialize(void)
+{
+	driver_tree_t *dnull;
+	driver_tree_t *dwav;
+	driver_tree_t *plugin;
+	driver_tree_t *driver;
+	DIR *plugindir;
+	struct dirent *plugin_dirent;
+	char *ext;
+	struct stat statbuf;
+	void *plughand;
+	char fullpath[NAME_MAX];
+
+	if (driver_head == NULL) {
+		/* insert the null and wav drivers into the tree */
+		dnull = (driver_tree_t *)malloc(sizeof(driver_tree_t));
+		dnull->functions = &ao_null;
+		dnull->handle = NULL;
+		dwav = (driver_tree_t *)malloc(sizeof(driver_tree_t));
+		dwav->functions = &ao_wav;
+		dwav->handle = NULL;
+		
+		dnull->next = dwav;
+		dwav->next = NULL;
+
+		driver_head = dnull;		
+		driver = dwav;
+
+		/* now insert any plugins we find */
+		plugindir = opendir(AO_PLUGIN_PATH);
+		if (plugindir != NULL) {
+			while ((plugin_dirent = readdir(plugindir)) != NULL) {
+				snprintf(fullpath, NAME_MAX, "%s/%s", AO_PLUGIN_PATH, plugin_dirent->d_name);
+				if (!stat(fullpath, &statbuf) && S_ISREG(statbuf.st_mode) && (ext = strrchr(plugin_dirent->d_name, '.')) != NULL) {
+					if (strcmp(ext, SHARED_LIB_EXT) == 0) {
+						plugin = _get_plugin(fullpath);
+						if (plugin) {
+							driver->next = plugin;
+							plugin->next = NULL;
+						}
+					}
+				}
+			}
+			
+			closedir(plugindir);
+		}
+	}
+}
 
-/* --- Driver Functions --- */
+void ao_shutdown(void)
+{
+	driver_tree_t *driver = driver_head;
+	driver_tree_t *next_driver;
+
+	if (!driver_head) return;
+
+	/* unload and free all the plugins */
+	driver = driver->next->next;
+	while (driver) {
+		if (driver->functions) free(driver->functions);
+		if (driver->handle) dlclose(driver->handle);
+		next_driver = driver->next;
+		free(driver);
+		driver = next_driver;
+	}
 
-/* This should have been set by the Makefile */
-#ifndef AO_DEFAULT
-#define AO_DEFAULT AO_NULL
-#endif
+	/* free the standard drivers */
+	if (driver_head->next) free(driver_head->next);
+	if (driver_head->next) free(driver_head);
+}
 
-int ao_get_driver_id (const char *short_name)
+int ao_get_driver_id(const char *short_name)
 {
 	int i;
+	driver_tree_t *driver = driver_head;
 
-	if (short_name == NULL) 
-		return AO_DEFAULT;
-	else 
-	{
+	if (short_name == NULL) {
+		return AO_NULL;
+	} else {
 		i = 0;
-		while (i < AO_DRIVERS)
-		{
-			/* Skip empty driver slots */
-			if (ao_drivers[i] != NULL
-			    && !strcmp(short_name, 
-				       ao_drivers[i]->get_driver_info()->short_name))
+		while (driver) {
+			if (strcmp(short_name, driver->functions->get_driver_info()->short_name) == 0)
 				return i;
-
+			driver = driver->next;
 			i++;
 		}
 		
@@ -141,17 +182,47 @@ int ao_get_driver_id (const char *short_name)
 	}
 }
 
+driver_tree_t *_get_driver(int driver_id) {
+	int i = 0;
+	driver_tree_t *driver = driver_head;
+
+	if (driver_id < 0) return NULL;
+
+	while (driver && (i < driver_id)) {
+		i++;
+		driver = driver->next;
+	}
+
+	if (i == driver_id) 
+		return driver;
+
+	return NULL;
+}
 
-int ao_check_driver_id (int driver_id)
+int _check_driver_id(int driver_id)
 {
-	return driver_id >= 0 && driver_id < AO_DRIVERS && 
-		ao_drivers[driver_id] != NULL;	
+	int i = 0;
+	driver_tree_t *driver = driver_head;
+
+	if (driver_id < 0) return 0;
+
+	while (driver && (i <= driver_id)) {
+		driver = driver->next;
+		i++;
+	}
+	
+	if (i == (driver_id + 1))
+		return 1;
+
+	return 0;
 }	
 
-ao_info_t *ao_get_driver_info (int driver_id)
+ao_info_t *ao_get_driver_info(int driver_id)
 {
-	if (ao_check_driver_id(driver_id))
-		return ao_drivers[driver_id]->get_driver_info();
+	driver_tree_t *driver;
+
+	if (driver = _get_driver(driver_id))
+		return driver->functions->get_driver_info();
 	else
 		return NULL;
 }
@@ -160,19 +231,17 @@ ao_info_t *ao_get_driver_info (int driver_id)
 
 /* -- Audio Functions --- */
 
-ao_device_t* ao_open (int driver_id, uint_32 bits, uint_32 rate, uint_32 channels, 
-	     ao_option_t *options)
+ao_device_t* ao_open(int driver_id, uint_32 bits, uint_32 rate, uint_32 channels, ao_option_t *options)
 {
 	ao_functions_t *funcs;
 	ao_internal_t *state;
 	ao_device_t *device;
+	driver_tree_t *driver = driver_head;
 
-	if (ao_check_driver_id(driver_id))
-	{
-		funcs = ao_drivers[driver_id];
+	if (driver = _get_driver(driver_id)) {
+		funcs = driver->functions;
 		state = funcs->open(bits, rate, channels, options);
-		if (state != NULL)
-		{
+		if (state != NULL) {
 			device = malloc(sizeof(ao_device_t));
 			device->funcs = funcs;
 			device->state = state;
@@ -183,14 +252,13 @@ ao_device_t* ao_open (int driver_id, uint_32 bits, uint_32 rate, uint_32 channel
 	return NULL;
 }	
 
-void ao_play (ao_device_t *device, void* output_samples, uint_32 num_bytes)
+void ao_play(ao_device_t *device, void* output_samples, uint_32 num_bytes)
 {
-  device->funcs->play(device->state, output_samples,
-		      num_bytes);
+	device->funcs->play(device->state, output_samples, num_bytes);
 }
 
 
-void ao_close (ao_device_t *device)
+void ao_close(ao_device_t *device)
 {
 	device->funcs->close(device->state);
 	free(device);
@@ -200,7 +268,7 @@ void ao_close (ao_device_t *device)
 
 /* --- Option Functions --- */
 
-ao_option_t* ao_parse_option (const char* op_str)
+ao_option_t* _parse_option(const char* op_str)
 {
 	char *copy;
 	char *value_ptr;
@@ -210,15 +278,13 @@ ao_option_t* ao_parse_option (const char* op_str)
         copy = strdup(op_str);
 	
         colon = strchr(copy, ':');
-        if (colon != NULL) 
-        {
+        if (colon != NULL) {
                 value_ptr = colon + 1;
                 *colon = 0x00; // Null terminate the key part
                 
-                // Allocate the option structure
+                /* Allocate the option structure */
                 op = malloc(sizeof(ao_option_t));
-                if (op != NULL)
-                {
+                if (op != NULL) {
                         op->key = strdup(copy);
                         op->value = strdup(value_ptr);
                         op->next = NULL;
@@ -230,25 +296,20 @@ ao_option_t* ao_parse_option (const char* op_str)
 }
 
 
-int ao_append_option (ao_option_t **options, const char *op_str)
+int ao_append_option(ao_option_t **options, const char *op_str)
 {
 	ao_option_t *temp;
 
-	temp = ao_parse_option(op_str);
+	temp = _parse_option(op_str);
 
 	if (temp == NULL)
 		return 0; //Bad option format
 
-	if (*options != NULL)
-	{
+	if (*options != NULL) {
 		while ((*options)->next != NULL)
-		{
 			*options = (*options)->next;
-		}
 		(*options)->next = temp;
-	}
-	else
-	{
+	} else {
 		*options = temp;
 	}
 
@@ -256,12 +317,11 @@ int ao_append_option (ao_option_t **options, const char *op_str)
 }
 
 
-void ao_free_options (ao_option_t* options)
+void ao_free_options(ao_option_t *options)
 {
 	ao_option_t *rest;
 
-	while (options != NULL)
-	{
+	while (options != NULL) {
 		rest = options->next;
 		free(options->key);
 		free(options->value);
@@ -270,12 +330,12 @@ void ao_free_options (ao_option_t* options)
 	}
 }
 
-/* Helper function lifted from lib/vorbisfile.c */
-int ao_is_big_endian() {
+/* Helper function lifted from Vorbis' lib/vorbisfile.c */
+int ao_is_big_endian(void) 
+{
 	uint_16 pattern = 0xbabe;
 	unsigned char *bytewise = (unsigned char *)&pattern;
+
 	if (bytewise[0] == 0xba) return 1;
-	
-	assert(bytewise[0] == 0xbe);
 	return 0;
 }
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..8d2b180e795049a5d928ea31b41d9d6d4300eaa9
--- /dev/null
+++ b/src/plugins/Makefile.am
@@ -0,0 +1,4 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+SUBDIRS = oss esd alsa # solaris irix
diff --git a/src/plugins/alsa/Makefile.am b/src/plugins/alsa/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..5485bf873540d4e4c04e1498fb0c4dae9c2d1808
--- /dev/null
+++ b/src/plugins/alsa/Makefile.am
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+if HAVE_ALSA
+
+alsaltlibs = libalsa.la
+alsaldflags = -export-dynamic -avoid-version
+alsasources = ao_alsa.c
+
+else
+
+alsaltlibs =
+alsaldflags =
+alsasources =
+
+endif
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include
+
+libdir = $(plugindir)
+lib_LTLIBRARIES = $(alsaltlibs)
+
+libalsa_la_LDFLAGS = $(alsaldflags)
+libalsa_la_SOURCES = $(alsasources)
+
+EXTRA_DIST = ao_alsa.c
diff --git a/src/ao_alsa.c b/src/plugins/alsa/ao_alsa.c
similarity index 100%
rename from src/ao_alsa.c
rename to src/plugins/alsa/ao_alsa.c
diff --git a/src/plugins/esd/Makefile.am b/src/plugins/esd/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..ab1a56785465309e5052443198fef90dad7d9d1a
--- /dev/null
+++ b/src/plugins/esd/Makefile.am
@@ -0,0 +1,28 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+if HAVE_ESD
+
+esdltlibs = libesd.la
+esdldflags = -export-dynamic -avoid-version
+esdsources = ao_esd.c
+
+else
+
+esdltlibs =
+esdldflags =
+esdsources =
+
+endif
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include @ESD_CFLAGS@
+
+libdir = $(plugindir)
+lib_LTLIBRARIES = $(esdltlibs)
+
+libesd_la_LDFLAGS = $(esdldflags)
+libesd_la_LIBADD = @ESD_LIBS@
+libesd_la_SOURCES = $(esdsources)
+
+EXTRA_DIST = ao_esd.c
diff --git a/src/ao_esd.c b/src/plugins/esd/ao_esd.c
similarity index 99%
rename from src/ao_esd.c
rename to src/plugins/esd/ao_esd.c
index 0e3b66d37f5c60189f71d86e36e5e93b924d11fe..fad7193135a7cf38c7848c9551130f0597be0feb 100644
--- a/src/ao_esd.c
+++ b/src/plugins/esd/ao_esd.c
@@ -31,7 +31,7 @@
 #include <string.h>
 
 #include <esd.h>
-#include "audio_out.h"
+#include <ao/ao.h>
 
 typedef struct ao_esd_internal_s
 {
diff --git a/src/ao_irix.c b/src/plugins/irix/ao_irix.c
similarity index 100%
rename from src/ao_irix.c
rename to src/plugins/irix/ao_irix.c
diff --git a/src/plugins/oss/Makefile.am b/src/plugins/oss/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..3703a23b6d13347b8513b1bea936994aa607e508
--- /dev/null
+++ b/src/plugins/oss/Makefile.am
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = foreign
+
+if HAVE_OSS
+
+ossltlibs = liboss.la
+ossldflags = -export-dynamic -avoid-version
+osssources = ao_oss.c
+
+else
+
+ossltlibs =
+ossldflags =
+osssources =
+
+endif
+
+INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include
+
+libdir = $(plugindir)
+lib_LTLIBRARIES = $(ossltlibs)
+
+liboss_la_LDFLAGS = $(ossldflags)
+liboss_la_SOURCES = $(osssources)
+
+EXTRA_DIST = ao_oss.c
diff --git a/src/ao_oss.c b/src/plugins/oss/ao_oss.c
similarity index 100%
rename from src/ao_oss.c
rename to src/plugins/oss/ao_oss.c
diff --git a/src/ao_solaris.c b/src/plugins/solaris/ao_solaris.c
similarity index 100%
rename from src/ao_solaris.c
rename to src/plugins/solaris/ao_solaris.c