From 2ab3d99967d68c79351fe2a3df22c445447e3010 Mon Sep 17 00:00:00 2001
From: Michał Cichoń <michcic@gmail.com>
Date: Tue, 15 Nov 2011 22:28:48 +0100
Subject: Initial import.

---
 libao/libao.vcproj                |  205 +++++
 libao/src/AUTHORS                 |    4 +
 libao/src/CHANGES                 |  103 +++
 libao/src/COPYING                 |  340 +++++++++
 libao/src/README                  |   70 ++
 libao/src/include/ao/ao.h         |  139 ++++
 libao/src/include/ao/ao_private.h |  211 ++++++
 libao/src/include/ao/os_types.h   |   39 +
 libao/src/include/ao/plugin.h     |   51 ++
 libao/src/src/ao_aixs.c           |  256 +++++++
 libao/src/src/ao_au.c             |  250 ++++++
 libao/src/src/ao_null.c           |  153 ++++
 libao/src/src/ao_raw.c            |  160 ++++
 libao/src/src/ao_wav.c            |  291 +++++++
 libao/src/src/ao_wmm.c            |  645 ++++++++++++++++
 libao/src/src/audio_out.c         | 1514 +++++++++++++++++++++++++++++++++++++
 libao/src/src/config.c            |  111 +++
 17 files changed, 4542 insertions(+)
 create mode 100644 libao/libao.vcproj
 create mode 100644 libao/src/AUTHORS
 create mode 100644 libao/src/CHANGES
 create mode 100644 libao/src/COPYING
 create mode 100644 libao/src/README
 create mode 100644 libao/src/include/ao/ao.h
 create mode 100644 libao/src/include/ao/ao_private.h
 create mode 100644 libao/src/include/ao/os_types.h
 create mode 100644 libao/src/include/ao/plugin.h
 create mode 100644 libao/src/src/ao_aixs.c
 create mode 100644 libao/src/src/ao_au.c
 create mode 100644 libao/src/src/ao_null.c
 create mode 100644 libao/src/src/ao_raw.c
 create mode 100644 libao/src/src/ao_wav.c
 create mode 100644 libao/src/src/ao_wmm.c
 create mode 100644 libao/src/src/audio_out.c
 create mode 100644 libao/src/src/config.c

(limited to 'libao')

diff --git a/libao/libao.vcproj b/libao/libao.vcproj
new file mode 100644
index 0000000..d1fc210
--- /dev/null
+++ b/libao/libao.vcproj
@@ -0,0 +1,205 @@
+<?xml version="1.0" encoding="windows-1250"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9,00"
+	Name="libao"
+	ProjectGUID="{75E224E3-6A99-4C8F-9598-9A6F115B91F2}"
+	RootNamespace="libao"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="131072"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)build\temp\lib\"
+			IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="0"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="$(ProjectDir)src\include\"
+				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
+				MinimalRebuild="false"
+				ExceptionHandling="0"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
+				WarningLevel="3"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\$(ProjectName)-mt-debug.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy &quot;$(ProjectDir)src\include\ao\ao.h&quot; &quot;$(SolutionDir)build\temp\include\ao\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\ao\os_types.h&quot; &quot;$(SolutionDir)build\temp\include\ao\&quot; /I /Y /D&#x0D;&#x0A;"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)build\temp\lib\"
+			IntermediateDirectory="$(SolutionDir)build\temp\obj\$(ProjectName)\$(ConfigurationName)"
+			ConfigurationType="4"
+			CharacterSet="0"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				AdditionalIncludeDirectories="$(ProjectDir)src\include\"
+				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;AO_BUILDING_LIBAO;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS"
+				ExceptionHandling="0"
+				RuntimeLibrary="0"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(IntDir)\vc90.pdb"
+				WarningLevel="3"
+				DebugInformationFormat="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLibrarianTool"
+				OutputFile="$(OutDir)\$(ProjectName)-mt.lib"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+				CommandLine="xcopy &quot;$(ProjectDir)src\include\ao\ao.h&quot; &quot;$(SolutionDir)build\temp\include\ao\&quot; /I /Y /D&#x0D;&#x0A;xcopy &quot;$(ProjectDir)src\include\ao\os_types.h&quot; &quot;$(SolutionDir)build\temp\include\ao\&quot; /I /Y /D&#x0D;&#x0A;"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Sources"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\src\src\ao_null.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\src\ao_wmm.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\src\audio_out.c"
+				>
+			</File>
+			<File
+				RelativePath=".\src\src\config.c"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Include"
+			>
+			<Filter
+				Name="ao"
+				>
+				<File
+					RelativePath=".\src\include\ao\ao.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\include\ao\ao_private.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\include\ao\os_types.h"
+					>
+				</File>
+				<File
+					RelativePath=".\src\include\ao\plugin.h"
+					>
+				</File>
+			</Filter>
+		</Filter>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
diff --git a/libao/src/AUTHORS b/libao/src/AUTHORS
new file mode 100644
index 0000000..30f7267
--- /dev/null
+++ b/libao/src/AUTHORS
@@ -0,0 +1,4 @@
+Aaron Holtzman
+Stan Seibert <indigo@aztec.asu.edu>
+Jack Moffitt <jack@icecast.org>
+Ralph Giles <giles@ashlu.bc.ca>
diff --git a/libao/src/CHANGES b/libao/src/CHANGES
new file mode 100644
index 0000000..99787b7
--- /dev/null
+++ b/libao/src/CHANGES
@@ -0,0 +1,103 @@
+1.1.0 - February 21, 2011
+ - Add autofoo ld symbol versioning to build system
+ - Update Roar driver to latest API
+ - Fix Roar driver to not block on SLP lookup during probe
+ - Improve/correct latency setup in ALSA (see Trac #1762)
+ - Add missing ctype.h header in build (see Trac #1760)
+ - Move toward more consistent option naming across drivers
+ - Fix Mac OS X AUHAL support to properly handle suspend/wakeup,
+   headphone plug/unplug, other hardware events
+ - Correct ao_example.c source to not pass dangling pointer for 
+   the matrix argument.
+ - Add 24 bit playback to Pulse plugin
+ - Fix 24 bit playback in ALSA plugin
+ - Fix segfaults when closing a driver that did not successfully open.
+ - Fix compilation of sndio plugin
+ - Fix building Mac OS X driver AUHAL compilation for 10.5,
+   restore Mac OS X 10.4 support
+
+1.0.0 - March 25, 2010
+ - AO returns to active development
+ - Added surround channel mapping API and capability
+ - Update and test all drivers on modern installs
+ - New config file options
+ - Driver options may be specifid in config file
+ - Support for MacosX < 10.5 dropped, driver modded to AUHAL
+ - Build in WMM driver rather than using dlopen()
+ - Added Roar Audio driver
+ - Added OpenBSD SNDIO driver
+ - Work around ESD non-4096 byte write bug
+ - Work around aRts server crash bug
+ - Workaround for VIA82xx click/crackle bugs under ALSA
+ - Remove dead/unused drivers (solaris, alasa05, mmsound)
+ - Numerous patches from multiple downstreams
+
+0.8.8 - May 24, 2007
+ - New win32 driver
+ - Few fixes and changes in autotools and configuration files.
+
+0.8.7 - unreleased snapshot
+- obsolete alsa device renamed to alsa05
+- the 'alsa' device now uses the 0.9/1.0 API
+- ALSA driver fixes
+
+0.8.6 - January 11, 2005
+- Added Polypaudio driver(libao-polyp 0.4) 
+  from Lennart Poettering <mzyvonbcbylc (at) 0pointer (dot) de>
+- Use esd_close() in the esd driver
+- Broaden sample rate tolerance in the OSS driver for nForce 
+  compatibility
+
+0.8.5 - March 19, 2004
+- Support now for the ALSA 1.0 API
+- Can build with --disable-esd option again
+- Minor build fixes
+- ALSA mmap() mode can be enabled/disabled at runtime using "use_mmap"
+  option.
+- Patch to OSS plugin to fix skipping issues with some drivers
+  (like emu10k1).
+
+0.8.4 - October 4, 2003
+- Added AIX sound driver from Stefan Tibus <sjti@gmx.net>
+- Committed some fixes from the Fink project to allow compiling on
+  OS X (still with all the dlcompat stuff)
+- Improvements in plugin detection code by David Walser, especially
+  when ESD or aRts are present.
+- NAS plugin from Antoine Mathys.
+- Portability fixes for various platforms (including dlopen() bugs) 
+  including HP-UX and *BSD.
+- Memory/resource leak fixes
+- Significant fixes to ALSA 0.9.x plugin by Kevin Cody, Jr.  This
+  should fix stuttering audio for mpg321 users.  The
+  --enable-alsa09-mmap option to ./configure turns on memory-mapped
+  I/O.  Note this is an experimental feature and causes some problems
+  with some sound card drivers and also users of the dmix software mixer.
+
+0.8.3 - July 2002
+- fix to ao.m4 macro
+- minor alsa09 plugin updates
+- fixes to irix plugin
+
+0.8.2 - December 2001
+- alsa09 plugin updated
+
+0.8.0 - August 2000
+- Major API rewrite.  Old apps and plugins will not work with this library!
+- Default driver detection now works.
+- /etc/libao.conf and ~/.libao config files now supported, see libao.conf man
+  page for details.
+- WAV files can now be piped to non-picky applications.  (Please don't
+  complain if this fails.  You shouldn't be using be using WAV for this
+  anyway.)
+- Various portability fixes for Solaris and *BSD.
+
+0.7.0 - June 2000
+- minor build fixes for different platforms
+
+0.6.0 - December 2000
+- slight api modification with ao_append_option()
+- fixed an option leak
+
+0.5.0 - November 2000
+- first official release under the Xiphophorus projects
+
diff --git a/libao/src/COPYING b/libao/src/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/libao/src/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/libao/src/README b/libao/src/README
new file mode 100644
index 0000000..6a08b56
--- /dev/null
+++ b/libao/src/README
@@ -0,0 +1,70 @@
+libao - A Cross-platform Audio Library, Version 0.8.6
+
+Originally Copyright (C) Aaron Holtzman - May 1999
+Changes Copyright (C) Jack Moffitt - October 2000
+Changes Copyright (C) Stan Seibert - July 2000-March 2004
+libao-pulse Copyright (C) Lennart Poettering 2004-2006
+Changes Copyright (C) 2004-2005 Xiph.org Foundation 
+Changes Maintainer Benjamin Gerard
+
+libao is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+libao is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Make; see the file COPYING.  If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+---------------------------------------------------------------------
+
+OVERVIEW
+
+Libao is a cross-platform audio library that allows programs to output
+audio using a simple API on a wide variety of platforms.  It currently
+supports:
+   * Null output
+   * WAV files
+   * OSS (Open Sound System)
+   * ESD (ESounD or Enlightened Sound Daemon)
+   * ALSA (Advanced Linux Sound Architecture)
+   * PulseAudio (next generation GNOME sound server)
+   * AIX
+   * Solaris (untested)
+   * IRIX (untested)
+
+HISTORY
+
+Libao began life as cross-platform audio library inside of ac3dec, an
+AC3 decoder by Aaron Holtzman that is part of the LiViD project.  When
+ogg123 (part of the command line vorbis tools) needed a way to play
+audio on multiple operating systems, someone on the vorbis-dev mailing
+list suggested the libao library as a possible way to add cross-platform 
+support to ogg123. Stan Seibert downloaded the libao library, severely 
+hacked it up in order to make the build process simpler and support 
+multiple live-playback devices. (The original code allowed one live 
+playback driver, the wav driver, and a null driver to be compiled into 
+the library.) Jack Moffitt got it supporting dynamically loaded plugins 
+so that binary versions of libao could be provided. The API was revised 
+for version 0.8.0.
+
+This code is being maintained by Stan Seibert (volsung@xiph.org) 
+and various other individuals.  Please DO NOT annoy Aaron Holtzman about 
+bugs, features, comments, etc. regarding this code.
+
+WORKAROUNDS
+
+The OSS emulation in ALSA deviates from the OSS spec by not returning
+immediately from an open() call if the OSS device is already in use.
+Instead, it makes the application wait until the device is available.
+This is not desirable during the autodetection phase of libao, so a
+workaround has been included in the source.  Since the workaround
+itself violates the OSS spec and causes other problems on some
+platforms, it is only enabled when ALSA is detected.  The workaround
+can be turned on or off by passing the --enable-broken-oss or
+--disable-broken-oss flag to the configure script.
diff --git a/libao/src/include/ao/ao.h b/libao/src/include/ao/ao.h
new file mode 100644
index 0000000..cb8c035
--- /dev/null
+++ b/libao/src/include/ao/ao.h
@@ -0,0 +1,139 @@
+/*
+ *
+ *  ao.h 
+ *
+ *	Original Copyright (C) Aaron Holtzman - May 1999
+ *      Modifications Copyright (C) Stan Seibert - July 2000, July 2001
+ *      More Modifications Copyright (C) Jack Moffitt - October 2000
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __AO_H__
+#define __AO_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "os_types.h"
+
+/* --- Constants ---*/
+
+#define AO_TYPE_LIVE 1
+#define AO_TYPE_FILE 2
+
+
+#define AO_ENODRIVER   1
+#define AO_ENOTFILE    2
+#define AO_ENOTLIVE    3
+#define AO_EBADOPTION  4
+#define AO_EOPENDEVICE 5
+#define AO_EOPENFILE   6
+#define AO_EFILEEXISTS 7
+#define AO_EBADFORMAT  8
+
+#define AO_EFAIL       100
+
+
+#define AO_FMT_LITTLE 1
+#define AO_FMT_BIG    2
+#define AO_FMT_NATIVE 4
+
+/* --- Structures --- */
+
+typedef struct ao_info {
+	int  type; /* live output or file output? */
+	char *name; /* full name of driver */
+	char *short_name; /* short name of driver */
+        char *author; /* driver author */
+	char *comment; /* driver comment */
+	int  preferred_byte_format;
+	int  priority;
+	char **options;
+	int  option_count;
+} ao_info;
+
+typedef struct ao_functions ao_functions;
+typedef struct ao_device ao_device;
+
+typedef struct ao_sample_format {
+	int  bits; /* bits per sample */
+	int  rate; /* samples per second (in a single channel) */
+	int  channels; /* number of audio channels */
+	int  byte_format; /* Byte ordering in sample, see constants below */
+        char *matrix; /* input channel location/ordering */
+} ao_sample_format;
+
+typedef struct ao_option {
+	char *key;
+	char *value;
+	struct ao_option *next;
+} ao_option;
+
+#if defined(AO_BUILDING_LIBAO)
+#include "ao_private.h"
+#endif
+
+/* --- Functions --- */
+
+/* library setup/teardown */
+void ao_initialize(void);
+void ao_shutdown(void);
+
+/* device setup/playback/teardown */
+int   ao_append_global_option(const char *key,
+                              const char *value);
+int          ao_append_option(ao_option **options,
+                              const char *key,
+                              const char *value);
+void          ao_free_options(ao_option *options);
+ao_device*       ao_open_live(int driver_id,
+                              ao_sample_format *format,
+                              ao_option *option);
+ao_device*       ao_open_file(int driver_id,
+                              const char *filename,
+                              int overwrite,
+                              ao_sample_format *format,
+                              ao_option *option);
+
+int                   ao_play(ao_device *device,
+                              char *output_samples,
+                              uint_32 num_bytes);
+int                  ao_close(ao_device *device);
+
+/* driver information */
+int              ao_driver_id(const char *short_name);
+int      ao_default_driver_id(void);
+ao_info       *ao_driver_info(int driver_id);
+ao_info **ao_driver_info_list(int *driver_count);
+char       *ao_file_extension(int driver_id);
+
+/* miscellaneous */
+int          ao_is_big_endian(void);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* __AO_H__ */
diff --git a/libao/src/include/ao/ao_private.h b/libao/src/include/ao/ao_private.h
new file mode 100644
index 0000000..5d4dfd6
--- /dev/null
+++ b/libao/src/include/ao/ao_private.h
@@ -0,0 +1,211 @@
+/*
+ *
+ *  ao_private.c
+ *
+ *       Copyright (C) Stan Seibert - July 2001
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __AO_PRIVATE_H__
+#define __AO_PRIVATE_H__
+
+/* --- Operating System Compatibility --- */
+
+/*
+  OpenBSD systems with a.out binaries require dlsym()ed symbols to be
+  prepended with an underscore, so we need the following nasty #ifdef
+  hack.
+*/
+#if defined(__OpenBSD__) && !defined(__ELF__)
+#define dlsym(h,s) dlsym(h, "_" s)
+#endif
+
+/* RTLD_NOW is the preferred symbol resolution behavior, but
+ * some platforms do not support it.  The autoconf script will have
+ * already defined DLOPEN_FLAG if the default is unacceptable on the
+ * current platform.
+ *
+ * ALSA requires RTLD_GLOBAL.
+ */
+#if !defined(DLOPEN_FLAG)
+#define DLOPEN_FLAG (RTLD_NOW | RTLD_GLOBAL)
+#endif
+
+/* --- Constants --- */
+
+#ifndef AO_SYSTEM_CONFIG
+#define AO_SYSTEM_CONFIG "/etc/libao.conf"
+#endif
+#ifndef AO_USER_CONFIG
+#define AO_USER_CONFIG   "/.libao"
+#endif
+
+/* --- Structures --- */
+
+typedef struct ao_config {
+	char *default_driver;
+} ao_config;
+
+typedef enum {
+  AO_OUTPUT_MATRIX_UNDEFINED=0,   /* matrix unset */
+  AO_OUTPUT_MATRIX_FIXED=1,       /* fixed, immutable channel order, eg, ALSA */
+  AO_OUTPUT_MATRIX_COLLAPSIBLE=2, /* fixed order but only used channels sent, eg MACOS */
+  AO_OUTPUT_MATRIX_PERMUTABLE=3,  /* channel map is fully permutable. eg Pulse */
+} ao_outorder;
+
+struct ao_device {
+	int  type; /* live output or file output? */
+	int  driver_id;
+	ao_functions *funcs;
+	FILE *file; /* File for output if this is a file driver */
+
+  /* input not necessarily == output. Right now, byte order, channel
+     count, and channel mappings may be altered. */
+
+	int  client_byte_format;
+	int  machine_byte_format;
+	int  driver_byte_format;
+	char *swap_buffer;
+	int  swap_buffer_size; /* Bytes allocated to swap_buffer */
+
+        int input_channels;
+        int output_channels;
+        int bytewidth;
+        int rate;
+
+        ao_outorder output_matrix_order;
+        char *output_matrix;  /* physical output channel
+                                 ordering/numbering matrix set by
+                                 driver if there's a channel
+                                 name->number mapping useful to the
+                                 backend driver in some way.  Eg,
+                                 Pulse has fully permutable input
+                                 channel masks, but specific channels
+                                 locations (eg, 'Center') still have
+                                 assigned numbers even if not a
+                                 specific slot int he input
+                                 interleave. */
+        int   output_mask;
+        int  *input_map;      /* input permutation mapping from each
+                                 input channel to a location in the
+                                 output_matrix. Made by ao_open,
+                                 intended for convenience use by
+                                 driver in device open. */
+
+        char *inter_matrix;   /* channel matrix as presented to the
+                                 backend API */
+        int  *inter_permute;  /* maps from each channel in the
+                                 inter_matrix back to an input channel
+                                 (if any) */
+
+	void *internal;       /* Pointer to driver-specific data */
+
+        int verbose;
+};
+
+struct ao_functions {
+	int (*test)(void);
+	ao_info* (*driver_info)(void);
+	int (*device_init)(ao_device *device);
+	int (*set_option)(ao_device *device, const char *key,
+			  const char *value);
+	int (*open)(ao_device *device, ao_sample_format *format);
+	int (*play)(ao_device *device, const char *output_samples,
+			   uint_32 num_bytes);
+	int (*close)(ao_device *device);
+	void (*device_clear)(ao_device *device);
+	char* (*file_extension)(void);
+};
+
+/* --- Functions --- */
+
+void ao_read_config_files (ao_config *config);
+
+#define adebug(format, ...) {\
+    if(device->verbose==2){                                             \
+      if(strcmp(format,"\n")){                                          \
+        if(device->funcs->driver_info()->short_name){                   \
+          fprintf(stderr,"ao_%s debug: " format,device->funcs->driver_info()->short_name,##__VA_ARGS__); \
+        }else{                                                          \
+          fprintf(stderr,"debug: " format,##__VA_ARGS__);                     \
+        }                                                               \
+      }else{                                                            \
+        fprintf(stderr,"\n");                                           \
+      }                                                                 \
+    }                                                                   \
+  }
+
+#define averbose(format, ...) {\
+    if(device->verbose>0){                                              \
+      if(strcmp(format,"\n")){                                          \
+        if(device->funcs->driver_info()->short_name){                   \
+          fprintf(stderr,"ao_%s info: " format,device->funcs->driver_info()->short_name,##__VA_ARGS__); \
+        }else{                                                          \
+          fprintf(stderr,"info: " format,##__VA_ARGS__);                      \
+        }                                                               \
+      }else{                                                            \
+        fprintf(stderr,"\n");                                           \
+      }                                                                 \
+    }                                                                   \
+  }
+
+#define ainfo(format, ...) {\
+    if(device->verbose>=0){                                             \
+      if(strcmp(format,"\n")){                                          \
+        if(device->funcs->driver_info()->short_name){                   \
+          fprintf(stderr,"ao_%s info: " format,device->funcs->driver_info()->short_name,##__VA_ARGS__); \
+        }else{                                                          \
+          fprintf(stderr,"info: " format,##__VA_ARGS__);                      \
+        }                                                               \
+      }else{                                                            \
+        fprintf(stderr,"\n");                                           \
+      }                                                                 \
+    }                                                                   \
+  }
+
+#define awarn(format, ...) {\
+    if(device->verbose>=0){                                             \
+      if(strcmp(format,"\n")){                                          \
+        if(device->funcs->driver_info()->short_name){                   \
+          fprintf(stderr,"ao_%s WARNING: " format,device->funcs->driver_info()->short_name,##__VA_ARGS__); \
+        }else{                                                          \
+          fprintf(stderr,"WARNING: " format,##__VA_ARGS__);                   \
+        }                                                               \
+      }else{                                                            \
+        fprintf(stderr,"\n");                                           \
+      }                                                                 \
+    }                                                                   \
+  }
+
+#define aerror(format, ...) {                                       \
+    if(device->verbose>=0){                                             \
+      if(strcmp(format,"\n")){                                          \
+        if(device->funcs->driver_info()->short_name){                   \
+          fprintf(stderr,"ao_%s ERROR: " format,device->funcs->driver_info()->short_name,##__VA_ARGS__); \
+        }else{                                                          \
+          fprintf(stderr,"ERROR: " format,##__VA_ARGS__);                     \
+        }                                                               \
+      }else{                                                            \
+        fprintf(stderr,"\n");                                           \
+      }                                                                 \
+    }                                                                   \
+  }
+
+#endif /* __AO_PRIVATE_H__ */
diff --git a/libao/src/include/ao/os_types.h b/libao/src/include/ao/os_types.h
new file mode 100644
index 0000000..8a56553
--- /dev/null
+++ b/libao/src/include/ao/os_types.h
@@ -0,0 +1,39 @@
+/*
+ *
+ *  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 audio output library.  See
+ *  README for a history of this source code.
+ *
+ *  libao is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* Set type sizes for this platform (Requires Autoconf) */
+
+#ifndef __OS_TYPES_H__
+#define __OS_TYPES_H__
+
+typedef unsigned char     uint_8;
+typedef unsigned short uint_16;
+typedef unsigned int uint_32;
+typedef signed   char     sint_8;
+typedef signed   short sint_16;
+typedef signed   int sint_32;
+
+#endif /* __OS_TYPES_H__ */
diff --git a/libao/src/include/ao/plugin.h b/libao/src/include/ao/plugin.h
new file mode 100644
index 0000000..29a3d96
--- /dev/null
+++ b/libao/src/include/ao/plugin.h
@@ -0,0 +1,51 @@
+/*
+ *
+ *  plugin.h - function declarations for libao plugins
+ *  
+ *      Copyright (C) Stan Seibert - June 2001
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef __PLUGIN_H__
+#define __PLUGIN_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+	
+#include <stdlib.h>
+#include "os_types.h"
+
+int ao_plugin_test();
+ao_info *ao_plugin_driver_info();
+int ao_plugin_device_init(ao_device *device);
+int ao_plugin_set_option(ao_device *device, const char *key, const char *value);
+int ao_plugin_open(ao_device *device, ao_sample_format *format);
+int ao_plugin_play(ao_device *device, const char *output_samples, 
+		uint_32 num_bytes);
+int ao_plugin_close(ao_device *device);
+void ao_plugin_device_clear(ao_device *device);
+char *ao_plugin_file_extension();
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* __PLUGIN_H__ */
diff --git a/libao/src/src/ao_aixs.c b/libao/src/src/ao_aixs.c
new file mode 100644
index 0000000..d8ba6ed
--- /dev/null
+++ b/libao/src/src/ao_aixs.c
@@ -0,0 +1,256 @@
+/*
+ *
+ *  ao_aixs.c    AIX (5.1)
+ *
+ *      Original Copyright (C) Stefan Tibus - August 2002
+ *
+ *  libao is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_aixs.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+#ifdef HAVE_SYS_AUDIO_H
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/audio.h>
+
+#include <ao/ao.h>
+#include <ao/plugin.h>
+
+
+/*
+ * default audio device to be used,
+ * possible options:
+ * /dev/paud0/1 on PCI machines with the Crystal chipset
+ * /dev/baud0/1 on MCA machines with the Crystal chipset
+ * /dev/acpa0/1 on MCA machines with the ACPA
+ */
+#ifndef AO_AIX_DEFAULT_DEV
+#define AO_AIX_DEFAULT_DEV "/dev/baud0/1"
+#define AO_AIX_DEFAULT_DEV2 "/dev/paud0/1"
+#define AO_AIX_DEFAULT_DEV3 "/dev/acpa0/1"
+#endif
+
+
+static char *ao_aixs_options[] = {"dev","id","matrix","verbose","quiet","debug"};
+ao_info ao_aixs_info = {
+  AO_TYPE_LIVE,
+  "AIX audio driver output",
+  "aixs",
+  "Stefan Tibus <sjti@gmx.net>",
+  "Outputs to the AIX audio system.",
+  AO_FMT_NATIVE,
+  20,
+  ao_aixs_options,
+  sizeof(ao_aixs_options)/sizeof(*ao_aixs_options)
+};
+
+
+typedef struct ao_aixs_internal {
+  char *dev;
+  int id;
+  int fd;
+} ao_aixs_internal;
+
+
+int ao_aixs_test()
+{
+  int fd;
+
+  fd = open(AO_AIX_DEFAULT_DEV, O_WRONLY);
+  if(fd<0)
+    fd = open(AO_AIX_DEFAULT_DEV2, O_WRONLY);
+  if(fd<0)
+    fd = open(AO_AIX_DEFAULT_DEV3, O_WRONLY);
+  if(fd<0)
+    return 0; /* Cannot use this plugin with default parameters */
+
+  close(fd);
+  return 1; /* This plugin works in default mode */
+}
+
+
+ao_info *ao_aixs_driver_info(void)
+{
+  return &ao_aixs_info;
+}
+
+
+int ao_aixs_device_init(ao_device *device)
+{
+  ao_aixs_internal *internal;
+
+  internal = (ao_aixs_internal *) calloc(1,sizeof(ao_aixs_internal));
+
+  if (internal == NULL)
+    return 0; /* Could not initialize device memory */
+
+  device->internal = internal;
+  device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
+
+  return 1; /* Memory alloc successful */
+}
+
+int ao_aixs_set_option(ao_device *device, const char *key, const char *value)
+{
+  ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+  if (!strcmp(key, "dev")) {
+    if(internal->dev)
+      free(internal->dev);
+    internal->dev = strdup(value);
+  }
+  if (!strcmp(key, "id")) {
+    internal->id = atoi(value);
+    if(internal->dev)
+      free(internal->dev);
+    internal->dev = NULL;
+  }
+
+  return 1;
+}
+
+
+int ao_aixs_open(ao_device *device, ao_sample_format *format)
+{
+	ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+	audio_init init;
+	audio_control control;
+	audio_change change;
+
+        if(!internal->dev){
+          char buffer[80];
+          int fd;
+
+          sprintf(buffer,"/dev/baud%d/1",id);
+          fd = open(buffer, O_WRONLY);
+          if(fd<0){
+            sprintf(buffer,"/dev/paud%d/1",id);
+            fd = open(buffer, O_WRONLY);
+          }
+          if(fd<0){
+            sprintf(buffer,"/dev/acpa%d/1",id);
+            fd = open(buffer, O_WRONLY);
+          }
+          if(fd<0) return 0;
+          internal->fd = fd;
+          internal->dev = strdup(buffer);
+        }else
+          if ( (internal->fd = open(internal->dev, O_WRONLY)) < 0 )
+            return 0;
+
+	init.srate = format->rate;
+	init.bits_per_sample = format->bits;
+	init.channels = device->output_channels;
+	init.mode = AUDIO_PCM;
+	init.flags = AUDIO_BIG_ENDIAN | AUDIO_TWOS_COMPLEMENT;
+	init.operation = AUDIO_PLAY;
+
+ 	if (ioctl(internal->fd, AUDIO_INIT, &init) < 0) {
+		close(internal->fd);
+		return 0;  /* Unsupported audio format */
+	}
+
+	change.balance = 0x3fff0000;
+	change.volume = 0x3fff0000;
+	change.monitor = AUDIO_IGNORE;
+	change.input = AUDIO_IGNORE;
+	change.output = AUDIO_OUTPUT_1;
+
+	control.ioctl_request = AUDIO_CHANGE;
+	control.position = 0;
+	control.request_info = &change;
+
+	if (ioctl(internal->fd, AUDIO_CONTROL, &control) < 0) {
+		close(internal->fd);
+		return 0;
+	}
+
+	control.ioctl_request = AUDIO_START;
+	control.request_info = NULL;
+
+	if (ioctl(internal->fd, AUDIO_CONTROL, &control) < 0) {
+		close(internal->fd);
+		return 0;
+	}
+
+	device->driver_byte_format = AO_FMT_NATIVE;
+        if(!device->inter_matrix){
+          /* set up matrix such that users are warned about > stereo playback */
+          if(device->output_channels<=2)
+            device->inter_matrix=strdup("L,R");
+          //else no matrix, which results in a warning
+        }
+
+	return 1;
+}
+
+
+int ao_aixs_play(ao_device *device, const char *output_samples,
+		uint_32 num_bytes)
+{
+	ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+	if (write(internal->fd, output_samples, num_bytes) < 0)
+		return 0;
+	else
+		return 1;
+}
+
+
+int ao_aixs_close(ao_device *device)
+{
+	ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+        if(internal->fd)
+          close(internal->fd);
+        internal->fd=-1;
+	return 1;
+}
+
+
+void ao_aixs_device_clear(ao_device *device)
+{
+	ao_aixs_internal *internal = (ao_aixs_internal *) device->internal;
+
+        if(internal->dev)
+          free(internal->dev);
+	free(internal);
+        device->internal = NULL;
+}
+
+ao_functions ao_aixs = {
+	ao_aixs_test,
+	ao_aixs_driver_info,
+	ao_aixs_device_init,
+	ao_aixs_set_option,
+	ao_aixs_open,
+	ao_aixs_play,
+	ao_aixs_close,
+	ao_aixs_device_clear
+};
+
+#endif
diff --git a/libao/src/src/ao_au.c b/libao/src/src/ao_au.c
new file mode 100644
index 0000000..f6aad2d
--- /dev/null
+++ b/libao/src/src/ao_au.c
@@ -0,0 +1,250 @@
+/*
+ *
+ *  ao_au.c
+ *
+ *      Copyright (C) Wil Mahan - May 2001
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_au.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+#include <ao/ao.h>
+#include <ao/plugin.h>
+
+#define AUDIO_FILE_MAGIC ((uint_32)0x2e736e64)  /* ".snd" */
+
+#define AUDIO_UNKNOWN_SIZE (~0) /* (unsigned) -1 */
+
+/* Format codes (not comprehensive) */
+#define AUDIO_FILE_ENCODING_LINEAR_8 (2) /* 8-bit linear PCM */
+#define AUDIO_FILE_ENCODING_LINEAR_16 (3) /* 16-bit linear PCM */
+
+#define AU_HEADER_LEN (28)
+
+#define DEFAULT_SWAP_BUFFER_SIZE 2048
+
+/* Write a uint_32 in big-endian order. */
+#define WRITE_U32(buf, x) \
+	*(buf) = (unsigned char)(((x)>>24)&0xff);\
+	*((buf)+1) = (unsigned char)(((x)>>16)&0xff);\
+	*((buf)+2) = (unsigned char)(((x)>>8)&0xff);\
+	*((buf)+3) = (unsigned char)((x)&0xff);
+
+typedef struct Audio_filehdr {
+	uint_32 magic; /* magic number */
+	uint_32 hdr_size; /* offset of the data */
+	uint_32 data_size; /* length of data (optional) */
+	uint_32 encoding; /* data format code */
+	uint_32 sample_rate; /* samples per second */
+	uint_32 channels; /* number of interleaved channels */
+	char info[4]; /* optional text information */
+} Audio_filehdr;
+
+static char *ao_au_options[] = {"matrix","verbose","quiet","debug"};
+static ao_info ao_au_info =
+{
+	AO_TYPE_FILE,
+	"AU file output",
+	"au",
+	"Wil Mahan <wtm2@duke.edu>",
+	"Sends output to a .au file",
+	AO_FMT_BIG,
+	0,
+	ao_au_options,
+        sizeof(ao_au_options)/sizeof(*ao_au_options)
+};
+
+typedef struct ao_au_internal
+{
+	Audio_filehdr au;
+} ao_au_internal;
+
+
+static int ao_au_test(void)
+{
+	return 1; /* File driver always works */
+}
+
+
+static ao_info *ao_au_driver_info(void)
+{
+	return &ao_au_info;
+}
+
+
+static int ao_au_device_init(ao_device *device)
+{
+	ao_au_internal *internal;
+
+	internal = (ao_au_internal *) malloc(sizeof(ao_au_internal));
+
+	if (internal == NULL)
+		return 0; /* Could not initialize device memory */
+
+	memset(&(internal->au), 0, sizeof(internal->au));
+
+	device->internal = internal;
+        device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
+
+	return 1; /* Memory alloc successful */
+}
+
+
+static int ao_au_set_option(ao_device *device, const char *key,
+			    const char *value)
+{
+	return 1; /* No options! */
+}
+
+
+static int ao_au_open(ao_device *device, ao_sample_format *format)
+{
+	ao_au_internal *internal = (ao_au_internal *) device->internal;
+	unsigned char buf[AU_HEADER_LEN];
+
+	/* The AU format is big-endian */
+	device->driver_byte_format = AO_FMT_BIG;
+
+	/* Fill out the header */
+	internal->au.magic = AUDIO_FILE_MAGIC;
+	internal->au.channels = device->output_channels;
+	if (format->bits == 8)
+		internal->au.encoding = AUDIO_FILE_ENCODING_LINEAR_8;
+	else if (format->bits == 16)
+		internal->au.encoding = AUDIO_FILE_ENCODING_LINEAR_16;
+	else {
+		/* Only 8 and 16 bits are supported at present. */
+		return 0;
+	}
+	internal->au.sample_rate = format->rate;
+	internal->au.hdr_size = AU_HEADER_LEN;
+
+	/* From the AU specification:  "When audio files are passed
+	 * through pipes, the 'data_size' field may not be known in
+	 * advance.  In such cases, the 'data_size' should be set
+	 * to AUDIO_UNKNOWN_SIZE."
+	 */
+	internal->au.data_size = AUDIO_UNKNOWN_SIZE;
+	/* strncpy(state->au.info, "OGG ", 4); */
+
+	/* Write the header in big-endian order */
+	WRITE_U32(buf, internal->au.magic);
+	WRITE_U32(buf + 4, internal->au.hdr_size);
+	WRITE_U32(buf + 8, internal->au.data_size);
+	WRITE_U32(buf + 12, internal->au.encoding);
+	WRITE_U32(buf + 16, internal->au.sample_rate);
+	WRITE_U32(buf + 20, internal->au.channels);
+	strncpy (buf + 24, internal->au.info, 4);
+
+	if (fwrite(buf, sizeof(char), AU_HEADER_LEN, device->file)
+	    != AU_HEADER_LEN) {
+		return 0; /* Error writing header */
+	}
+
+        if(!device->inter_matrix){
+          /* set up matrix such that users are warned about > stereo playback */
+          if(device->output_channels<=2)
+            device->inter_matrix=strdup("L,R");
+          //else no matrix, which results in a warning
+        }
+
+
+	return 1;
+}
+
+
+/*
+ * play the sample to the already opened file descriptor
+ */
+static int ao_au_play(ao_device *device, const char *output_samples,
+		       uint_32 num_bytes)
+{
+	if (fwrite(output_samples, sizeof(char), num_bytes,
+		   device->file) < num_bytes)
+		return 0;
+	else
+		return 1;
+}
+
+static int ao_au_close(ao_device *device)
+{
+	ao_au_internal *internal = (ao_au_internal *) device->internal;
+
+        off_t size;
+	unsigned char buf[4];
+
+	/* Try to find the total file length, including header */
+	size = ftell(device->file);
+
+	/* It's not a problem if the lseek() fails; the AU
+	 * format does not require a file length.  This is
+	 * useful for writing to non-seekable files (e.g.
+	 * pipes).
+	 */
+	if (size > 0) {
+		internal->au.data_size = size - AU_HEADER_LEN;
+
+		/* Rewind the file */
+		if (fseek(device->file, 8 /* offset of data_size */,
+					SEEK_SET) < 0)
+		{
+			return 1; /* Seek failed; that's okay  */
+		}
+
+		/* Fill in the file length */
+		WRITE_U32 (buf, internal->au.data_size);
+		if (fwrite(buf, sizeof(char), 4, device->file) < 4) {
+			return 1; /* Header write failed; that's okay */
+		}
+	}
+
+	return 1;
+}
+
+
+static void ao_au_device_clear(ao_device *device)
+{
+	ao_au_internal *internal = (ao_au_internal *) device->internal;
+
+	free(internal);
+        device->internal=NULL;
+}
+
+ao_functions ao_au = {
+	ao_au_test,
+	ao_au_driver_info,
+	ao_au_device_init,
+	ao_au_set_option,
+	ao_au_open,
+	ao_au_play,
+	ao_au_close,
+	ao_au_device_clear
+};
diff --git a/libao/src/src/ao_null.c b/libao/src/src/ao_null.c
new file mode 100644
index 0000000..cd7271d
--- /dev/null
+++ b/libao/src/src/ao_null.c
@@ -0,0 +1,153 @@
+/*
+ *
+ *  ao_null.c
+ *
+ *      Original Copyright (C) Aaron Holtzman - May 1999
+ *      Modifications Copyright (C) Stan Seibert - July 2000, July 2001
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_null.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <ao/ao.h>
+
+static char *ao_null_options[] = {
+  "debug","verbose","matrix","quiet"
+};
+static ao_info ao_null_info = {
+	AO_TYPE_LIVE,
+	"Null output",
+	"null",
+	"Stan Seibert <volsung@asu.edu>",
+	"This driver does nothing.",
+	AO_FMT_NATIVE,
+	0,
+	ao_null_options,
+        sizeof(ao_null_options)/sizeof(*ao_null_options)
+};
+
+
+typedef struct ao_null_internal {
+	unsigned long byte_counter;
+} ao_null_internal;
+
+
+static int ao_null_test(void)
+{
+	return 1; /* Null always works */
+}
+
+
+static ao_info *ao_null_driver_info(void)
+{
+	return &ao_null_info;
+}
+
+
+static int ao_null_device_init(ao_device *device)
+{
+	ao_null_internal *internal;
+
+	internal = (ao_null_internal *) malloc(sizeof(ao_null_internal));
+
+	if (internal == NULL)
+		return 0; /* Could not initialize device memory */
+
+	internal->byte_counter = 0;
+
+	device->internal = internal;
+        device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
+
+	return 1; /* Memory alloc successful */
+}
+
+
+static int ao_null_set_option(ao_device *device, const char *key,
+			      const char *value)
+{
+	/*ao_null_internal *internal = (ao_null_internal *) device->internal;*/
+	(void)value;
+	(void)key;
+	(void)device;
+
+	return 1;
+}
+
+
+
+static int ao_null_open(ao_device *device, ao_sample_format *format)
+{
+	/* Use whatever format the client requested */
+	device->driver_byte_format = device->client_byte_format;
+
+        if(!device->inter_matrix){
+          /* by default, we want inter == in */
+          if(format->matrix)
+            device->inter_matrix = _strdup(format->matrix);
+        }
+
+	return 1;
+}
+
+
+static int ao_null_play(ao_device *device, const char *output_samples,
+			uint_32 num_bytes)
+{
+	ao_null_internal *internal = (ao_null_internal *)device->internal;
+
+	internal->byte_counter += num_bytes;
+
+	return 1;
+}
+
+
+static int ao_null_close(ao_device *device)
+{
+	ao_null_internal *internal = (ao_null_internal *) device->internal;
+
+	adebug("%ld bytes sent to null device.\n", internal->byte_counter);
+
+	return 1;
+}
+
+
+static void ao_null_device_clear(ao_device *device)
+{
+	ao_null_internal *internal = (ao_null_internal *) device->internal;
+
+	free(internal);
+        device->internal=NULL;
+}
+
+
+ao_functions ao_null = {
+	ao_null_test,
+	ao_null_driver_info,
+	ao_null_device_init,
+	ao_null_set_option,
+	ao_null_open,
+	ao_null_play,
+	ao_null_close,
+	ao_null_device_clear
+};
diff --git a/libao/src/src/ao_raw.c b/libao/src/src/ao_raw.c
new file mode 100644
index 0000000..50b21be
--- /dev/null
+++ b/libao/src/src/ao_raw.c
@@ -0,0 +1,160 @@
+/*
+ *
+ *  ao_raw.c
+ *
+ *      Copyright (C) Stan Seibert - January 2001, July 2001
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_raw.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ao/ao.h>
+#include <ao/plugin.h>
+
+static char *ao_raw_options[] = {"byteorder","matrix","verbose","quiet","debug"};
+static ao_info ao_raw_info =
+{
+	AO_TYPE_FILE,
+	"RAW sample output",
+	"raw",
+	"Stan Seibert <indigo@aztec.asu.edu>",
+	"Writes raw audio samples to a file",
+	AO_FMT_NATIVE,
+	0,
+	ao_raw_options,
+        sizeof(ao_raw_options)/sizeof(*ao_raw_options)
+};
+
+typedef struct ao_raw_internal
+{
+	int byte_order;
+} ao_raw_internal;
+
+
+static int ao_raw_test(void)
+{
+	return 1; /* Always works */
+}
+
+
+static ao_info *ao_raw_driver_info(void)
+{
+	return &ao_raw_info;
+}
+
+
+static int ao_raw_device_init(ao_device *device)
+{
+	ao_raw_internal *internal;
+
+	internal = (ao_raw_internal *) malloc(sizeof(ao_raw_internal));
+
+	if (internal == NULL)
+		return 0; /* Could not initialize device memory */
+
+	internal->byte_order = AO_FMT_NATIVE;
+
+	device->internal = internal;
+        device->output_matrix_order = AO_OUTPUT_MATRIX_FIXED;
+
+	return 1; /* Memory alloc successful */
+}
+
+static int ao_raw_set_option(ao_device *device, const char *key,
+			      const char *value)
+{
+	ao_raw_internal *internal = (ao_raw_internal *)device->internal;
+
+	if (!strcmp(key, "byteorder")) {
+		if (!strcmp(value, "native"))
+			internal->byte_order = AO_FMT_NATIVE;
+		else if (!strcmp(value, "big"))
+			internal->byte_order = AO_FMT_BIG;
+		else if (!strcmp(value, "little"))
+			internal->byte_order = AO_FMT_LITTLE;
+		else
+			return 0; /* Bad option value */
+	}
+
+	return 1;
+}
+
+
+static int ao_raw_open(ao_device *device, ao_sample_format *format)
+{
+	ao_raw_internal *internal = (ao_raw_internal *)device->internal;
+
+	device->driver_byte_format = internal->byte_order;
+
+        //if(!device->inter_matrix){
+        ///* by default, inter == in */
+        //if(format->matrix)
+        //  device->inter_matrix = strdup(format->matrix);
+        //}
+
+	return 1;
+}
+
+
+/*
+ * play the sample to the already opened file descriptor
+ */
+static int ao_raw_play(ao_device *device, const char *output_samples,
+		       uint_32 num_bytes)
+{
+	if (fwrite(output_samples, sizeof(char), num_bytes,
+		   device->file) < num_bytes)
+		return 0;
+	else
+		return 1;
+}
+
+
+static int ao_raw_close(ao_device *device)
+{
+	/* No closeout needed */
+	return 1;
+}
+
+
+static void ao_raw_device_clear(ao_device *device)
+{
+	ao_raw_internal *internal = (ao_raw_internal *) device->internal;
+
+	free(internal);
+        device->internal=NULL;
+}
+
+
+ao_functions ao_raw = {
+	ao_raw_test,
+	ao_raw_driver_info,
+	ao_raw_device_init,
+	ao_raw_set_option,
+	ao_raw_open,
+	ao_raw_play,
+	ao_raw_close,
+	ao_raw_device_clear
+};
diff --git a/libao/src/src/ao_wav.c b/libao/src/src/ao_wav.c
new file mode 100644
index 0000000..297a8ac
--- /dev/null
+++ b/libao/src/src/ao_wav.c
@@ -0,0 +1,291 @@
+/*
+ *
+ *  ao_wav.c
+ *
+ *      Original Copyright (C) Aaron Holtzman - May 1999
+ *      Modifications Copyright (C) Stan Seibert - July 2000, July 2001
+ *                    Copyright (C) Monty - January 2010
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_wav.c 17718 2010-12-06 20:09:29Z xiphmont $
+
+ ********************************************************************/
+
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <ao/ao.h>
+
+#define WAVE_FORMAT_PCM         0x0001
+#define FORMAT_MULAW            0x0101
+#define IBM_FORMAT_ALAW         0x0102
+#define IBM_FORMAT_ADPCM        0x0103
+#define WAVE_FORMAT_EXTENSIBLE  0xfffe
+
+#define WAV_HEADER_LEN 68
+
+#define WRITE_U32(buf, x) *(buf)     = (unsigned char)(x&0xff);\
+						  *((buf)+1) = (unsigned char)((x>>8)&0xff);\
+						  *((buf)+2) = (unsigned char)((x>>16)&0xff);\
+						  *((buf)+3) = (unsigned char)((x>>24)&0xff);
+
+#define WRITE_U16(buf, x) *(buf)     = (unsigned char)(x&0xff);\
+						  *((buf)+1) = (unsigned char)((x>>8)&0xff);
+
+#define DEFAULT_SWAP_BUFFER_SIZE 2048
+
+struct riff_struct {
+	unsigned char id[4];   /* RIFF */
+	unsigned int len;
+	unsigned char wave_id[4]; /* WAVE */
+};
+
+
+struct chunk_struct
+{
+	unsigned char id[4];
+	unsigned int len;
+};
+
+struct common_struct
+{
+	unsigned short wFormatTag;
+	unsigned short wChannels;
+	unsigned int dwSamplesPerSec;
+	unsigned int dwAvgBytesPerSec;
+	unsigned short wBlockAlign;
+	unsigned short wBitsPerSample;
+        unsigned short cbSize;
+	unsigned short wValidBitsPerSample;
+        unsigned int   dwChannelMask;
+        unsigned short subFormat;
+};
+
+struct wave_header
+{
+	struct riff_struct   riff;
+	struct chunk_struct  format;
+	struct common_struct common;
+	struct chunk_struct  data;
+};
+
+
+static char *ao_wav_options[] = {"matrix","verbose","quiet","debug"};
+static ao_info ao_wav_info =
+{
+	AO_TYPE_FILE,
+	"WAV file output",
+	"wav",
+	"Aaron Holtzman <aholtzma@ess.engr.uvic.ca>",
+	"Sends output to a .wav file",
+	AO_FMT_LITTLE,
+	0,
+	ao_wav_options,
+        sizeof(ao_wav_options)/sizeof(*ao_wav_options)
+};
+
+typedef struct ao_wav_internal
+{
+	struct wave_header wave;
+} ao_wav_internal;
+
+
+static int ao_wav_test(void)
+{
+	return 1; /* File driver always works */
+}
+
+
+static ao_info *ao_wav_driver_info(void)
+{
+	return &ao_wav_info;
+}
+
+
+static int ao_wav_device_init(ao_device *device)
+{
+	ao_wav_internal *internal;
+
+	internal = (ao_wav_internal *) malloc(sizeof(ao_wav_internal));
+
+	if (internal == NULL)
+		return 0; /* Could not initialize device memory */
+
+	memset(&(internal->wave), 0, sizeof(internal->wave));
+
+	device->internal = internal;
+        device->output_matrix = strdup("L,R,C,LFE,BL,BR,CL,CR,BC,SL,SR");
+        device->output_matrix_order = AO_OUTPUT_MATRIX_COLLAPSIBLE;
+
+	return 1; /* Memory alloc successful */
+}
+
+
+static int ao_wav_set_option(ao_device *device, const char *key,
+			     const char *value)
+{
+	return 1; /* No options! */
+}
+
+static int ao_wav_open(ao_device *device, ao_sample_format *format)
+{
+	ao_wav_internal *internal = (ao_wav_internal *) device->internal;
+	unsigned char buf[WAV_HEADER_LEN];
+	int size = 0x7fffffff; /* Use a bogus size initially */
+
+	/* Store information */
+	internal->wave.common.wChannels = device->output_channels;
+	internal->wave.common.wBitsPerSample = ((format->bits+7)>>3)<<3;
+	internal->wave.common.wValidBitsPerSample = format->bits;
+	internal->wave.common.dwSamplesPerSec = format->rate;
+
+	memset(buf, 0, WAV_HEADER_LEN);
+
+	/* Fill out our wav-header with some information. */
+	strncpy(internal->wave.riff.id, "RIFF",4);
+	internal->wave.riff.len = size - 8;
+	strncpy(internal->wave.riff.wave_id, "WAVE",4);
+
+	strncpy(internal->wave.format.id, "fmt ",4);
+	internal->wave.format.len = 40;
+
+	internal->wave.common.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+	internal->wave.common.dwAvgBytesPerSec =
+		internal->wave.common.wChannels *
+		internal->wave.common.dwSamplesPerSec *
+		(internal->wave.common.wBitsPerSample >> 3);
+
+	internal->wave.common.wBlockAlign =
+		internal->wave.common.wChannels *
+		(internal->wave.common.wBitsPerSample >> 3);
+	internal->wave.common.cbSize = 22;
+	internal->wave.common.subFormat = WAVE_FORMAT_PCM;
+        internal->wave.common.dwChannelMask=device->output_mask;
+
+	strncpy(internal->wave.data.id, "data",4);
+
+	internal->wave.data.len = size - WAV_HEADER_LEN;
+
+	strncpy(buf, internal->wave.riff.id, 4);
+	WRITE_U32(buf+4, internal->wave.riff.len);
+	strncpy(buf+8, internal->wave.riff.wave_id, 4);
+	strncpy(buf+12, internal->wave.format.id,4);
+	WRITE_U32(buf+16, internal->wave.format.len);
+	WRITE_U16(buf+20, internal->wave.common.wFormatTag);
+	WRITE_U16(buf+22, internal->wave.common.wChannels);
+	WRITE_U32(buf+24, internal->wave.common.dwSamplesPerSec);
+	WRITE_U32(buf+28, internal->wave.common.dwAvgBytesPerSec);
+	WRITE_U16(buf+32, internal->wave.common.wBlockAlign);
+	WRITE_U16(buf+34, internal->wave.common.wBitsPerSample);
+	WRITE_U16(buf+36, internal->wave.common.cbSize);
+	WRITE_U16(buf+38, internal->wave.common.wValidBitsPerSample);
+	WRITE_U32(buf+40, internal->wave.common.dwChannelMask);
+	WRITE_U16(buf+44, internal->wave.common.subFormat);
+        memcpy(buf+46,"\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71",14);
+	strncpy(buf+60, internal->wave.data.id, 4);
+	WRITE_U32(buf+64, internal->wave.data.len);
+
+	if (fwrite(buf, sizeof(char), WAV_HEADER_LEN, device->file)
+	    != WAV_HEADER_LEN) {
+		return 0; /* Could not write wav header */
+	}
+
+	device->driver_byte_format = AO_FMT_LITTLE;
+
+	return 1;
+}
+
+
+/*
+ * play the sample to the already opened file descriptor
+ */
+static int ao_wav_play(ao_device *device, const char *output_samples,
+			uint_32 num_bytes)
+{
+	if (fwrite(output_samples, sizeof(char), num_bytes,
+		   device->file) < num_bytes)
+		return 0;
+	else
+		return 1;
+
+}
+
+static int ao_wav_close(ao_device *device)
+{
+	ao_wav_internal *internal = (ao_wav_internal *) device->internal;
+	unsigned char buf[4];  /* For holding length values */
+
+	long size;
+
+	/* Find how long our file is in total, including header */
+	size = ftell(device->file);
+
+	if (size < 0) {
+		return 0;  /* Wav header corrupt */
+	}
+
+	/* Go back and set correct length info */
+
+	internal->wave.riff.len = size - 8;
+	internal->wave.data.len = size - WAV_HEADER_LEN;
+
+	/* Rewind to riff len and write it */
+	if (fseek(device->file, 4, SEEK_SET) < 0)
+		return 0; /* Wav header corrupt */
+
+	WRITE_U32(buf, internal->wave.riff.len);
+	if (fwrite(buf, sizeof(char), 4, device->file) < 4)
+	  return 0; /* Wav header corrupt */
+
+
+	/* Rewind to data len and write it */
+	if (fseek(device->file, 64, SEEK_SET) < 0)
+		return 0; /* Wav header corrupt */
+
+	WRITE_U32(buf, internal->wave.data.len);
+	if (fwrite(buf, sizeof(char), 4, device->file) < 4)
+	  return 0; /* Wav header corrupt */
+
+
+	return 1; /* Wav header correct */
+}
+
+static void ao_wav_device_clear(ao_device *device)
+{
+	ao_wav_internal *internal = (ao_wav_internal *) device->internal;
+
+	free(internal);
+        device->internal=NULL;
+}
+
+
+ao_functions ao_wav = {
+	ao_wav_test,
+	ao_wav_driver_info,
+	ao_wav_device_init,
+	ao_wav_set_option,
+	ao_wav_open,
+	ao_wav_play,
+	ao_wav_close,
+	ao_wav_device_clear
+};
diff --git a/libao/src/src/ao_wmm.c b/libao/src/src/ao_wmm.c
new file mode 100644
index 0000000..7cd05f1
--- /dev/null
+++ b/libao/src/src/ao_wmm.c
@@ -0,0 +1,645 @@
+/*
+ *
+ *  ao_wmm.c
+ *
+ *      Copyright (C) Benjamin Gerard - March 2007
+ *
+ *  This file is part of libao, a cross-platform library.  See
+ *  README for a history of this source code.
+ *
+ *  libao is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: ao_wmm.c 17629 2010-11-18 12:04:46Z xiphmont $
+
+ ********************************************************************/
+
+//#define PREPARE_EACH
+//#define _CRT_SECURE_NO_DEPRECATE
+
+#include <windows.h>
+#include <mmreg.h>
+#include <mmsystem.h>
+//#include <ks.h>
+//#include <ksmedia.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+
+//#ifndef KSDATAFORMAT_SUBTYPE_PCM
+//#define KSDATAFORMAT_SUBTYPE_PCM (GUID) {0x00000001,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}}
+//#endif
+
+GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,{0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
+
+
+#include "ao/ao.h"
+/* #include "ao/plugin.h" */
+
+#define GALLOC_WVHD_TYPE (GHND)
+#define GALLOC_DATA_TYPE (GHND)
+
+static const char * mmerror(MMRESULT mmrError)
+{
+  static char mmbuffer[1024];
+  int len;
+  sprintf(mmbuffer,"mm:%d ",(int)mmrError);
+  len = (int)strlen(mmbuffer);
+  waveOutGetErrorTextA(mmrError, mmbuffer+len, sizeof(mmbuffer)-len);
+  mmbuffer[sizeof(mmbuffer)-1] = 0;
+  return mmbuffer;
+}
+
+static char * ao_wmm_options[] = {"dev", "id", "matrix","verbose","quiet","debug"};
+static ao_info ao_wmm_info =
+  {
+    /* type             */ AO_TYPE_LIVE,
+    /* name             */ "WMM audio driver output ",
+    /* short-name       */ "wmm",
+    /* author           */ "Benjamin Gerard <benjihan@users.sourceforge.net>",
+    /* comment          */ "Outputs audio to the Windows MultiMedia driver.",
+    /* prefered format  */ AO_FMT_LITTLE,
+    /* priority         */ 20,
+    /* options          */ ao_wmm_options,
+    /* # of options     */ sizeof(ao_wmm_options)/sizeof(*ao_wmm_options)
+  };
+
+typedef struct {
+  WAVEHDR wh;          /* waveheader                        */
+  char *  data;        /* sample data ptr                   */
+  int     idx;         /* index of this header              */
+  int     count;       /* current byte count                */
+  int     length;      /* size of data                      */
+  int     sent;        /* set when header is sent to device */
+} myWH_t;
+
+typedef struct ao_wmm_internal {
+  UINT  id;             /* device id                       */
+  HWAVEOUT hwo;         /* waveout handler                 */
+  WAVEOUTCAPSA caps;     /* device caps                     */
+  WAVEFORMATEXTENSIBLE wavefmt; /* sample format           */
+
+  int opened;           /* device has been opened          */
+  int prepared;         /* waveheaders have been prepared  */
+  int blocks;           /* number of blocks (wave headers) */
+  int splPerBlock;      /* sample per blocks.              */
+  int msPerBlock;       /* millisecond per block (approx.) */
+
+  void * bigbuffer;     /* Allocated buffer for waveheaders and sound data */
+  myWH_t * wh;          /* Pointer to waveheaders in bigbuffer             */
+  BYTE * spl;           /* Pointer to sound data in bigbuffer              */
+
+  int sent_blocks;      /* Number of waveheader sent (not ack).        */
+  int full_blocks;      /* Number of waveheader full (ready to send).  */
+  int widx;             /* Index to the block being currently filled.  */
+  int ridx;             /* Index to the block being sent.              */
+
+} ao_wmm_internal;
+
+int ao_wmm_test(void)
+{
+  return 1; /* This plugin works in default mode */
+}
+
+ao_info *ao_wmm_driver_info(void)
+{
+  return &ao_wmm_info;
+}
+
+int ao_wmm_set_option(ao_device *device,
+                      const char *key, const char *value)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int res = 0;
+
+  if (!strcmp(key, "dev")) {
+    if (!strcmp(value,"default")) {
+      key = "id";
+      value = "0";
+    } else {
+      WAVEOUTCAPSA caps;
+      int i, max = waveOutGetNumDevs();
+
+      adebug("searching for device %s among %d\n", value, max);
+      for (i=0; i<max; ++i) {
+        MMRESULT mmres = waveOutGetDevCapsA(i, &caps, sizeof(caps));
+        if (mmres == MMSYSERR_NOERROR) {
+          res = !strcmp(value, caps.szPname);
+          adebug("checking id=%d, name='%s', ver=%d.%d  => [%s]\n",
+                i,caps.szPname,caps.vDriverVersion>>8,caps.vDriverVersion&255,res?"YES":"no");
+          if (res) {
+            internal->id   = i;
+            internal->caps = caps;
+            break;
+          }
+        } else {
+          aerror("waveOutGetDevCaps(%d) => %s",i,mmerror(mmres));
+        }
+      }
+      goto finish;
+    }
+  }
+
+  if (!strcmp(key,"id")) {
+    MMRESULT mmres;
+    WAVEOUTCAPSA caps;
+
+    int id  = strtol(value,0,0);
+    int max = waveOutGetNumDevs();
+
+    if (id >= 0 &&  id <= max) {
+      if (id-- == 0) {
+        adebug("set default wavemapper\n");
+        id = WAVE_MAPPER;
+      }
+      mmres = waveOutGetDevCapsA(id, &caps, sizeof(caps));
+
+      if (mmres == MMSYSERR_NOERROR) {
+        res = 1;
+        adebug("checking id=%d, name='%s', ver=%d.%d  => [YES]\n",
+              id,caps.szPname,caps.vDriverVersion>>8,caps.vDriverVersion&255);
+        internal->id   = id;
+        internal->caps = caps;
+      } else {
+        aerror("waveOutGetDevCaps(%d) => %s",id,mmerror(mmres));
+      }
+    }
+  }
+
+ finish:
+  return res;
+}
+
+
+int ao_wmm_device_init(ao_device *device)
+{
+  ao_wmm_internal *internal;
+  int res;
+
+  internal = (ao_wmm_internal *) malloc(sizeof(ao_wmm_internal));
+  device->internal = internal;
+  if (internal != NULL) {
+    memset(internal,0,sizeof(ao_wmm_internal));
+    internal->id          = WAVE_MAPPER;
+    internal->blocks      = 32;
+    internal->splPerBlock = 512;
+    /* set default device */
+    ao_wmm_set_option(device,"id","0");
+  }
+
+  res = internal != NULL;
+
+  device->output_matrix = _strdup("L,R,C,LFE,BL,BR,CL,CR,BC,SL,SR");
+  device->output_matrix_order = AO_OUTPUT_MATRIX_COLLAPSIBLE;
+
+  return res;
+}
+
+static int _ao_open_device(ao_device *device)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int res;
+  MMRESULT mmres;
+
+  mmres =
+    waveOutOpen(&internal->hwo,
+		internal->id,
+		&internal->wavefmt.Format,
+		(DWORD_PTR)0/* waveOutProc */,
+		(DWORD_PTR)device,
+		CALLBACK_NULL/* |WAVE_FORMAT_DIRECT */|WAVE_ALLOWSYNC);
+
+  if(mmres == MMSYSERR_NOERROR){
+    adebug("waveOutOpen id=%d, channels=%d, bits=%d, rate %d => SUCCESS\n",
+          internal->id,
+          internal->wavefmt.Format.nChannels,
+          (int)internal->wavefmt.Format.wBitsPerSample,
+          (int)internal->wavefmt.Format.nSamplesPerSec);
+  }else{
+    aerror("waveOutOpen id=%d, channels=%d, bits=%d, rate %d => FAILED\n",
+          internal->id,
+          internal->wavefmt.Format.nChannels,
+          (int)internal->wavefmt.Format.wBitsPerSample,
+          (int)internal->wavefmt.Format.nSamplesPerSec);
+  }
+
+  if (mmres == MMSYSERR_NOERROR) {
+    UINT id;
+    if (MMSYSERR_NOERROR == waveOutGetID(internal->hwo,&id)) {
+      internal->id = id;
+    }
+  }
+
+  res = (mmres == MMSYSERR_NOERROR);
+  return res;
+}
+
+static int _ao_close_device(ao_device *device)
+{
+  ao_wmm_internal * internal = (ao_wmm_internal *) device->internal;
+  int res;
+  MMRESULT mmres;
+
+  mmres = waveOutClose(internal->hwo);
+  if(mmres == MMSYSERR_NOERROR) {
+    adebug("waveOutClose(%d)\n => %s\n", internal->id, mmerror(mmres));
+  }else{
+    aerror("waveOutClose(%d)\n => %s\n", internal->id, mmerror(mmres));
+  }
+  res = (mmres == MMSYSERR_NOERROR);
+
+  return res;
+}
+
+static int _ao_alloc_wave_headers(ao_device *device)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int bytesPerBlock = internal->wavefmt.Format.nBlockAlign * internal->splPerBlock;
+  /*   int bytes = internal->blocks * (sizeof(WAVEHDR) + bytesPerBlock); */
+  int bytes = internal->blocks * (sizeof(*internal->wh) + bytesPerBlock);
+  int res;
+  MMRESULT mmres;
+
+  adebug("_ao_alloc_wave_headers blocks=%d, bytes/blocks=%d, total=%d\n",
+         internal->blocks,bytesPerBlock,bytes);
+
+  internal->bigbuffer = malloc(bytes);
+  if (internal->bigbuffer != NULL) {
+    int i;
+    BYTE * b;
+
+    memset(internal->bigbuffer,0,bytes);
+    internal->wh = internal->bigbuffer;
+    internal->spl = (LPBYTE) (internal->wh+internal->blocks);
+    for (i=0, b=internal->spl; i<internal->blocks; ++i, b+=bytesPerBlock) {
+      internal->wh[i].data = (char*)b;
+      internal->wh[i].wh.lpData = internal->wh[i].data;
+      internal->wh[i].length = bytesPerBlock;
+      internal->wh[i].wh.dwBufferLength = internal->wh[i].length;
+      internal->wh[i].wh.dwUser = (DWORD_PTR)device;
+      mmres = waveOutPrepareHeader(internal->hwo,
+				   &internal->wh[i].wh,sizeof(WAVEHDR));
+      if (MMSYSERR_NOERROR != mmres) {
+        aerror("waveOutPrepareHeader(%d) => %s\n",i, mmerror(mmres));
+        break;
+      }
+    }
+    if (i<internal->blocks) {
+      while (--i >= 0) {
+        waveOutUnprepareHeader(internal->hwo,
+			       &internal->wh[i].wh,sizeof(WAVEHDR));
+      }
+      free(internal->bigbuffer);
+      internal->wh        = 0;
+      internal->spl       = 0;
+      internal->bigbuffer = 0;
+    } else {
+      /* all ok ! */
+    }
+  } else {
+    adebug("malloc() => FAILED\n");
+  }
+
+  res = (internal->bigbuffer != NULL);
+  if(!res){
+    aerror("_ao_alloc_wave_headers() => FAILED\n");
+  }else{
+    adebug("_ao_alloc_wave_headers() => success\n");
+  }
+  return res;
+}
+
+static int _ao_get_free_block(ao_device * device);
+static int _ao_wait_wave_headers(ao_device *device, int wait_all)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int res = 1;
+
+  adebug("wait for %d blocks (%swait all)\n",
+         internal->sent_blocks,wait_all?"":"not ");
+
+  while (internal->sent_blocks > 0) {
+    int n;
+    _ao_get_free_block(device);
+    n = internal->sent_blocks;
+    if (n > 0) {
+      unsigned int ms = (internal->msPerBlock>>1)+1;
+      if (wait_all) ms *= n;
+      adebug("sleep for %ums wait on %d blocks\n",ms, internal->sent_blocks);
+      Sleep(ms);
+    }
+  }
+
+  res &= !internal->sent_blocks;
+  if(!res){
+    aerror("_ao_wait_wave_headers => FAILED\n");
+  }else{
+    adebug("_ao_wait_wave_headers => success\n");
+  }
+  return res;
+}
+
+static int _ao_free_wave_headers(ao_device *device)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  MMRESULT mmres;
+  int res = 1;
+
+  if (internal->wh) {
+    int i;
+
+    /* Reset so we dont need to wait ... Just a satefy net
+     * since _ao_wait_wave_headers() has been called once before.
+     */
+    mmres = waveOutReset(internal->hwo);
+    adebug("waveOutReset(%d) => %s\n", internal->id, mmerror(mmres));
+    /* Wait again to be sure reseted waveheaders has been released. */
+    _ao_wait_wave_headers(device,0);
+
+    for (i=internal->blocks; --i>=0; ) {
+      mmres = waveOutUnprepareHeader(internal->hwo,
+				     &internal->wh[i].wh,sizeof(WAVEHDR));
+      if (mmres != MMSYSERR_NOERROR)
+        aerror("waveOutUnprepareHeader(%d) => %s\n", i, mmerror(mmres));
+
+      res &= mmres == MMSYSERR_NOERROR;
+    }
+    internal->wh  = 0;
+    internal->spl = 0;
+  }
+
+  if(!res){
+    aerror("_ao_alloc_wave_headers() => FAILED\n");
+  }else{
+    adebug("_ao_alloc_wave_headers() => success\n");
+  }
+  return res;
+}
+
+
+/*
+ * open the audio device for writing to
+ */
+int ao_wmm_open(ao_device * device, ao_sample_format * format)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int res = 0;
+  WAVEFORMATEXTENSIBLE wavefmt;
+
+  adebug("open() channels=%d, bits=%d, rate=%d, format %d(%s)\n",
+         device->output_channels,format->bits,format->rate,format->byte_format,
+         format->byte_format==AO_FMT_LITTLE
+         ?"little"
+         :(format->byte_format==AO_FMT_NATIVE
+           ?"native"
+           :(format->byte_format==AO_FMT_BIG?"big":"unknown")));
+
+  if(internal->opened) {
+    aerror("open() => already opened\n");
+    goto error_no_close;
+  }
+
+  /* Force LITTLE as specified by WIN32 API */
+  format->byte_format = AO_FMT_LITTLE;
+  device->driver_byte_format = AO_FMT_LITTLE;
+
+  /* $$$ WMM 8 bit samples are unsigned... Not sure for ao ... */
+  /* Yes, ao 8 bit PCM is unsigned -- Monty */
+
+  /* Make sample format */
+  memset(&wavefmt,0,sizeof(wavefmt));
+  wavefmt.Format.wFormatTag          = WAVE_FORMAT_EXTENSIBLE;
+  wavefmt.Format.nChannels           = device->output_channels;
+  wavefmt.Format.wBitsPerSample      = (((format->bits+7)>>3)<<3);
+  wavefmt.Format.nSamplesPerSec      = format->rate;
+  wavefmt.Format.nBlockAlign         = (wavefmt.Format.wBitsPerSample>>3)*wavefmt.Format.nChannels;
+  wavefmt.Format.nAvgBytesPerSec     = wavefmt.Format.nSamplesPerSec*wavefmt.Format.nBlockAlign;
+  wavefmt.Format.cbSize              = 22;
+  wavefmt.Samples.wValidBitsPerSample = format->bits;
+  wavefmt.SubFormat           = KSDATAFORMAT_SUBTYPE_PCM;
+  wavefmt.dwChannelMask       = device->output_mask;
+
+  internal->wavefmt       = wavefmt;
+
+  /* $$$ later this should be optionnal parms */
+  internal->blocks      = 64;
+  internal->splPerBlock = 512;
+  internal->msPerBlock  =
+    (internal->splPerBlock * 1000 + format->rate - 1) / format->rate;
+
+  /* Open device */
+  if(!_ao_open_device(device))
+    goto error;
+  internal->opened = 1;
+
+  /* Allocate buffers */
+  if (!_ao_alloc_wave_headers(device))
+    goto error;
+  internal->prepared = 1;
+
+  res = 1;
+ error:
+  if (!res) {
+    if (internal->prepared) {
+      _ao_free_wave_headers(device);
+      internal->prepared = 0;
+    }
+    if (internal->opened) {
+      _ao_close_device(device);
+      internal->opened = 0;
+    }
+  }
+
+ error_no_close:
+  if(res){
+    adebug("open() => success\n");
+  }else{
+    aerror("open() => FAILED\n");
+  }
+  return res;
+}
+
+
+
+/* Send a block to audio hardware */
+static int _ao_send_block(ao_device *device, const int idx)
+{
+  ao_wmm_internal * internal = (ao_wmm_internal *) device->internal;
+  MMRESULT mmres;
+
+  /* Satanity checks */
+  if (internal->wh[idx].sent) {
+    adebug("block %d marked SENT\n",idx);
+    return 0;
+  }
+  if (!!(internal->wh[idx].wh.dwFlags & WHDR_DONE)) {
+    adebug("block %d marked DONE\n",idx);
+    return 0;
+  }
+
+  /* count <= 0, just pretend it's been sent */
+  if (internal->wh[idx].count <= 0) {
+    internal->wh[idx].sent = 2; /* set with 2 so we can track these special cases */
+    internal->wh[idx].wh.dwFlags |= WHDR_DONE;
+    ++internal->sent_blocks;
+    return 1;
+  }
+
+  internal->wh[idx].wh.dwBufferLength = internal->wh[idx].count;
+  internal->wh[idx].count = 0;
+  mmres = waveOutWrite(internal->hwo,
+		       &internal->wh[idx].wh, sizeof(WAVEHDR));
+  internal->wh[idx].sent = (mmres == MMSYSERR_NOERROR);
+  /*&& !(internal->wh[idx].wh.dwFlags & WHDR_DONE);*/
+  internal->sent_blocks += internal->wh[idx].sent;
+  if (mmres != MMSYSERR_NOERROR) {
+    adebug("waveOutWrite(%d) => %s\n",idx,mmerror(mmres));
+  }
+  return mmres == MMSYSERR_NOERROR;
+}
+
+/* Get idx of next free block. */
+static int _ao_get_free_block(ao_device * device)
+{
+  ao_wmm_internal * internal = (ao_wmm_internal *) device->internal;
+  const int idx = internal->widx;
+  int ridx = internal->ridx;
+
+  while (internal->wh[ridx].sent && !!(internal->wh[ridx].wh.dwFlags & WHDR_DONE)) {
+    /* block successfully sent to hardware, release it */
+    /*debug("_ao_get_free_block: release block %d\n",ridx);*/
+    internal->wh[ridx].sent = 0;
+    internal->wh[ridx].wh.dwFlags &= ~WHDR_DONE;
+
+    --internal->full_blocks;
+    if (internal->full_blocks<0) {
+      adebug("internal error with full block counter\n");
+      internal->full_blocks = 0;
+    }
+
+    --internal->sent_blocks;
+    if (internal->sent_blocks<0) {
+      adebug("internal error with sent block counter\n");
+      internal->sent_blocks = 0;
+    }
+    if (++ridx >= internal->blocks) ridx = 0;
+  }
+  internal->ridx = ridx;
+
+  return internal->wh[idx].sent
+    ? -1
+    : idx;
+}
+
+/*
+ * play the sample to the already opened file descriptor
+ */
+int ao_wmm_play(ao_device *device,
+                const char *output_samples, uint_32 num_bytes)
+{
+  int ret = 1;
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+
+  while(ret && num_bytes > 0) {
+    int n;
+    const int idx = _ao_get_free_block(device);
+
+    if (idx == -1) {
+      Sleep(internal->msPerBlock);
+      continue;
+    }
+
+    /* Get free bytes in the block */
+    n = internal->wh[idx].wh.dwBufferLength
+      - internal->wh[idx].count;
+
+    /* Get amount to copy */
+    if (n > (int)num_bytes) {
+      n = num_bytes;
+    }
+
+    /* Do copy */
+    CopyMemory((char*)internal->wh[idx].wh.lpData
+	       + internal->wh[idx].count,
+	       output_samples, n);
+
+    /* Updates pointers and counters */
+    output_samples += n;
+    num_bytes -= n;
+    internal->wh[idx].count += n;
+
+    /* Is this block full ? */
+    if (internal->wh[idx].count
+	== internal->wh[idx].wh.dwBufferLength) {
+      ++internal->full_blocks;
+      if (++internal->widx == internal->blocks) {
+	internal->widx = 0;
+      }
+      ret = _ao_send_block(device,idx);
+    }
+  }
+
+  adebug("ao_wmm_play => %d rem => [%s]\n",num_bytes,ret?"success":"error");
+  return ret;
+
+}
+
+int ao_wmm_close(ao_device *device)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+  int ret = 0;
+
+  if (internal->opened && internal->prepared) {
+    _ao_wait_wave_headers(device, 1);
+  }
+
+  if (internal->prepared) {
+    ret = _ao_free_wave_headers(device);
+    internal->prepared = 0;
+  }
+
+  if (internal->opened) {
+    ret = _ao_close_device(device);
+    internal->opened = 0;
+  }
+
+  return ret;
+}
+
+void ao_wmm_device_clear(ao_device *device)
+{
+  ao_wmm_internal *internal = (ao_wmm_internal *) device->internal;
+
+  if (internal->bigbuffer) {
+    free(internal->bigbuffer); internal->bigbuffer = NULL;
+  }
+  free(internal);
+  device->internal=NULL;
+}
+
+ao_functions ao_wmm = {
+  ao_wmm_test,
+  ao_wmm_driver_info,
+  ao_wmm_device_init,
+  ao_wmm_set_option,
+  ao_wmm_open,
+  ao_wmm_play,
+  ao_wmm_close,
+  ao_wmm_device_clear
+};
diff --git a/libao/src/src/audio_out.c b/libao/src/src/audio_out.c
new file mode 100644
index 0000000..f83199d
--- /dev/null
+++ b/libao/src/src/audio_out.c
@@ -0,0 +1,1514 @@
+/*
+ *
+ *  audio_out.c
+ *
+ *      Original Copyright (C) Aaron Holtzman - May 1999
+ *      Modifications Copyright (C) Stan Seibert - July 2000
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: audio_out.c 17008 2010-03-24 03:12:16Z xiphmont $
+
+ ********************************************************************/
+
+#define STRIP_PLUGINS
+
+#define HAVE_WMM
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#ifndef STRIP_PLUGINS
+#if defined HAVE_DLFCN_H && defined HAVE_DLOPEN
+# include <dlfcn.h>
+#else
+static void *dlopen(const char *filename, int flag) {return 0;}
+static char *dlerror(void) { return "dlopen: unsupported"; }
+static void *dlsym(void *handle, const char *symbol) { return 0; }
+static int dlclose(void *handle) { return 0; }
+#undef DLOPEN_FLAG
+#define DLOPEN_FLAG 0
+#endif
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef _MSC_VER
+# include <unistd.h>
+#endif
+//#include <dirent.h>
+
+#include "ao/ao.h"
+#include "ao/ao_private.h"
+
+/* These should have been set by the Makefile */
+#ifndef AO_PLUGIN_PATH
+#define AO_PLUGIN_PATH "/usr/local/lib/ao"
+#endif
+#ifndef SHARED_LIB_EXT
+#define SHARED_LIB_EXT ".so"
+#endif
+
+/* --- Other constants --- */
+#define DEF_SWAP_BUF_SIZE  1024
+
+/* --- Driver Table --- */
+
+typedef struct driver_list {
+	ao_functions *functions;
+	void *handle;
+	struct driver_list *next;
+} driver_list;
+
+
+extern ao_functions ao_null;
+//extern ao_functions ao_wav;
+//extern ao_functions ao_raw;
+//extern ao_functions ao_au;
+#ifdef HAVE_SYS_AUDIO_H
+extern ao_functions ao_aixs;
+#endif
+#ifdef HAVE_WMM
+extern ao_functions ao_wmm;
+#endif
+static ao_functions *static_drivers[] = {
+	&ao_null, /* Must have at least one static driver! */
+	//&ao_wav,
+	//&ao_raw,
+	//&ao_au,
+#ifdef HAVE_SYS_AUDIO_H
+	&ao_aixs,
+#endif
+#ifdef HAVE_WMM
+	&ao_wmm,
+#endif
+
+	NULL /* End of list */
+};
+
+static driver_list *driver_head = NULL;
+static ao_config config = {
+	NULL /* default_driver */
+};
+
+static ao_info **info_table = NULL;
+static int driver_count = 0;
+
+/* uses the device messaging and option infrastructure */
+static ao_device *ao_global_dummy;
+static ao_device ao_global_dummy_storage;
+static ao_option *ao_global_options=NULL;
+
+/* ---------- Helper functions ---------- */
+
+/* Clear out all of the library configuration options and set them to
+   defaults.   The defaults should match the initializer above. */
+static void _clear_config()
+{
+        memset(ao_global_dummy,0,sizeof(*ao_global_dummy));
+        ao_global_dummy = NULL;
+        ao_free_options(ao_global_options);
+        ao_global_options = NULL;
+
+	free(config.default_driver);
+	config.default_driver = NULL;
+}
+
+
+#ifndef STRIP_PLUGINS
+/* Load a plugin from disk and put the function table into a driver_list
+   struct. */
+static driver_list *_get_plugin(char *plugin_file)
+{
+        ao_device *device = ao_global_dummy;
+	driver_list *dt;
+	void *handle;
+        char *prompt="";
+
+	handle = dlopen(plugin_file, DLOPEN_FLAG /* See ao_private.h */);
+
+	if (handle) {
+                prompt="calloc() failed";
+                dt = (driver_list *)calloc(1,sizeof(driver_list));
+		if (!dt) return NULL;
+
+		dt->handle = handle;
+
+		dt->functions = (ao_functions *)calloc(1,sizeof(ao_functions));
+		if (!(dt->functions)) {
+			free(dt);
+			return NULL;
+		}
+
+                prompt="ao_plugin_test() missing";
+		dt->functions->test = dlsym(dt->handle, "ao_plugin_test");
+		if (!(dt->functions->test)) goto failed;
+
+                prompt="ao_plugin_driver_info() missing";
+		dt->functions->driver_info =
+		  dlsym(dt->handle, "ao_plugin_driver_info");
+		if (!(dt->functions->driver_info)) goto failed;
+
+                prompt="ao_plugin_device_list() missing";
+		dt->functions->device_init =
+		  dlsym(dt->handle, "ao_plugin_device_init");
+		if (!(dt->functions->device_init )) goto failed;
+
+                prompt="ao_plugin_set_option() missing";
+		dt->functions->set_option =
+		  dlsym(dt->handle, "ao_plugin_set_option");
+		if (!(dt->functions->set_option)) goto failed;
+
+                prompt="ao_plugin_open() missing";
+		dt->functions->open = dlsym(dt->handle, "ao_plugin_open");
+		if (!(dt->functions->open)) goto failed;
+
+                prompt="ao_plugin_play() missing";
+		dt->functions->play = dlsym(dt->handle, "ao_plugin_play");
+		if (!(dt->functions->play)) goto failed;
+
+                prompt="ao_plugin_close() missing";
+		dt->functions->close = dlsym(dt->handle, "ao_plugin_close");
+		if (!(dt->functions->close)) goto failed;
+
+                prompt="ao_plugin_clear() missing";
+		dt->functions->device_clear =
+		  dlsym(dt->handle, "ao_plugin_device_clear");
+		if (!(dt->functions->device_clear)) goto failed;
+
+
+	} else {
+          aerror("Failed to load plugin %s => dlopen() failed\n",plugin_file);
+          return NULL;
+	}
+
+        adebug("Loaded driver %s\n",dt->functions->driver_info()->short_name);
+	return dt;
+
+ failed:
+        aerror("Failed to load plugin %s => %s\n",plugin_file,prompt);
+	free(dt->functions);
+	free(dt);
+	return NULL;
+}
+#endif
+
+
+/* If *name is a valid driver name, return its driver number.
+   Otherwise, test all of available live drivers until one works. */
+static int _find_default_driver_id (const char *name)
+{
+	int def_id;
+	int id;
+	ao_info *info;
+	driver_list *dl = driver_head;
+        ao_device *device = ao_global_dummy;
+
+        adebug("Testing drivers to find playback default...\n");
+	if ( name == NULL || (def_id = ao_driver_id(name)) < 0 ) {
+		/* No default specified. Find one among available drivers. */
+		def_id = -1;
+
+		id = 0;
+		while (dl != NULL) {
+
+			info = dl->functions->driver_info();
+                        adebug("...testing %s\n",info->short_name);
+			if ( info->type == AO_TYPE_LIVE &&
+			     info->priority > 0 && /* Skip static drivers */
+			     dl->functions->test() ) {
+				def_id = id; /* Found a usable driver */
+                                adebug("OK, using driver %s\n",info->short_name);
+				break;
+			}
+
+			dl = dl->next;
+			id++;
+		}
+	}
+
+	return def_id;
+}
+
+
+/* Convert the static drivers table into a linked list of drivers. */
+static driver_list* _load_static_drivers(driver_list **end)
+{
+        ao_device *device = ao_global_dummy;
+	driver_list *head;
+	driver_list *driver;
+	int i;
+
+	/* insert first driver */
+	head = driver = calloc(1,sizeof(driver_list));
+	if (driver != NULL) {
+		driver->functions = static_drivers[0];
+		driver->handle = NULL;
+		driver->next = NULL;
+                adebug("Loaded driver %s (built-in)\n",driver->functions->driver_info()->short_name);
+
+		i = 1;
+		while (static_drivers[i] != NULL) {
+                  driver->next = calloc(1,sizeof(driver_list));
+			if (driver->next == NULL)
+				break;
+
+			driver->next->functions = static_drivers[i];
+			driver->next->handle = NULL;
+			driver->next->next = NULL;
+
+			driver = driver->next;
+                        adebug("Loaded driver %s (built-in)\n",driver->functions->driver_info()->short_name);
+			i++;
+		}
+	}
+
+	if (end != NULL)
+		*end = driver;
+
+	return head;
+}
+
+
+/* Load the dynamic drivers from disk and append them to end of the
+   driver list.  end points the driver_list node to append to. */
+static void _append_dynamic_drivers(driver_list *end)
+{
+#ifdef HAVE_DLOPEN
+	struct dirent *plugin_dirent;
+	char *ext;
+	struct stat statbuf;
+	DIR *plugindir;
+	driver_list *plugin;
+	driver_list *driver = end;
+        ao_device *device = ao_global_dummy;
+
+	/* now insert any plugins we find */
+	plugindir = opendir(AO_PLUGIN_PATH);
+        adebug("Loading driver plugins from %s...\n",AO_PLUGIN_PATH);
+	if (plugindir != NULL) {
+          while ((plugin_dirent = readdir(plugindir)) != NULL) {
+            char fullpath[strlen(AO_PLUGIN_PATH) + 1 + strlen(plugin_dirent->d_name) + 1];
+            snprintf(fullpath, sizeof(fullpath), "%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;
+                  driver = driver->next;
+                }
+              }
+            }
+          }
+
+          closedir(plugindir);
+	}
+#endif
+}
+
+
+/* Compare two drivers based on priority
+   Used as compar function for qsort() in _make_info_table() */
+static int _compar_driver_priority (const driver_list **a,
+				    const driver_list **b)
+{
+	return memcmp(&((*b)->functions->driver_info()->priority),
+		      &((*a)->functions->driver_info()->priority),
+		      sizeof(int));
+}
+
+
+/* Make a table of driver info structures for ao_driver_info_list(). */
+static ao_info ** _make_info_table (driver_list **head, int *driver_count)
+{
+	driver_list *list;
+	int i;
+	ao_info **table;
+	driver_list **drivers_table;
+
+	*driver_count = 0;
+
+	/* Count drivers */
+	list = *head;
+	i = 0;
+	while (list != NULL) {
+		i++;
+		list = list->next;
+	}
+
+
+	/* Sort driver_list */
+	drivers_table = (driver_list **) calloc(i, sizeof(driver_list *));
+	if (drivers_table == NULL)
+		return (ao_info **) NULL;
+	list = *head;
+	*driver_count = i;
+	for (i = 0; i < *driver_count; i++, list = list->next)
+		drivers_table[i] = list;
+	qsort(drivers_table, i, sizeof(driver_list *),
+			(int(*)(const void *, const void *))
+			_compar_driver_priority);
+	*head = drivers_table[0];
+	for (i = 1; i < *driver_count; i++)
+		drivers_table[i-1]->next = drivers_table[i];
+	drivers_table[i-1]->next = NULL;
+
+
+	/* Alloc table */
+	table = (ao_info **) calloc(i, sizeof(ao_info *));
+	if (table != NULL) {
+		for (i = 0; i < *driver_count; i++)
+			table[i] = drivers_table[i]->functions->driver_info();
+	}
+
+	free(drivers_table);
+
+	return table;
+}
+
+
+/* Return the driver struct corresponding to particular driver id
+   number. */
+static driver_list *_get_driver(int driver_id) {
+	int i = 0;
+	driver_list *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;
+}
+
+
+#ifndef STRIP_PLUGINS
+/* Check if driver_id is a valid id number */
+static int _check_driver_id(int driver_id)
+{
+	int i = 0;
+	driver_list *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;
+}
+#endif
+
+
+/* helper function to convert a byte_format of AO_FMT_NATIVE to the
+   actual byte format of the machine, otherwise just return
+   byte_format */
+static int _real_byte_format(int byte_format)
+{
+	if (byte_format == AO_FMT_NATIVE) {
+		if (ao_is_big_endian())
+			return AO_FMT_BIG;
+		else
+			return AO_FMT_LITTLE;
+	} else
+		return byte_format;
+}
+
+
+/* Create a new ao_device structure and populate it with data */
+static ao_device* _create_device(int driver_id, driver_list *driver,
+				 ao_sample_format *format, FILE *file)
+{
+	ao_device *device;
+
+	device = calloc(1,sizeof(ao_device));
+
+	if (device != NULL) {
+		device->type = driver->functions->driver_info()->type;
+		device->driver_id = driver_id;
+		device->funcs = driver->functions;
+		device->file = file;
+		device->machine_byte_format =
+		  ao_is_big_endian() ? AO_FMT_BIG : AO_FMT_LITTLE;
+		device->client_byte_format =
+		  _real_byte_format(format->byte_format);
+		device->swap_buffer = NULL;
+		device->swap_buffer_size = 0;
+		device->internal = NULL;
+                device->output_channels = format->channels;
+                device->inter_permute = NULL;
+                device->output_matrix = NULL;
+	}
+
+	return device;
+}
+
+
+/* Expand the swap buffer in this device if it is smaller than
+   min_size. */
+static int _realloc_swap_buffer(ao_device *device, int min_size)
+{
+	void *temp;
+
+	if (min_size > device->swap_buffer_size) {
+		temp = realloc(device->swap_buffer, min_size);
+		if (temp != NULL) {
+			device->swap_buffer = temp;
+			device->swap_buffer_size = min_size;
+			return 1; /* Success, realloc worked */
+		} else
+			return 0; /* Fail to realloc */
+	} else
+		return 1; /* Success, no need to realloc */
+}
+
+
+static void _buffer_zero(char *target,int och,int bytewidth,int ochannels,int bytes){
+  int i = och*bytewidth;
+  int stride = bytewidth*ochannels;
+  switch(bytewidth){
+  case 1:
+    while(i<bytes){
+      ((unsigned char *)target)[i] = 128; /* 8 bit PCM is unsigned in libao */
+      i+=stride;
+    }
+    break;
+  case 2:
+    while(i<bytes){
+      target[i] = 0;
+      target[i+1] = 0;
+      i+=stride;
+    }
+    break;
+  case 3:
+    while(i<bytes){
+      target[i] = 0;
+      target[i+1] = 0;
+      target[i+2] = 0;
+      i+=stride;
+    }
+    break;
+  case 4:
+    while(i<bytes){
+      target[i] = 0;
+      target[i+1] = 0;
+      target[i+2] = 0;
+      target[i+3] = 0;
+      i+=stride;
+    }
+    break;
+  }
+}
+
+static void _buffer_permute_swap(char *target,int och,int bytewidth,int ochannels,int bytes,
+                                 char *source,int ich, int ichannels){
+  int o = och*bytewidth;
+  int i = ich*bytewidth;
+  int ostride = bytewidth*ochannels;
+  int istride = bytewidth*ichannels;
+  switch(bytewidth){
+  case 2:
+    while(o<bytes){
+      target[o] = source[i+1];
+      target[o+1] = source[i];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  case 3:
+    while(o<bytes){
+      target[o] = source[i+2];
+      target[o+1] = source[i+1];
+      target[o+2] = source[i];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  case 4:
+    while(o<bytes){
+      target[o] = source[i+3];
+      target[o+1] = source[i+2];
+      target[o+2] = source[i+1];
+      target[o+3] = source[i];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  }
+}
+
+static void _buffer_permute(char *target,int och,int bytewidth,int ochannels,int bytes,
+                            char *source,int ich, int ichannels){
+  int o = och*bytewidth;
+  int i = ich*bytewidth;
+  int ostride = bytewidth*ochannels;
+  int istride = bytewidth*ichannels;
+  switch(bytewidth){
+  case 1:
+    while(o<bytes){
+      target[o] = source[i];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  case 2:
+    while(o<bytes){
+      target[o] = source[i];
+      target[o+1] = source[i+1];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  case 3:
+    while(o<bytes){
+      target[o] = source[i];
+      target[o+1] = source[i+1];
+      target[o+2] = source[i+2];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  case 4:
+    while(o<bytes){
+      target[o] = source[i];
+      target[o+1] = source[i+1];
+      target[o+2] = source[i+2];
+      target[o+3] = source[i+3];
+      o+=ostride;
+      i+=istride;
+    }
+    break;
+  }
+}
+
+
+#ifndef STRIP_PLUGINS
+/* Swap and copy the byte order of samples from the source buffer to
+   the target buffer. */
+static void _swap_samples(char *target_buffer, char* source_buffer,
+			  uint_32 num_bytes)
+{
+	uint_32 i;
+
+	for (i = 0; i < num_bytes; i += 2) {
+		target_buffer[i] = source_buffer[i+1];
+		target_buffer[i+1] = source_buffer[i];
+	}
+}
+#endif
+
+/* the channel locations we know right now. code below assumes U is in slot 0, X in 1, M in 2 */
+static char *mnemonics[]={
+  "X",
+  "M",
+  "L","C","R","CL","CR","SL","SR","BL","BC","BR","LFE",
+  "A1","A2","A3","A4","A5","A6","A7","A8","A9","A10",
+  "A11","A12","A13","A14","A15","A16","A17","A18","A19","A20",
+  "A21","A22","A23","A24","A25","A26","A27","A28","A29","A30",
+  "A31","A32",NULL
+};
+
+/* Check the requested matrix string for syntax and mnemonics */
+static char *_sanitize_matrix(int maxchannels, char *matrix, ao_device *device){
+  if(matrix){
+    char *ret = calloc(strlen(matrix)+1,1); /* can only get smaller */
+    char *p=matrix;
+    int count=0;
+    while(count<maxchannels){
+      char *h,*t;
+      int m=0;
+
+      /* trim leading space */
+      while(*p && isspace(*p))p++;
+
+      /* search for seperator */
+      h=p;
+      while(*h && *h!=',')h++;
+
+      /* trim trailing space */
+      t=h;
+      while(t>p && isspace(*(t-1)))t--;
+
+      while(mnemonics[m]){
+        if(t-p && !strncmp(mnemonics[m],p,t-p) &&
+           strlen(mnemonics[m])==t-p){
+          if(count)strcat(ret,",");
+          strcat(ret,mnemonics[m]);
+          break;
+        }
+        m++;
+      }
+      if(!mnemonics[m]){
+        /* unrecognized channel mnemonic */
+        {
+          int i;
+          aerror("Unrecognized channel name \"");
+          for(i=0;i<t-p;i++)fputc(p[i],stderr);
+          fprintf(stderr,"\" in channel matrix \"%s\"\n",matrix);
+        }
+        free(ret);
+        return NULL;
+      }else
+        count++;
+      if(!*h)break;
+      p=h+1;
+    }
+    return ret;
+  }else
+    return NULL;
+}
+
+static int _find_channel(int needle, char *haystack){
+  char *p=haystack;
+  int count=0;
+
+  /* X does not map to anything, including X! */
+  if(needle==0) return -1;
+
+  while(1){
+    char *h;
+    int m=0;
+
+    /* search for seperator */
+    h=p;
+    while(*h && *h!=',')h++;
+
+    while(mnemonics[m]){
+      if(!strncmp(mnemonics[needle],p,h-p) &&
+         strlen(mnemonics[needle])==h-p)break;
+      m++;
+    }
+    if(mnemonics[m])
+      return count;
+    count++;
+    if(!*h)break;
+    p=h+1;
+  }
+  return -1;
+}
+
+static char **_tokenize_matrix(char *matrix){
+  char **ret=NULL;
+  char *p=matrix;
+  int count=0;
+  while(1){
+    char *h,*t;
+
+    /* trim leading space */
+    while(*p && isspace(*p))p++;
+
+    /* search for seperator */
+    h=p;
+    while(*h && *h!=',')h++;
+
+    /* trim trailing space */
+    t=h;
+    while(t>p && isspace(*(t-1)))t--;
+
+    count++;
+    if(!*h)break;
+    p=h+1;
+  }
+
+  ret = calloc(count+1,sizeof(*ret));
+
+  p=matrix;
+  count=0;
+  while(1){
+    char *h,*t;
+
+    /* trim leading space */
+    while(*p && isspace(*p))p++;
+
+    /* search for seperator */
+    h=p;
+    while(*h && *h!=',')h++;
+
+    /* trim trailing space */
+    t=h;
+    while(t>p && isspace(*(t-1)))t--;
+
+    ret[count] = calloc(t-p+1,1);
+    memcpy(ret[count],p,t-p);
+    count++;
+    if(!*h)break;
+    p=h+1;
+  }
+
+  return ret;
+
+}
+
+static void _free_map(char **m){
+  char **in=m;
+  while(m && *m){
+    free(*m);
+    m++;
+  }
+  if(in)free(in);
+}
+
+static unsigned int _matrix_to_channelmask(int ch, char *matrix, char *premap, int **mout){
+  unsigned int ret=0;
+  char *p=matrix;
+  int *perm=(*mout=malloc(ch*sizeof(*mout)));
+  int i;
+  char **map = _tokenize_matrix(premap);
+
+  for(i=0;i<ch;i++) perm[i] = -1;
+  i=0;
+
+  while(1){
+    char *h=p;
+    int m=0;
+
+    /* search for seperator */
+    while(*h && *h!=',')h++;
+
+    while(map[m]){
+      if(h-p && !strncmp(map[m],p,h-p) &&
+         strlen(map[m])==h-p)
+        break;
+      m++;
+    }
+    /* X is a placeholder, X does not map to X */
+    if(map[m] && strcmp(map[m],"X")){
+      ret |= (1<<m);
+      perm[i] = m;
+    }
+    if(!*h)break;
+    p=h+1;
+    i++;
+  }
+
+  _free_map(map);
+  return ret;
+}
+
+static char *_channelmask_to_matrix(unsigned int mask, char *premap){
+  int m=0;
+  int count=0;
+  char buffer[257]={0};
+  char **map = _tokenize_matrix(premap);
+
+  while(map[m]){
+    if(mask & (1<<m)){
+      if(count)
+        strcat(buffer,",");
+      strcat(buffer,map[m]);
+      count++;
+    }
+    m++;
+  }
+  _free_map(map);
+  return _strdup(buffer);
+}
+
+static int _channelmask_bits(unsigned int mask){
+  int count=0;
+  while(mask){
+    if(mask&1)count++;
+    mask/=2;
+  }
+  return count;
+}
+
+static int _channelmask_maxbit(unsigned int mask){
+  int count=0;
+  int max=-1;
+  while(mask){
+    if(mask&1)max=count;
+    mask/=2;
+    count++;
+  }
+  return max;
+}
+
+static char *_matrix_intersect(char *matrix,char *premap){
+  char *p=matrix;
+  char buffer[257]={0};
+  int count=0;
+  char **map = _tokenize_matrix(premap);
+
+  while(1){
+    char *h=p;
+    int m=0;
+
+    /* search for seperator */
+    while(*h && *h!=',')h++;
+
+    while(map[m]){
+      if(h-p && !strncmp(map[m],p,h-p) &&
+         strlen(map[m])==h-p)
+        break;
+      m++;
+    }
+    /* X is a placeholder, X does not map to X */
+    if(map[m] && strcmp(map[m],"X")){
+      if(count)
+        strcat(buffer,",");
+      strcat(buffer,map[m]);
+      count++;
+    }
+
+    if(!*h)break;
+    p=h+1;
+  }
+
+  _free_map(map);
+  return _strdup(buffer);
+}
+
+static int ao_global_load_options(ao_option *options){
+  while (options != NULL) {
+    if(!strcmp(options->key,"debug")){
+      ao_global_dummy->verbose=2;
+    }else if(!strcmp(options->key,"verbose")){
+      if(ao_global_dummy->verbose<1)ao_global_dummy->verbose=1;
+    }else if(!strcmp(options->key,"quiet")){
+      ao_global_dummy->verbose=-1;
+    }
+
+    options = options->next;
+  }
+
+  return 0;
+
+}
+
+static int ao_device_load_options(ao_device *device, ao_option *options){
+
+  while (options != NULL) {
+    if(!strcmp(options->key,"matrix")){
+      /* If a driver has a static channel mapping mechanism
+         (physically constant channel mapping, or at least an
+         unvarying set of constants for mapping channels), the
+         output_matrix is already set.  An app/user specified
+         output mapping trumps. */
+      if(device->output_matrix)
+        free(device->output_matrix);
+      /* explicitly set the output matrix to the requested
+         string; devices must not override. */
+      device->output_matrix = _sanitize_matrix(32, options->value, device);
+      if(!device->output_matrix){
+        aerror("Empty or inavlid output matrix\n");
+        return AO_EBADOPTION;
+      }
+      adebug("Sanitized device output matrix: %s\n",device->output_matrix);
+    }else if(!strcmp(options->key,"debug")){
+      device->verbose=2;
+    }else if(!strcmp(options->key,"verbose")){
+      if(device->verbose<1)device->verbose=1;
+    }else if(!strcmp(options->key,"quiet")){
+      device->verbose=-1;
+    }else{
+      if (!device->funcs->set_option(device, options->key, options->value)) {
+        /* Problem setting options */
+        return AO_EOPENDEVICE;
+      }
+    }
+
+    options = options->next;
+  }
+
+  return 0;
+}
+
+/* Open a device.  If this is a live device, file == NULL. */
+static ao_device* _open_device(int driver_id, ao_sample_format *format,
+			       ao_option *options, FILE *file)
+{
+	ao_functions *funcs;
+	driver_list *driver;
+	ao_device *device=NULL;
+	int result;
+        ao_sample_format sformat=*format;
+        sformat.matrix=NULL;
+
+	/* Get driver id */
+	if ( (driver = _get_driver(driver_id)) == NULL ) {
+		errno = AO_ENODRIVER;
+		goto error;
+	}
+
+	funcs = driver->functions;
+
+	/* Check the driver type */
+	if (file == NULL &&
+	    funcs->driver_info()->type != AO_TYPE_LIVE) {
+
+		errno = AO_ENOTLIVE;
+		goto error;
+	} else if (file != NULL &&
+		   funcs->driver_info()->type != AO_TYPE_FILE) {
+
+		errno = AO_ENOTFILE;
+		goto error;
+	}
+
+	/* Make a new device structure */
+	if ( (device = _create_device(driver_id, driver,
+				      format, file)) == NULL ) {
+		errno = AO_EFAIL;
+		goto error;
+	}
+
+	/* Initialize the device memory; get static channel mapping */
+	if (!funcs->device_init(device)) {
+		errno = AO_EFAIL;
+		goto error;
+	}
+
+	/* Load options */
+        errno = ao_device_load_options(device,ao_global_options);
+        if(errno) goto error;
+        errno = ao_device_load_options(device,options);
+        if(errno) goto error;
+
+        /* also sanitize the format input channel matrix */
+        if(format->matrix){
+          sformat.matrix = _sanitize_matrix(format->channels, format->matrix, device);
+          if(!sformat.matrix)
+            awarn("Input channel matrix invalid; ignoring.\n");
+
+          /* special-case handling of 'M'. */
+          if(sformat.channels==1 && sformat.matrix && !strcmp(sformat.matrix,"M")){
+            free(sformat.matrix);
+            sformat.matrix=NULL;
+          }
+        }
+
+        /* If device init was able to declare a static channel mapping
+           mechanism, reconcile it to the input now.  Odd drivers that
+           need to communicate with a backend device to determine
+           channel mapping strategy can still bypass this mechanism
+           entirely.  Also, drivers like ALSA may need to adjust
+           strategy depending on what device is successfully opened,
+           etc, but this still saves work later. */
+
+        if(device->output_matrix && sformat.matrix){
+          switch(device->output_matrix_order){
+          case AO_OUTPUT_MATRIX_FIXED:
+            /* Backend channel ordering is immutable and unused
+               channels must still be sent.  Look for the highest
+               channel number we are able to map from the input
+               matrix. */
+            {
+              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
+                                                         device->output_matrix,
+                                                         &device->input_map);
+              int max = _channelmask_maxbit(mask);
+              if(max<0){
+                aerror("Unable to map any channels from input matrix to output");
+                errno = AO_EBADFORMAT;
+                goto error;
+              }
+              device->output_channels = max+1;
+              device->output_mask = mask;
+              device->inter_matrix = _strdup(device->output_matrix);
+            }
+            break;
+
+          case AO_OUTPUT_MATRIX_COLLAPSIBLE:
+            /* the ordering of channels submitted to the backend is
+               fixed, but only the channels in use should be present
+               in the audio stream */
+            {
+              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
+                                                         device->output_matrix,
+                                                         &device->input_map);
+              int channels = _channelmask_bits(mask);
+              if(channels<0){
+                aerror("Unable to map any channels from input matrix to output");
+                errno = AO_EBADFORMAT;
+                goto error;
+              }
+              device->output_channels = channels;
+              device->output_mask = mask;
+              device->inter_matrix = _channelmask_to_matrix(mask,device->output_matrix);
+            }
+            break;
+
+          case AO_OUTPUT_MATRIX_PERMUTABLE:
+            /* The ordering of channels is freeform.  Only the
+               channels in use should be sent, and they may be sent in
+               any order.  If possible, leave the input ordering
+               unchanged */
+            {
+              unsigned int mask = _matrix_to_channelmask(sformat.channels,sformat.matrix,
+                                                         device->output_matrix,
+                                                         &device->input_map);
+              int channels = _channelmask_bits(mask);
+              if(channels<0){
+                aerror("Unable to map any channels from input matrix to output");
+                errno = AO_EBADFORMAT;
+                goto error;
+              }
+              device->output_channels = channels;
+              device->output_mask = mask;
+              device->inter_matrix = _matrix_intersect(sformat.matrix,device->output_matrix);
+            }
+            break;
+
+          default:
+            aerror("Driver backend failed to set output ordering.\n");
+            errno = AO_EFAIL;
+            goto error;
+          }
+
+        }else{
+          device->output_channels = sformat.channels;
+        }
+
+        /* other housekeeping */
+        device->input_channels = sformat.channels;
+        device->bytewidth = (sformat.bits+7)>>3;
+        device->rate = sformat.rate;
+
+	/* Open the device */
+	result = funcs->open(device, &sformat);
+	if (!result) {
+          errno = AO_EOPENDEVICE;
+          goto error;
+	}
+
+        /* set up permutation based on finalized inter_matrix mapping */
+        /* The only way device->output_channels could be zero here is
+           if the driver has opted to ouput no channels (eg, the null
+           driver). */
+        if(sformat.matrix){
+          if(!device->inter_matrix){
+            awarn("Driver %s does not support automatic channel mapping;\n"
+                 "\tRouting only L/R channels to output.\n\n",
+                 info_table[device->driver_id]->short_name);
+            device->inter_matrix=_strdup("L,R");
+          }
+          {
+
+            /* walk thorugh the inter matrix, match channels */
+            char *op=device->inter_matrix;
+            int count=0;
+            device->inter_permute = calloc(device->output_channels,sizeof(int));
+
+            adebug("\n");
+
+            while(count<device->output_channels){
+              int m=0,mm;
+              char *h=op;
+
+              if(*op){
+                /* find mnemonic offset of inter channel */
+                while(*h && *h!=',')h++;
+                while(mnemonics[m]){
+                  if(!strncmp(mnemonics[m],op,h-op))
+                    break;
+                  m++;
+                }
+                mm=m;
+
+                /* find match in input if any */
+                device->inter_permute[count] = _find_channel(m,sformat.matrix);
+                if(device->inter_permute[count] == -1 && sformat.channels == 1){
+                  device->inter_permute[count] = _find_channel(1,sformat.matrix);
+                  mm=1;
+                }
+              }else
+                device->inter_permute[count] = -1;
+
+              /* display resulting mapping for now */
+              if(device->inter_permute[count]>=0){
+                adebug("input %d (%s)\t -> backend %d (%s)\n",
+                       device->inter_permute[count], mnemonics[mm],
+                       count,mnemonics[m]);
+              }else{
+                adebug("             \t    backend %d (%s)\n",
+                       count,mnemonics[m]);
+              }
+              count++;
+              op=h;
+              if(*h)op++;
+            }
+            {
+              char **inch = _tokenize_matrix(sformat.matrix);
+              int i,j;
+              int unflag=0;
+              for(j=0;j<sformat.channels;j++){
+                for(i=0;i<device->output_channels;i++)
+                  if(device->inter_permute[i]==j)break;
+                if(i==device->output_channels){
+                  adebug("input %d (%s)\t -> none\n",
+                         j,inch[j]);
+                  unflag=1;
+                }
+              }
+              _free_map(inch);
+              if(unflag)
+                awarn("Some input channels are unmapped and will not be used.\n");
+            }
+            averbose("\n");
+
+          }
+        }
+
+        /* if there's no actual permutation to do, release the permutation vector */
+        if(device->inter_permute && device->output_channels == device->input_channels){
+          int i;
+          for(i=0;i<device->output_channels;i++)
+            if(device->inter_permute[i]!=i)break;
+          if(i==device->output_channels){
+            free(device->inter_permute);
+            device->inter_permute=NULL;
+          }
+        }
+
+	/* Resolve actual driver byte format */
+	device->driver_byte_format =
+		_real_byte_format(device->driver_byte_format);
+
+	/* Only create swap buffer if needed */
+        if (device->bytewidth>1 &&
+            device->client_byte_format != device->driver_byte_format){
+          adebug("swap buffer required:\n");
+          adebug("  machine endianness: %d\n",ao_is_big_endian());
+          adebug("  device->client_byte_format:%d\n",device->client_byte_format);
+          adebug("  device->driver_byte_format:%d\n",device->driver_byte_format);
+        }
+
+	if ( (device->bytewidth>1 &&
+              device->client_byte_format != device->driver_byte_format) ||
+             device->inter_permute){
+
+          result = _realloc_swap_buffer(device, DEF_SWAP_BUF_SIZE);
+
+          if (!result) {
+
+            if(sformat.matrix)free(sformat.matrix);
+            device->funcs->close(device);
+            device->funcs->device_clear(device);
+            free(device);
+            errno = AO_EFAIL;
+            return NULL; /* Couldn't alloc swap buffer */
+          }
+	}
+
+	/* If we made it this far, everything is OK. */
+        if(sformat.matrix)free(sformat.matrix);
+	return device;
+
+ error:
+        {
+          int errtemp = errno;
+          if(sformat.matrix)
+            free(sformat.matrix);
+          ao_close(device);
+          errno=errtemp;
+        }
+        return NULL;
+}
+
+
+/* ---------- Public Functions ---------- */
+
+/* -- Library Setup/Teardown -- */
+
+static ao_info ao_dummy_info=
+  { 0,0,0,0,0,0,0,0,0 };
+static ao_info *ao_dummy_driver_info(void){
+  return &ao_dummy_info;
+}
+static ao_functions ao_dummy_funcs=
+  { 0, &ao_dummy_driver_info, 0,0,0,0,0,0,0};
+
+void ao_initialize(void)
+{
+	driver_list *end;
+        ao_global_dummy = &ao_global_dummy_storage;
+        ao_global_dummy->funcs = &ao_dummy_funcs;
+
+	/* Read config files */
+	ao_read_config_files(&config);
+        ao_global_load_options(ao_global_options);
+
+	if (driver_head == NULL) {
+		driver_head = _load_static_drivers(&end);
+		_append_dynamic_drivers(end);
+	}
+
+	/* Create the table of driver info structs */
+	info_table = _make_info_table(&driver_head, &driver_count);
+}
+
+void ao_shutdown(void)
+{
+	driver_list *driver = driver_head;
+	driver_list *next_driver;
+
+	if (!driver_head) return;
+
+	/* unload and free all the drivers */
+	while (driver) {
+		if (driver->handle) {
+#ifndef STRIP_PLUGINS
+		  dlclose(driver->handle);
+#endif
+		  free(driver->functions); /* DON'T FREE STATIC FUNC TABLES */
+		}
+		next_driver = driver->next;
+		free(driver);
+		driver = next_driver;
+	}
+
+    free(info_table);
+
+        _clear_config();
+	/* NULL out driver_head or ao_initialize() won't work */
+	driver_head = NULL;
+}
+
+
+/* -- Device Setup/Playback/Teardown -- */
+int ao_append_option(ao_option **options, const char *key, const char *value)
+{
+	ao_option *op, *list;
+
+	op = calloc(1,sizeof(ao_option));
+	if (op == NULL) return 0;
+
+	op->key = _strdup(key);
+	op->value = _strdup(value?value:"");
+	op->next = NULL;
+
+	if ((list = *options) != NULL) {
+		list = *options;
+		while (list->next != NULL) list = list->next;
+		list->next = op;
+	} else {
+		*options = op;
+	}
+
+
+	return 1;
+}
+
+int ao_append_global_option(const char *key, const char *value)
+{
+  return ao_append_option(&ao_global_options,key,value);
+}
+
+void ao_free_options(ao_option *options)
+{
+	ao_option *rest;
+
+	while (options != NULL) {
+		rest = options->next;
+		free(options->key);
+		free(options->value);
+		free(options);
+		options = rest;
+	}
+}
+
+
+ao_device *ao_open_live (int driver_id, ao_sample_format *format,
+			ao_option *options)
+{
+	return _open_device(driver_id, format, options, NULL);
+}
+
+
+ao_device *ao_open_file (int driver_id, const char *filename, int overwrite,
+			 ao_sample_format *format, ao_option *options)
+{
+	FILE *file;
+	ao_device *device;
+
+	if (strcmp("-", filename) == 0)
+		file = stdout;
+	else {
+
+		if (!overwrite) {
+			/* Test for file existence */
+			file = fopen(filename, "r");
+			if (file != NULL) {
+				fclose(file);
+				errno = AO_EFILEEXISTS;
+				return NULL;
+			}
+		}
+
+
+		file = fopen(filename, "w");
+	}
+
+
+	if (file == NULL) {
+		errno = AO_EOPENFILE;
+		return NULL;
+	}
+
+	device = _open_device(driver_id, format, options, file);
+
+	if (device == NULL) {
+		fclose(file);
+		/* errno already set by _open_device() */
+		return NULL;
+	}
+
+	return device;
+}
+
+
+int ao_play(ao_device *device, char* output_samples, uint_32 num_bytes)
+{
+	char *playback_buffer;
+
+	if (device == NULL)
+	  return 0;
+
+	if (device->swap_buffer != NULL) {
+          int out_bytes = num_bytes*device->output_channels/device->input_channels;
+          if (_realloc_swap_buffer(device, out_bytes)) {
+            int i;
+            int swap = (device->bytewidth>1 &&
+                        device->client_byte_format != device->driver_byte_format);
+            for(i=0;i<device->output_channels;i++){
+              int ic = device->inter_permute ? device->inter_permute[i] : i;
+              if(ic==-1){
+                _buffer_zero(device->swap_buffer,i,device->bytewidth,device->output_channels,
+                             out_bytes);
+              }else if(swap){
+                _buffer_permute_swap(device->swap_buffer,i,device->bytewidth,device->output_channels,
+                                     out_bytes, output_samples, ic, device->input_channels);
+              }else{
+                _buffer_permute(device->swap_buffer,i,device->bytewidth,device->output_channels,
+                                out_bytes, output_samples, ic, device->input_channels);
+              }
+            }
+            playback_buffer = device->swap_buffer;
+            num_bytes = out_bytes;
+          } else
+            return 0; /* Could not expand swap buffer */
+	} else
+          playback_buffer = output_samples;
+
+	return device->funcs->play(device, playback_buffer, num_bytes);
+}
+
+
+int ao_close(ao_device *device)
+{
+	int result;
+
+	if (device == NULL)
+		result = 0;
+	else {
+		result = device->funcs->close(device);
+		device->funcs->device_clear(device);
+
+		if (device->file) {
+			fclose(device->file);
+			device->file = NULL;
+		}
+
+		if (device->swap_buffer != NULL)
+			free(device->swap_buffer);
+                if (device->output_matrix != NULL)
+                        free(device->output_matrix);
+                if (device->input_map != NULL)
+                        free(device->input_map);
+                if (device->inter_matrix != NULL)
+                        free(device->inter_matrix);
+                if (device->inter_permute != NULL)
+                        free(device->inter_permute);
+		free(device);
+	}
+
+	return result;
+}
+
+
+/* -- Driver Information -- */
+
+int ao_driver_id(const char *short_name)
+{
+	int i;
+	driver_list *driver = driver_head;
+
+	i = 0;
+	while (driver) {
+		if (strcmp(short_name,
+			   driver->functions->driver_info()->short_name) == 0)
+			return i;
+		driver = driver->next;
+		i++;
+	}
+
+	return -1; /* No driver by that name */
+}
+
+
+int ao_default_driver_id (void)
+{
+	/* Find the default driver in the list of loaded drivers */
+
+	return _find_default_driver_id(config.default_driver);
+}
+
+
+ao_info *ao_driver_info(int driver_id)
+{
+	driver_list *driver;
+
+	if ( (driver = _get_driver(driver_id)) )
+		return driver->functions->driver_info();
+	else
+		return NULL;
+}
+
+
+ao_info **ao_driver_info_list(int *count)
+{
+	*count = driver_count;
+	return info_table;
+}
+
+
+/* -- Miscellaneous -- */
+
+/* Stolen from Vorbis' lib/vorbisfile.c */
+int ao_is_big_endian(void)
+{
+	static uint_16 pattern = 0xbabe;
+	return 0[(volatile unsigned char *)&pattern] == 0xba;
+}
diff --git a/libao/src/src/config.c b/libao/src/src/config.c
new file mode 100644
index 0000000..9693730
--- /dev/null
+++ b/libao/src/src/config.c
@@ -0,0 +1,111 @@
+/*
+ *
+ *  config.c
+ *
+ *       Copyright (C) Stan Seibert - July 2000
+ *       Copyright (C) Monty - Mar 2010
+ *
+ *  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
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  libao is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GNU Make; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ********************************************************************
+
+ last mod: $Id: config.c 17763 2010-12-17 11:28:29Z xiphmont $
+
+ ********************************************************************/
+
+#include "ao/ao.h"
+#include "ao/ao_private.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+
+#define LINE_LEN 100
+
+static char *trim(char *p){
+  char *t;
+  while(*p && isspace(*p))p++;
+  if(*p){
+    t=p+strlen(p);
+    while(t>p && isspace(*(t-1))){
+      t--;
+      *t='\0';
+    }
+  }
+  return p;
+}
+
+static int ao_read_config_file(ao_config *config, const char *config_file)
+{
+	FILE *fp;
+	char line[LINE_LEN];
+	int end;
+
+	if ( !(fp = fopen(config_file, "r")) )
+		return 0; /* Can't open file */
+
+	while (fgets(line, LINE_LEN, fp)) {
+		/* All options are key=value */
+
+		if (strncmp(line, "default_driver=", 15) == 0) {
+			free(config->default_driver);
+			end = strlen(line);
+			if (line[end-1] == '\n')
+				line[end-1] = 0; /* Remove trailing newline */
+
+			config->default_driver = _strdup(line+15);
+		}else{
+                        /* entries in the config file that don't parse as
+                           directives to AO at large are treated as driver
+                           options */
+                        char *key=trim(line);
+                        if(key && *key){
+                          char *val=strchr(key,'=');
+                          if(val){
+                            *val='\0';
+                            val++;
+                          }
+                          ao_append_global_option(key,val);
+                        }
+                }
+	}
+
+	fclose(fp);
+
+	return 1;
+}
+
+void ao_read_config_files (ao_config *config)
+{
+	char userfile[FILENAME_MAX+1];
+	char *homedir = getenv("HOME");
+
+	/* Read the system-wide config file */
+	ao_read_config_file(config, AO_SYSTEM_CONFIG);
+
+	/* Read the user config file */
+	if ( homedir!=NULL &&
+	     strlen(homedir) <= FILENAME_MAX - strlen(AO_USER_CONFIG) )
+	{
+		strncpy(userfile, homedir, FILENAME_MAX);
+		strcat(userfile, AO_USER_CONFIG);
+		ao_read_config_file(config, userfile);
+	}
+}
+
-- 
cgit v1.2.3